Giter VIP home page Giter VIP logo

hx's Issues

How-to contains misleading memo use

(defnc WrappedComponent [{:keys [someValue]}]
  ;; This options map is parsed at compile time to expand to the above
  ;; It's the same way you can pass in `:pre` and `:post` checks for
  ;; `defn` (and likewise, `defnc`).
  {:wrap [(some-lib/withSomeValue)
          (react/memo =)]}
  ;; Return hiccup
  [:div "I was rendered with " someValue])

the memo comparator should not be = but something more like (fn [x y] (= (js->clj x) (js->clj y))). The result of clj->js is what's passed to the comparator, and cljs never compares them as truthy.

Props with numbers in are dropped or truncated

Props that contain numbers that get passed to components defined with defnc end up going missing or having the numbers truncated.

For example - the test component below never receives a value for :x1, and receives a value for :test rather than :test2

(defnc Test
  [opts]
  (println opts)
  [:div])

[Test {:x1 0 :test2 1}]  => {: 0 :test 1 :class nil}

You can also see this if you call (hx.react/props->clj #js {"x0" 1}) directly.

I think this is because of the implementation of camel->kebab.

Semantics and API of <-state

I'm creating this issue to capture the discussion that has been happening across other issues and PRs around the <-state hook.

To summarize:

Currently, <-state returns an object that implements the IDeref / IReset / ISwap interfaces, allowing it to be used similar to how Clojure(Script)atoms are used.

This feels very familiar to me and many others because this is the primary way that Reagent provided state management.

However, there are several conflicts when trying to apply atom semantics to React's state management which all revolve around the fact that React doesn't apply state updates synchronously.

Issues that this brings in:

  1. Currently, we have a custom type that provides a thin implementation of the protocols on top of React's useState directly. This has been brought up (#38, #11) that it violates the expectations one has for calling swap! and then dereferencing in the same tick.

  2. If we adopt atom semantics whole-hog (e.g. actually use an atom and use add-watch), then we create circumstances where our atom state and React's state can diverge.

A simple example of this divergence I've taken from Dan Abramov's blog post The Complete Guide to useEffect:

(hx/defnc StateWithEffect [{:keys [receive]}]
  (let [count (hooks/<-state 0)]
    (hooks/<-effect
     (fn []
       (js/setTimeout
        (fn []
          (prn @count))
        3000)
       js/undefined))
    [:div {:on-click #(swap! count inc)}
     @count]))

Clicking this 5 times in a row, will give different results depending on if <-state return value is updated synchronously vs. asynchronously.

This problem gets worse when Concurrent React lands.

I think that this is due to a fundamental mismatch between the way we have handled state in the past, and how React wants to handle managing our state and doing computations. I am still in the process of grokking how React Hooks work and the concepts behind them, but this is what I understand so far:

React wants to own the scheduling of our application. This means that we tell React the what and the how, and React takes care of the when.

This is especially true for renders, but React wants to schedule computing state as well. This is something that I have only just understood. An example:

(def lifecycle (atom 0))

(hx/defnc WhenApplied [_]
  (reset! lifecycle :rendering)
  (let [count (hx.hooks/<-state 0)]
    (reset! lifecycle nil)
    [:div {:on-click #(swap! count (fn update [n]
                                     (prn "update:" @lifecycle)
                                     (inc n)))}
     @count]))

We notice that after the first click (not sure why this doesn't apply to the first one), the update fn is run during the :rendering phase; specifically when the corresponding useState hook is called.

What this means is that when Concurrent React is in full effect, the state computation will be scheduled alongside the accompanying render based on the priority of the dispatch. E.g. the state updates from a user typing in an input field might be applied before the state updates of a websocket connection, even though the typing events fired after the websocket events.

I tried to setup a simple example. It's not super powerful, but if you try it can illustrate the point:

(def schedule (atom :high))

(hx/defnc Scheduler [_]
  (let [updates (hooks/<-state [])]
    [:div
     [:div "Updates: " (prn-str @updates)]
     [:div
      [:input
       {:on-change (fn update []
                     (case @schedule
                       :low (do
                              (reset! schedule :high)
                              (scheduler/unstable_scheduleCallback
                               #(swap! updates conj :low)))
                       :high (do
                               (reset! schedule :low)
                               (swap! updates conj :high))))}]]
     [:div [:button {:on-click #(reset! updates [])} "reset"]]]))

(react-dom/render
  (hx/f [react/unstable_ConcurrentMode
         [Scheduler]]))

This will alternate between high and low scheduling priorities. If you type REALLY REALLY fast in order to get the page to start dropping frames, you can get multiple :high updates in a row. This is because React is prioritizing those updates over the :low ones when performance starts to degrade.

This means that we have to do one of two things if we want to adopt atom semantics for <-state hook:

  1. Short circuit React's scheduler so that our updates are always the same priority.

  2. Risk that our atom state and React's state get out of sync

If we do number 1, then we can never rise above Reagent/Rum's async-always behavior. If we do number 2... we can't do number 2 😝that's just a bug.

This is why I believe the best course of action is to... not use atoms or the IDeref / IReset / ISwap protocols. At this point I think that React has hit a pretty good sweet spot by just returning a tuple [state set-state] that can be re-named by the consumer.

Anyway, those are my thoughts. Let's continue the discussion here!

Enforcing "Rules of Hooks"

Per the React docs:

Only Call Hooks at the Top Level

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls. (If you’re curious, we’ll explain this in depth below.)

Only Call Hooks from React Functions

Don’t call Hooks from regular JavaScript functions. Instead, you can:

✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks (we’ll learn about them on the next page).
By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

The React team has released an eslint plugin that helps enforce these rules.

I think it would be interesting to see how we could help CLJS developers follow these same conventions.

Here are some considerations:

  • It's better to make it easy to do the right thing, then hard to do the wrong thing
  • We want to have similar (highly prefer the same) ergonomics for code that uses hx and foreign code (e.g. npm libraries, CLJS libs that don't use hx)
  • We want to make sure that we don't break code that doesn't use hx 😅

My initial thought was a hooks macro that was similar to let, but to enforce that hooks can't be used outside of that macro, detect if hooks are being used in loops, etc.

We could do some silly things, like:

  • Patch React.useState, React.useEffect etc. to only work if inside a hooks block.
    This would break any external libs trying to use Hooks 😛
  • Enforce it only for Hooks using the hx.hooks namespace
    This would have inconsistent behavior with 3rd party code

Perhaps having it be purely syntax level would be best: e.g. it looks for either <- or use at the beginning of the symbol name, then enforces the top-level rules of hooks.

I'm not sure how we would enforce that Hooks must only be used in React component functions or custom Hooks in this case.

Posting this issue here to collect thoughts!

CI failed with incompatible module

The last CI build failed with the error:

#!/bin/sh -eo pipefail
yarn install

yarn install v1.9.4
info No lockfile found.
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/4] Resolving packages...
[2/4] Fetching packages...
error [email protected]: The engine "node" is incompatible with this module. Expected version ">=8.10".
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
Exited with code 1

weird closing over <-state with <-effect

  (let [state (<-state {:log [{:foo ["bar" "baz"]
                               :bar {:baz 42}}]
                        :history []
                        :current {:foo ["bar" "baz"]
                                  :bar {:baz 42}}
                        :next {:coll nil
                               :k nil
                               :v nil}})
        tap-fn (fn [x]
                 (swap! state update :log conj x))]
    ;; add tap listener
    (<-effect (fn []
                (println "Adding tap")
                (add-tap tap-fn)
                (fn []
                  (printlin "removing tap")
                  (remove-tap tap-fn)))
              [state])

Helper for HoC

Right now, creating components that need to be wrapped in HOC (especially multiple HOC) is a bit cumbersome.

See https://github.com/Lokeh/hx/blob/master/examples/workshop/sortable.cljs and https://github.com/Lokeh/hx/blob/master/examples/workshop/react_dnd.cljs for examples.

I could imagine an API similar to:

(hx/defnc DraggableBox [{:keys [connect-drag-source top left text] :as props}]
  ;; key `:wrap` defines a vector of HoCs to wrap the component in
  {:hx/wrap [(dnd/DragSource "box"
                       box-spec
                       ;; this maps the react-dnd context to props for our
                       ;; component
                       (fn [connect]
                         #js {:connectDragSource (. connect dragSource)}))]}
  ;; render body
  (connect-drag-source
   (hx/f [:div {:style {:top top
                        :left left
                        :position "absolute"
                        :border "1px solid #333"}}
          text])))

The defnc macro could define two vars in the call site: DraggableBox which is the wrapped component, and DraggableBox_Render which is the non-wrapped component as written in the body of the defnc macro.

With the Hooks proposal gaining such momentum and mindshare, this might eventually be an unneeded enhancement. In the meantime, many React libraries are implemented as a collection of HoCs, so it might be smart to introduce this and then deprecate it once Hooks has been released in a stable version of React.

Destructuring defnc :keys [class] has weird behaviour

(defnc MyComponent[{:keys [variant class-name class]
                       :or {variant :down class "foo" class-name "bar"}}]
  (println "class" (if class class "CLASS NOT TRUTHY"))
  (println "classname" (if class-name class-name "CLASSNAME NOT TRUTHY"))

[:div "something"])

When invoking the above code like:

[MyComponent {:variant :up}]

The following is printed:

class CLASS NOT TRUTHY
classname bar

But when invoking it with:

[MyComponent {:class "hx-rocks"}]
class hx-rocks
classname hx-rocks

It seems that :class is set unconditionally to nil in that map, so that the keys destructuring doesn't work. I made this small repro using plain ClojureScript to make sure:

(defn TEST [{:keys [a b] :or {a 1 b 2}}]
  (println "A" a "B" b))

(TEST {:a nil})

This prints: A nil B 2.

hx/f exceptions handlint

when passing a nil value map {nil nil} (eg, when using select-keys with and the props have not been populated) with hx/f a doesn't support namespaces error occurs

Make it fast

Thomas Heller setup a super simple benchmark that compares hx and some other wrapper libs. hx is significantly behind the pack:

react x 89,450 ops/sec ±3.99% (84 runs sampled)
reagent x 49,954 ops/sec ±2.25% (89 runs sampled)
hx x 8,489 ops/sec ±5.66% (79 runs sampled)

This is with a few simple perf tweaks (memoizing props processing), I can get it to about 13-6,000 ops/sec. This is still really bad.

My goal would to see hx at least as fast as reagent.

Question marks in props are dropped

Usage:

[MyComponent {:is-fancy? true}]

Result prop is:

{:is-fancy true}

This seems to have been an issue before, I wonder if there could be a better way to pass in Clojure keywords without munging them at all, as probably edge cases will always be there.

Since JS hashes accept string keys, "is-fancy?" should be a perfectly fine prop key. The cost of removing this munging is that most native React elements will have to be manually typed as camelCase but I think that's fine (and makes it easier to see in the code where you're doing interop vs your own components).

Thoughts?

React `createContext` wrapper

Are there any plans to add wrappers for things such as createContext (similar to the dummy wrappers in hx.hooks such as <-reducer)?

It would be nice to do some Clojure wrapping to for easily getting out the Consumer and Provider by key.

swap! on a <-state atom behaves differently from useState

I wasn't sure exactly how to explain this - it was an issue that came up as I was trying to implement drag and drop and had quite a lot of event handlers all over the place.

I've done my best to make a minimal reproduction, hope it's not too vague!

The component below sets up a timer which increments a counter.
The raw react version increments the number on every tick, it calls the version of setNum that takes a function. The hx version only increments once, but doesn't continue to increment, I think because it is holding a reference to the initial state.

(defnc Counter
  [opts]
  (let [num-hx (<-state 1)
        [num setNum] (react/useState 1)]
    (react/useEffect (fn []
                       (let [id (js/setInterval #(swap! num-hx inc) 1000)]
                         (fn []
                           (js/clearInterval id)))) #js [])
    (react/useEffect (fn []
                       (let [id (js/setInterval #(setNum inc) 1000)]
                         (fn []
                           (js/clearInterval id)))) #js [])
    [:div
     [:span @num-hx]
     [:span "/"]
     [:span num]]))

should provide sugar for using React/memo with defnc

I get that you're trying to provide a "close to the (mental) metal" wrapper around React, but one of the nice things about working in clojure and with clojure data structures with React is that we can take advantage of their immutability to control re-rendering, as with rum's rum/static mixin for shouldComponentUpdate. The functional component equivalent of this is React.memo, a higher-order component for wrapping functional components to only re-render them when the arguments pass a shallow equality test, which I think will suit the nature of working with react from clojure.

I don't know what you'd consider this to look like, perhaps defncs or maybe defstatic, but it would be nice to not have to do this wrapping manually.

Add displayName to defnc components

I was using the react dev tools in Chrome and noticed that components used the munged clojurescript function name, which is not that pretty.

Turns out you can set a displayName attribute and React will use that instead. Since defnc is a macro, we have access to the original name and namespace, so therefore you can do:

(let [...
       namespace (str *ns*)]
`(do
   (defn ~name ... )
   (set! (.-displayName ~name) (str ~namespace "/" '~name)))

I'm not 100% sure yet if this will work nicely with release builds, but I'm opening an issue to see if you would be willing to accept this. If yes, I'll investigate properly and make a PR. I also wanted to look into propTypes since they use the same mechanism.

Passing down original js props in render props does not work with js->clj

In attempt to translate material-ui autocomplete. passing props from render-prop function down will break with a Error: Doesn't support namespace: ref error
Consider translating the following component to hx

<Autocomplete
  options={top100Films}
  getOptionLabel={option => option.title}
  style={{ width: 300 }}
  renderInput={params => (
    <TextField {...params} label="Combo box" variant="outlined" fullWidth />
  )}
/>
(defnc HeaderAutocomplete [__]
       (let [renderInput (fn [params]
                           (hx/f [TextField (js->clj params)]))]
       [Autocomplete {:id "autocomplete"
                      :options (clj->js options)
                      :renderInput renderInput
                      :getOptionLabel (fn [elem]
                                        (:title elem))
                      }]))

That will throw Error: Doesn't support namespace: ref .
The workaround was using clj-bean as so :

(defnc HeaderAutocomplete [__]
       (let [renderInput (fn [params]
                           (hx/f [TextField (merge {:fullWidth true
                                                    :variant "outlined"} (bean params) )]))]
       [Autocomplete {:id "autocomplete"
                      :options (->js options)
                      :renderInput renderInput
                      :getOptionLabel (fn [elem]
                                        (:title (bean elem) ))
                      }]))

note Im using bean and not ->clj since it seems that if you recursively convert the whole object it wont work. in fact i was only able to change inputProps prop, by merging with js directly using Object.assign like this :


:inputProps (.assign js/Object inputProps-clj (->js { :onChange #(updateVal (-> % .-target .-value))
                                                                                                                        :value selected-value}))

where inputProps-clj is :

(let [params-clj (bean params)
                                 inputProps-clj (:inputProps params-clj)

`defcomponent` API is very confusing

defcomponent requires the first function to behave like a constructor but it doesn't check its name and argument list.
At the same time, React itself does not require an explicit constructor for class components.

CLJ render-to-string

I'm a bit wary to support this but I see it's benefits, especially when wanting to play with component trees at a REPL.

I honestly think that Node.js will eventually have a much better story once SSR Suspense hits, but in the meantime this can cover a number of use cases.

The trick will be making sure that CLJ rendering == Node.js rendering, and supporting hooks.

Functional components can't be specced

Because functional components are expected to take in a JavaScript object as props, and return a React Element, it is not currently possible to write a spec for them.

Push missing tags + maybe a 0.5.4 release

Besides the tags it also seems that the 0.5.3 release that's on Clojars might be a mishap. It's not documented in the changelog and it contains a hx/hiccup/tag.cljc file that requires goog.obj instead of goog.object resulting in analyzer errors.

track dependencies to selectively rerender with useMemo

Hey @Lokeh JS dev here, just started learning Clojure. I appreciate your work in integrating JS/react tools, and just now read your "when-is-immutability-fast" article.

Regarding your "wrapping all of our components in React.memo" comment in the article, I also thought about this when learning about macros. I like the idea of taking advantage of Clojure so that we can stop thinking about performance and focus on the UI. The concern seems to be that not every component needs this optimization - but wouldn't it be possible to track dependencies, and only apply the useMemo hook where it's necessary?

JS tools like mobx provide this rendering magic via proxies, but since macros give control over code+data this optimization could be done via react itself without having to add another dependency.

Just started learning Clojure/macros of course, so this is all high level for me still, would be great to hear your thoughts! Thanks

Keys syntax suggestion

It would have been easier if we had
(hx/defnc HasChildren [children]
instead of
(hx/defnc HasChildren [{:keys [children]}]

Export hooks under Clojure-style names

I'm pretty curious why hooks are exported in camelCase instead of, typical for Clojure, kebab-case? Since hx is Clojure(Script) lib it seems like kebab-case would be more "natural"?

Improved react dev-tools support for hooks

Opening this to start a discussion going, but it seems it's not going to be an easy one.

React dev-tools supports introspecting the props and hooks of a component. Props work relatively well, but unfortunately, hx hooks look a little bit opaque:

2019-03-14 at 7 46 AM

Observations:

  1. All the names are the same.
  2. The first State hook is a CLJS map, but it renders as "...". This could be fixed by using useDebugValue inside <-state, to do custom formatting (pr-str would be an easy first step).

There's more to research here, as even using React/useState with a JS object doesn't show any value.

Why shallow-clj->js?

It would be nice to not have to call clj->js myself when passing in values to React components.
I assume shallow-clj->js is just a performance optimization? How significant is it?
I've found myself several times now wanting to pass a Clojure object into a React component and having to wrap it in a clj->js.

Race condition issue with <-deref

The more I use hx, the more I like it. Thanks so much!

I ran across a baffling race condition when using <-deref. I haven't created a repro yet, but as far as I can tell, it goes like this:

  1. Setup some top-level atom
  2. Kick off a network request that will eventually swap! into that atom.
  3. Render a component that uses <-deref on that atom.
  4. Component is rendered using the current state
  5. Network request comes back, updates the atom <--- MISSED UPDATE
  6. useEffect is called to add a watch to the atom

If steps 5 and 6 are swapped (because of a slower network etc) then everything works fine.

I worked around this issue by adding an extra call to setState after the watch is added. This might lead to an unnecessary render but I'm not sure.

It seems that useEffect is called asynchronously after rendering is done, and that is probably the source of the race condition.

class & className issue when wrapping defnc component with pure react component

Hi again :)

I just ran into another issue with class & className (based on hx 0.4):

At various places, I'm wrapping some of my defnc components with react-bootstrap "Collapse" components.

The bootstrap collapse component will pass in an extra "className" attribute to my component, which I have to stick to my top-level div.

Example:

;; ... snip ... wrapping looks like:
[bootstrap/Collapse {:in is-current}
    children]

;; and component declaration looks like:

(defnc MyMenu [{:keys [class] :as props}]
  [:div {:class class}
    ;; snip
    ])

It looks like that MyMenu receives className but not class.

I haven't had time to look at the hx code to see where this could be taken care of, but I think that given that I can use MyMenu from other places by using class, it should be usable also with native React components wrapping it.

Thoughts?

Reducers dont support Multimethods

Recently i had to do the following
https://i.imgur.com/DMGUjlt.png
The reason is that multimethods are not actually js functions but rather objects implementing the
Ifn protocol so in order to be used as reducers one has to call them from within an actual function
I think the same is true for keywords, sets and maps. It would be a good enhanchment to be able to use them as reducers without having a top level wrapper function

Experience Report

Hi, I spent the past couple days integrating hx with an existing Reagent application and thought I'd share an experience report in case it's useful to other users or to the library developers.

First, the reason I did this at all is that Reagent's development has slowed while React continues to introduce new features and idioms, and I would like to be able to use javascript libraries that use new React features like hooks without difficulty. The application currently uses re-frame and reagent.

I tried to replace a couple UIs with hx, and it ended up not being very difficult at all.

Because I have some library components for form inputs and things like that, I need to manage reagent components containing hx components and vice versa. This is pretty easy in both directions. Reagent components can return react elements, so instead of using the typical [my-reagent-component and its args] that you'll see a lot in reagent applications, you do (hx.react/$ my-hx-component args-as-a-map).
The other direction requires you to use reagent.core/as-element. Instead of referring to the subcomponent in the usual hx way, [my-hx-component props-map], you use (reagent/as-element [my-reagent-component ...]).

I ended up adding some wrapper components to deal with the fact that reagent components can take any number of args but hx components just take a single props map.

(defn reagent-wrapper-of-hx-component [whatever arguments etc]
  (hx/$ whatever {:whatever whatever :arguments arguments :etc etc}))

I have been using https://github.com/Lokeh/reagent-context in this project for react context + reagent integration. That lib doesn't directly expose the react Context object when you create a context, so in order to use the useContext hook, I had to dig into the implementation details a bit:

(def ctx (reagent-context/create))
;; in a let binding in an hx component:
(react/useContext (.-instance ctx))

This is a re-frame project, so I've used subscribe and dispatch extensively. Nothing needed to change in calls to dispatch but subscribe calls were replaced with calls to use-sub, as defined here (note it's defined as <-sub in that repo).

(let [thing @(rf/subscribe [:thing])])
;; becomes:
(let [thing (use-sub [:thing])])

Also, don't forget to change reagent components using the hiccup class+id shorthand to define those things in props. I don't like the #id.class syntax in hiccup, but I haven't totally gotten rid of it from my project yet.

[:div.foo]
;; becomes
[:div {:class "foo"}]

I've ended up needing to work w/ js objects and idioms more than I would have hoped, plus I worry that the cljs<->js translation that happens w/ defnc components will eventually cause perf problems. It makes me wonder how practical/achievable it would be to modify react to allow things other than plain js objects for props.
It's also possible I overused plain js objects because I wasn't always sure where clojurescript objects were acceptable/would perform well, like in the useState hook. IDK if that is something that hx should try to document.

I also integrated react-dnd with hx, which was easier than when I tried to use it with Reagent before. I know others have had success with a reagent and react-dnd integration via a wrapper lib, but I was able to use react-dnd without any wrapper lib at all, which is nice.

I'm pleased so far with hx, and will do future js library integrations via hx instead of reagent, and perhaps eventually replace all my reagent code with hx.

Only complaint: some of the names in hx's API are unclear. hx.react/f and hx.react/$ are the main offenders. I'd prefer longer, descriptive names. Especially given how infrequently those functions are used in practice.

Typo in package 0.5.3 (maybe broken)

I tried to analyse the lilactown/hx v0.5.3 package with cljdoc-analyzer project.

I discover that in the file hx/hiccup/tag.cljc, there is a use of the package goog.obj as dependency. But this package doesn't exist, the correct name is goog.object.

By the way, the file hx/hiccup/tag.cljc doesn't exist anymore on the master branch, so maybe you should generate a new version of the hx package, v0.5.4
Just to get the latest package analysable by cljdoc (if cljdoc cannot anaylise it, it's possible that no one can use it...).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.