Giter Club home page Giter Club logo

hot-module-reload's Introduction

Aurelia

License: MIT npm version CircleCI TypeScript Twitter

Backers on Open Collective Sponsors on Open Collective Discord Chat

Aurelia 2

This is the Aurelia 2 monorepo, containing core and plugin packages, examples, benchmarks, and documentation for the upcoming major version of everybody's favorite modern JavaScript framework, Aurelia.

Introduction

Aurelia is a modern, front-end JavaScript framework for building browser, mobile, and desktop applications. It focuses on aligning closely with web platform specifications, using convention over configuration, and having minimal framework intrusion. Basically, we want you to just write your code without the framework getting in your way. 😉

Aurelia applications are built by composing a series of simple components. By convention, components are made up of a vanilla JavaScript or Typescript class, with a corresponding HTML template.

//app.js
export class App {
  welcome = "Welcome to Aurelia";

  quests = [
    "To seek the holy grail",
    "To take the ring to Mordor",
    "To rescue princess Leia"
  ];
}
<!-- app.html -->
<form>
  <label>
    <span>What is your name?</span>
    <input value.bind="name & debounce:500">
  </label>

  <label>
    <span>What is your quest?</span>
    <select value.bind="quest">
      <option></option>
      <option repeat.for="q of quests">${q}</option>
    </select>
  </label>
</form>

<p if.bind="name">${welcome}, ${name}!</p>
<p if.bind="quest">Now set forth ${quest.toLowerCase()}!</p>

This example shows you some of the powerful features of the aurelia binding syntax. To learn further, please see our documentation.

Feeling excited? Check out how to use makes to get started in the next section.

Note: Please keep in mind that Aurelia 2 is still in beta. A number of features and use cases around the public API are still untested and there will be a few more breaking changes.

Getting Started

First, ensure that you have Node.js v8.9.0 or above installed on your system. Next, using npx, a tool distributed as part of Node.js, we'll create a new Aurelia 2 app. At a command prompt, run the following command:

npx makes aurelia

This will cause npx to download the makes scaffolding tool, along with the aurelia generator, which it will use to guide you through the setup process. Once complete, you'll have a new Aurelia 2 project ready to run. For more information on Aurelia's use of makes, see here. If you aren't interested in taking our preferred approach to generating a project, you can also see the examples folder in this repo for pure JIT setups (no conventions) with various loaders and bundlers.

Documentation

You can read the documentation on Aurelia 2 here. Our new docs are currently a work-in-progress, so the most complete documentation is available in our getting started section. If you've never used Aurelia before, you'll want to begin with our Quick Start Guide.

Contributing

If you are interested in contributing to Aurelia, please see our contributor documentation for more information. You'll learn how to build the code and run tests, how best to engage in our social channels, how to submit PRs, and even how to contribute to our documentation. We welcome you and thank you in advance for joining with us in this endeavor.

Staying Up-to-Date

To keep up to date on Aurelia, please visit and subscribe to the official blog and our email list. We also invite you to follow us on twitter. If you have questions, have a look around our Discourse forum. For chat on Aurelia 2, join our new Aurelia 2 community on Discord. If you'd like to join the growing list of Aurelia sponsors, please back us on Open Collective.

License

Aurelia is MIT licensed. You can find out more and read the license document here.

hot-module-reload's People

Contributors

adamwillden avatar eisenbergeffect avatar jods4 avatar meirionhughes avatar niieani avatar rluba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hot-module-reload's Issues

SCSS hot reload is not working

@EisenbergEffect thanks for doing the release, unfortunately the new feat in #12 doesn't seem to work for me. @niieani, @jods4 did you try it out at the time?

I'm submitting a bug report

  • Library Version:
    0.2.0

Please tell us about your environment:

  • Operating System:
    Windows 10

  • Node Version:
    8.2.1

  • NPM Version:
    5.4.2

  • JSPM OR Webpack AND Version
    Webpack 3.6.0

  • Browser:
    Chrome 61.0.3163.100

  • Language:
    TypeScript 2.5.2

Current behavior:
All my dependencies are up to date

{
  "version": "1.0.0",
  "sasslintConfig": "node_modules/siopa-package-tools/.sass-lint.yml",
  "private": true,
  "scripts": {
    "test": "jest",
    "start": "webpack"
  },
  "dependencies": {
    "aurelia-bootstrapper": "^2.1.1",
    "aurelia-dependency-injection": "^1.3.2",
    "aurelia-framework": "^1.1.5",
    "aurelia-pal": "^1.4.0",
    "aurelia-router": "^1.4.0"
  },
  "devDependencies": {
    "@types/extract-text-webpack-plugin": "^3.0.0",
    "@types/jest": "^21.1.2",
    "@types/node": "^8.0.32",
    "aspnet-webpack": "^2.0.1",
    "aurelia-hot-module-reload": "^0.2.0",
    "aurelia-polyfills": "^1.2.2",
    "aurelia-webpack-plugin": "^2.0.0-rc.5",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.0",
    "file-loader": "^1.1.5",
    "gulp": "github:gulpjs/gulp#4.0",
    "import-glob-loader": "^1.1.0",
    "node-sass": "^4.5.3",
    "sass-loader": "^6.0.6",
    "siopa-package-tools": "^1.0.9",
    "style-loader": "^0.19.0",
    "ts-loader": "^2.3.7",
    "ts-node": "^3.3.0",
    "tslib": "^1.7.1",
    "tslint": "^5.5.0",
    "typescript": "^2.5.2",
    "webpack": "^3.6.0",
    "webpack-hot-middleware": "^2.19.1"
  }
}

Given the following component, when changing the color, an error is displayed in console.

// relevant webpack config line
{ test: /\.scss$/i, issuer: /\.html$/i, loader: 'css-loader!sass-loader' },
<template class="c-header-bar">
  <require from="./header-bar.scss"></require>
  My Header Text
</template>
.c-header-bar {
  color: blue;
}
process-update.js:115 [HMR] Cannot check for update (Full reload needed)
handleError @ process-update.js:115
process-update.js:116 [HMR] TypeError: Cannot read property 'resources' of undefined
    at HmrContext.29.HmrContext.reloadCss (http://localhost:5000/dist/app.js?v=QNzl5O3zgddSQAkYZUauFSbxSVlDVeKMHEZPOYHMqfk:10355:29)
...ETC
handleError @ process-update.js:116
aurelia-hot-module-reload.js:235 Uncaught (in promise) TypeError: Cannot read property 'resources' of undefined
    at HmrContext.29.HmrContext.reloadCss (aurelia-hot-module-reload.js:235)
    at Object.hot (aurelia-hot-module-reload.js:79)
    at aurelia-loader-webpack.js:167
    at Object.hotApply [as apply] (bootstrap 8fa308dbf2e403c4d37c:580)
    at cb (process-update.js:52)
    at process-update.js:68
    at <anonymous>

Expected/desired behavior:

Given the following component, when changing the color, then the rendered text should change color without console errors.

If I use .css files instead with the same setup and following webpack config line everything works

        { test: /\.css$/i, issuer: /\.html$/i, loader: 'css-loader' },

Corresponding view does not rerender

I'm submitting a bug report

  • Library Version:
    0.1.0

Please tell us about your environment:

  • Operating System:
    Windows 8.1

  • Node Version:
    6.9.2

  • NPM Version:
    3.9.6
  • JSPM OR Webpack AND Version
    webpack 2.5.1
  • Browser:
    Chrome 58.0.3029.110

  • Language:
    ESNext

Current behavior:
HMR does update and replace view-model but without updating corresponding view.

Expected/desired behavior:

  • What is the expected behavior?
    To update corresponding view with current view-model.

Not sure if it is a bug or my mistake. I use webpack-dev-middleware and webpack-hot-middleware along with browser-sync. My webpack config:

/*global __dirname, module, process */
const path = require('path');
const { AureliaPlugin } = require('aurelia-webpack-plugin');
const NyanProgressPlugin = require('nyan-progress-webpack-plugin');
const webpack = require('webpack');

const isProduction = process.env.NODE_ENV === 'production';
const plugins = [new AureliaPlugin({
  featuers: {
    svg: false
  }
})];
const entry = ['aurelia-bootstrapper'];

if (isProduction) {
  plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      mangle: true,
      compress: {
        warnings: false,
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true
      },
      output: {
        comments: false
      }
    })
  );
} else {
  plugins.push(
    new NyanProgressPlugin(),
    new webpack.HotModuleReplacementPlugin()
  );
  entry.push('webpack-hot-middleware/client?reload=true&overlay=true');
}

module.exports = {
  context: path.resolve(__dirname),
  resolve: {
    extensions: ['.js'],
    modules: ['src', 'node_modules'].map(dir => path.resolve(__dirname, dir))
  },
  entry,
  output: {
    filename: 'app.built.js',
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.html$/,
        use: 'html-loader'
      }
    ]
  },
  devtool: isProduction ? false : 'inline-source-map',
  plugins
};

BrowserSync configuration:

browserSync.init({
    online: false,
    open: false,
    port: 9000,
    http: true,
    https: true,
    proxy: proxySettings ? `https://${proxySettings.url}:${proxySettings.port}` : defaultServerForProxying,
    middleware: [
      webpackDevMiddleware(bundler, {
        publicPath: config.output.publicPath
      }),
      webpackHotMiddleware(bundler)
    ]
  });

When I update view-model browser's console seems fine:

[HMR] bundle rebuilding
[HMR] bundle rebuilt in 1232ms
[HMR] Checking for updates on the server...
Running default HMR for pages/home/index
[HMR] Updated modules:
[HMR]  - ./src/pages/home/index.js
[HMR] App is up to date.
Analyzing pages/home/index->GoalsIndex
Replacing function GoalsIndex() {
  _classCallCheck(this, GoalsIndex);

  this.goalsData = {
    summary: {
      savedSoFar: { amount: 0, currency: 'PLN' },
      averageMonthlyTempo: { amount: 0, currency: 'PLN' },
 … with function GoalsIndex() {
  _classCallCheck(this, GoalsIndex);

  this.goalsData = {
    summary: {
      savedSoFar: { amount: 0, currency: 'PLN' },
      averageMonthlyTempo: { amount: 0, currency: 'PLN' },

The funny thing is that it works for only view changes, it hot reloads correctly.

[question] How to use HMR for typescript

For hot module replacement(reload) in asp.net core, we face some difficulties, in which typescript files do not reload on the change save process. while it is working with angular which seems to be owing to the following code snippet in their boot-client.ts

if (module['hot']) {
    module['hot'].accept();
    module['hot'].dispose(() => {
        // Before restarting the app, we create a new root element and dispose the old one
        const oldRootElem = document.querySelector('app');
        const newRootElem = document.createElement('app');
        oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
        modulePromise.then(appModule => appModule.destroy());
    });
} else {
    enableProdMode();
}

I was wondering whether there is any solution to enable such capability for Aurelia projects or not?

When a state template is replaced, the ViewModel is detached and unbound but not attached or bound

I'm submitting a bug report

  • Library Version:
    0.3.0

Please tell us about your environment:

  • Operating System:
    OSX 10.14.6

  • Node Version:
    10.16.3

  • NPM Version:
    6.9.0

  • JSPM OR Webpack AND Version
    webpack 4.41.0

  • Browser:
    all

  • Language:
    ESNext

Current behavior:
When changing the template of a route component, the state instance ("view model"?) gets it’s detached() and unbind() handlers called, but neither attached() nor bind() are called again - leading to lots of NPEs in our case.

When changing the template of a regular component, neither detached() nor unbind() are called.

Expected/desired behavior:

Route components should act like regular components: Either call all lifecycle methods during HMR or none.

Hidden Views do not reload

This includes Views which are conditionally hidden (e.g. with if.bind), not the ones that are simply not shown (hidden via CSS).

To reproduce:

  1. hide a View so that it's removed from the DOM
  2. change the template of that View
  3. unhide the View

The View will still contain old data, and its ViewFactory and template fragment will be out of date with the module, thus any further HMR on that Element will fail until the View is fully re-created (e.g. by switching routes).

To fix this we'll need to switch the way we traverse Controllers in search for Views matching a given template. We need to match all the Views, whether they're attached and present in the DOM or not.

If that still does not make it possible to access all the created View instances, we can think of alternative solutions, such as storing old fragments, or tracking Views with afterCreated hook and then replacing the ViewFactories in a beforeBind hook. However, this would not be a great solution because this would cause a memory-leak, as the memory consumption of the site would grow with every hot-reload of any View.

App entry point

My application root is by convention app. It starts like this:
aurelia.start().then(() => aurelia.setRoot());

I noticed that app is not loaded through any of the module.hot.accept paths in aurelia-loader-webpack and hence does not support HMR. Changing code in app.ts triggers a full reload.

app.html on the other hand goes through module.hot.accept and triggers a hot reload, but the view is only updated the very first time. After that, it still triggers a hot reload but the view is not updated anymore.
I don't have that problem with other views, they refresh fine.

A previously <require>d CSS does not Hot-unload when removed from a View

With the current implementation, there is no signal to the CSS resource when a View is being detached and hence the CSS is never being unloaded (currently that's by design). Therefore removing a <require from="file.css"> from a HTML template has no effect, but making said css file empty, does.

ViewModels are being patched, not re-created

Currently, we only switch out the prototype of the ViewModels, from the old ones to the new ones. It would be best if we could re-create them and then copy their state over to the new object. This also creates problems of its own, because we'll need to de-register old instances in the DI Containers and re-register new ones in their places. That will be quite challenging, since Containers do not expose any such capabilities.

A possible solution would be to add a "proxy" feature to Aurelia DI, so that, if enabled, resolved instances could be globally overwritable with a user-defined proxy function.

Error on validated form reload

I'm submitting a bug report

  • Library Version:
    0.2.1

Please tell us about your environment:

  • Operating System:
    Windows 10

  • Node Version:
    12.16.2

  • NPM Version:
    6.14.4

  • JSPM OR Webpack AND Version
    webpack 4.44.2

  • Browser:
    all

  • Language:
    TypeScript 4.0.3

Current behavior:
Updating a template or a view model which uses ValidationController causes HMR to crash with

Uncaught (in promise) Error: A ValidationController has not been registered.
    at ValidateBindingBehaviorBase.bind (aurelia-validation.js?f0d7:1082)
    at BindingBehavior.bind (aurelia-binding.js?5f98:1191)
    at Binding.bind (aurelia-binding.js?5f98:4996)
    at View.bind (aurelia-templating.js?8628:1678)
    at eval (render-utils.js?b780:95)
    at Array.forEach (<anonymous>)
    at rerenderMatchingSlotChildren (render-utils.js?b780:80)
    at eval (aurelia-hot-module-reload.js?e5b8:215)
    at Set.forEach (<anonymous>)
    at HmrContext.eval (aurelia-hot-module-reload.js?e5b8:215)

Expected/desired behavior:

  • What is the expected behavior?
    The HRM refreshes without crashing

  • What is the motivation / use case for changing the behavior?
    Better support development cycle by removing the need to refresh a page after each update

Aurelia's design vs HMR [conversation]

☝️ February 17, 2017 11:31 PM

HMR needs a bit more work but the reasons it's so hard are more architectural
currently I need to traverse soo many places in order to find the instances and replace them
(in the HMR code)

I think this is something to think about for Aurelia 2.0: how to structure the code so that the instances of things like VM aren't stored directly, but perhaps as getters to a centralized store
it would also be good if we had access to the whole tree of DI Containers, to traverse both up and down in depth but I get that Aurelia wasn't designed with HMR in mind, so it's an afterthought now
we'd need some fundamental changes to make it robust

Bazyli Brzóska @niieani 23:36
now the HMR code is traversing as many places as I can to find with matching exports and their instances and trying to either replace them or swap their prototype for the new one
https://github.com/aurelia/hot-module-reload/blob/master/src/view-model-traverse-controller.ts
all this logic:

  • isn't perfect, since there's no way to tell if we caught all the references where an export "might be"
  • is super difficult to reason about
  • is dependent on Aurelia's internal data structures

with Views it's even harder, since there isn't a centralized place where we can iterate the whole "Aurelia" tree (as opposed to the DOM tree)
so currently I'm just finding the Views to hot-reload like this: DOM.querySelectorAll('.au-target')

return Array.from(DOM.querySelectorAll('.au-target')) as Array<Element & AU>;

and then accessing their .au properties that (sometimes) contain .view and .scope
and then traversing that for .controller, .viewFactory and router slots

Jedd Ahyoung @jedd-ahyoung 23:41
so you're saying there should be something like a ViewRegistry or something? maybe a weakmap that can be iterated?

Bazyli Brzóska @niieani 23:41
the problem is a weakmap can't be iterated
I've already looked into it

Jedd Ahyoung @jedd-ahyoung 23:41
thought it could be.....guess i'm wrong. maybe maps can and weakmaps can't, hmm

Bazyli Brzóska @niieani 23:42
there currently isn't any construct in JS that allows you to create an interable WeakSet / WeakMap

jods @jods4 23:42
I think that was by design.

Bazyli Brzóska @niieani 23:42
it would be possible (cause it make sense, the garbage collector would just remove the item from the set during GC)
anyway, we'd just need to add the hook in the appropriate place

Jedd Ahyoung @jedd-ahyoung 23:43
hmm. seems like you'd need some type of tree structure in memory with refs to the views, but you'd need to be able to invalidate them easily. that could be done without a weakmap, i suppose, using generic js hash objects - quick lookup as well

Bazyli Brzóska @niieani 23:43
when the View is created, a reference would have to be added somewhere
and then when it is destroyed, we'd remove that reference
I've tried experimenting with the ViewHooks
but we don't have enough of them to make this possible
i.e. no way to consistently remove the Views from such a map

Jedd Ahyoung @jedd-ahyoung 23:45
yeah, this basically has nothing to do with the component lifecycle, right? the lifecycle of a view isn't tied to how it's stored within aurelia due to caching

Bazyli Brzóska @niieani 23:46
yes
but we do have a hook for after a view was created, for example
we'd also need to store ViewModels the same way, in a central registry

Jedd Ahyoung @jedd-ahyoung 23:47
not sure how the view cache works....i imagine it's built to lookup in constant time, but maybe it'd be possible to built it as a tree structure of sorts for traversal purposes?

Bazyli Brzóska @niieani 23:47
that is, instances of the ViewModels

Jedd Ahyoung @jedd-ahyoung 23:48
the real problem with views is that i don't think that you could actually do anything unless the view was cached due to aurelia conventions and differing view strategies

Bazyli Brzóska @niieani 23:48
while references to module exports should be getters that point to the module in the loader cache

Jedd Ahyoung @jedd-ahyoung 23:48
not sure but i think the only thing you really could do was invalidate the cache and reload
yeah, for the viewmodels maybe you actually could use an aurelia loader that's built specifically for webpack and module loading

Bazyli Brzóska @niieani 23:49
The thing is with HMR I can remove a View and recreate it
it's not a problem
I only need to track where the View is, what's it's parent is and where in the DOM it is (if visible)

Jedd Ahyoung @jedd-ahyoung 23:49
you could keep the viewmodel registry there, in the loader instance

Bazyli Brzóska @niieani 23:50
the rest is bindingContext and overrideContext, which we can keep between reloads
so when you swap out a .html, it recompiles the template, removes the old View, removes all the references to it (that I can find), makes a new View with the new template and replaces the references to match the new View

Jedd Ahyoung @jedd-ahyoung 23:52
makes sense, yeah
might it be possible to swap out the viewlocator and do it there?

Bazyli Brzóska @niieani 23:53
don't know
I didn't dig that deep

404 in README - Documentation is nonexistent?

Currently we use Gulp in our development environment. We are looking to move to Webpack and set up HMR, but it's really not clear from the README what all is involved in setting this up. The README links to a page that doesn't exist (http://aurelia.io/hub.html) and when I go there and do a search for "HMR" or "hot module reload" or any such permutation, I come up dry.

An example of a REAMDE for HMR that's got good documentation can be found at https://github.com/gaearon/react-hot-loader. Code examples etc. Can we please have this? :) Thanks!

Container.instance undefined

I'm submitting a bug report

  • Library Version:
    0.1.0

Please tell us about your environment:

  • Operating System:
    Windows 10

  • Node Version:
    7.10.0

  • NPM Version:
    5.0.3

  • JSPM OR Webpack AND Version
    webpack 2.6.1

  • Browser:
    Chrome 58

  • Language:
    ESNext

Current behavior:
We have a ASP.NET Core project serving an API with Aurelia as SPA (also served by ASP.NET Core and packed with Webpack, inspired by https://github.com/aspnet/JavaScriptServices/tree/dev/templates/AureliaSpa). When we run our minimal setup with only a main.js, app.js and frontpage.js with almost no content, we receive the following error:

Uncaught (in promise) TypeError: Cannot read property 'get' of undefined
    at new HmrContext (aurelia-hot-module-reload.js:38)
    at WebpackLoader.<anonymous> (aurelia-loader-webpack.js:67)
    at Generator.next (<anonymous>)
    at aurelia-loader-webpack.js:6
    at Promise (<anonymous>)
    at 58.__awaiter (aurelia-loader-webpack.js:2)
    at Object.fetch (aurelia-loader-webpack.js:58)
    at WebpackLoader.<anonymous> (aurelia-loader-webpack.js:105)
    at Generator.next (<anonymous>)
    at aurelia-loader-webpack.js:6

The line that fails is this one:
this.viewEngine = Container.instance.get(ViewEngine);
(https://github.com/aurelia/hot-module-reload/blob/master/src/aurelia-hot-module-reload.ts#L42)

Expected/desired behavior:
Execution should not fail.

I'm not sure if this is a bug, or a misconfiguration. Sorry if this shouldn't have been posted here.

Global resources don't hot-reload

I was playing with a basic value converter:

export class UpperValueConverter {
  toView(name: string) {
    return name && name.toUpperCase();
  }
}

When imported locally in a view with <require from="converters/upper"></require>, the code does hot reload. The bindings don't refresh immediately but on the next value change I can see that the new converter code is running.

If I declare that converter as a global resource in my main file, like so:

import 'aurelia-bootstrapper';
import { Aurelia } from 'aurelia-framework';

export function configure(aurelia: Aurelia) {
  aurelia.use
         .standardConfiguration()
         .developmentLogging()
         .globalResources('converters/upper');
  aurelia.start().then(() => aurelia.setRoot());
}

Then it doesn't work and triggers a full-reload.

I noticed that in the second case, loading the converter does not go through any of the module.hot.accept paths in aurelia-loader-webpack, which explains why HMR doesn't work.

HMR for SystemJS

Hi Guys,

I'm trying to work out how to get Aurelia HMR support into systemjs-hmr, and by extension systemjs-hot-reloader.

But I'm unsure of what it would take other then standard hmr. This project seems to reimplement a module registry?

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.