Coder Social home page Coder Social logo

newland's Introduction

newland

如果说前端是维斯特洛大陆,那么后端是更为古老先进的瓦雷利亚大陆!

注:上面的地名出自《冰与火之歌》

前端的世界基本定形了,谁也消灭不了谁

在jquery崛起之后,有许多框架消亡了,如MochiKit。上代王者Prototype更新缓慢,但百足巨虫僵而未死, 受它的启迪,一拔人从OO角度进行改良,诞生了mootools,一拔人从函数式编程角度进度改良,诞生了underscore。 dojo拥有IBM等后台,最新版完全支持AMD。YUI是上上上代互联网巨头雅虎的产品,设计精良。EXT是YUI出走的孩子,UI库的典范,它的团队精力充沛, 还用node.js搭建了express.js这著名框架。

jqueryPrototypemootoolsEXT dojoYUIunderscore
风暴地北境西境河湾地 多恩(南境)谷地河间
风息堡临冬城凯岩城高庭 阳戟城鹰巢城奔流城
鹿玫瑰太阳
拜拉席恩史塔克兰尼斯特提利尔马泰尔艾林徒利

此外,

后端比较出彩的四大框架:tower,derby,express,railsway。

前端比较出彩的MVC框架:ember,angular,knockout,backbone。

从历史趋来看,前端往后端进发是必然的事,有个术语好像叫什么大前端。就是一帮苦逼的码农,基本是PHPer,他们负责整个页面的生成与脚本交互。

但前端的技术发展得这么快,一般PHPer很难跟进的,因此由专业的JSer接手是势在必行了,因为PHPer最重要的工作,页面接装模板, 从ruby世界的好事者已经搞了许多套,前端模板已为大家所接受,但我们没有必要用两套模板,node.js的出现让这成为可能。 而且页面的各种性能优化都与请求头,HTTP协议息息相关,JSer想搞高自己的水平,也要了解这一部分知识,如果搞最赚钱的页游,socket等知识也是必需的。

一个明显的例子,像Sencha这个公司,它前端拥有EXT,EXT在4.0中完成MVC机制与模块加载机制,后端拥有express框架,十年前,很难想象有人竟然靠JS赚钱开公司! 这是前端大翻身的机会,几个前端只要有创意,就可以踢开PM开发自己的产品了,不需求助于PHPer, javaer……

newland就是基于这样的情愫搞出来的,带领JSer驶向一个新世界。

===============================

目录构成与模块说明

实在非常抱歉,现在整个项目文件非常混乱,就像西班牙殖民者驾着其破船,乱打乱撞发现新大陆,兴奋之余,船只撞到海岸的礁石上,到处是碎片,也不知怎么办……

不过,首要任务是活下来,在瓦雷利亚的海滩上建立一个小渔村或农舍!

<p〉这个广裘的大陆上有着许多帝国,前端的七大王国,相对它们来说就是部落国而已。因此我的小框架绝对也引不起它们的注意……

mass.js 框架的入口
├─app
│  ├─cache
│  ├─config
│  ├─controllers
│  ├─errors
│  ├─helpers
│  ├─logs
│  ├─models
│  ├─public
│  │   ├─scripts
│  │   ├─styles
│  │   └─images
│  ├─config.js 配置文件,现在就只用到它的端口:8888
│  └─views
├─system
│  ├─more
    │   └─here_document.js 模拟其他语言的here document语法
    ├─mime
    ├─deploy.js  热启动
    ├─mime.js  用于从请求头中取出正确的MIME
    ├─ejs.js   模板系统
    ├─view.js  用于拼装页面,一般情况页面都有两个部分组成(用于显示主要内容的局部模板与布局用的全局模板)
    ├─flow.js  用于处理node.js操作的回调嵌套问题,类似于发布者订阅者模式
    ├─hjs.js   高层次的IO API,就像前端的DOM操作一样,原生的那一套在jQuery那样的API下黯然失色
    ├─lang.js  就是前端mass的lang模块,不过它前后端通吃,里面大量工具函数
    ├─lang_fix.js lang.js的补丁模块
    ├─status.js  各种状态码,用于错误页面
    ├─server.js   newland框架的二当家,用于接受各种情况,派发数据


另外还有许多文件,这都是我上一次来这片大陆时,撞沉后的海盗船碎片,不用过于介怀!

试用

安装node.js,下载newland项目,命令台定位到newland目录下,然后node mass.js.在浏览器下http://localhost:8888/

wiki

光是一个readme是无法把什么都说明白,更多有用的资料我放到wiki上了!

newland's People

Contributors

rubylouvre 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

newland's Issues

完成日志打印功能

没有使用经典的createWriteStream方法,我把要打印的日志push进一个数组,然后hfs.writeFile用递归输出。如果有什么好的实现请告诉我

logger.js

完成flash机制

flash是基于session的消息传送机制,我们可以把消息放到flash中并在下一个action访问到它们。
用法

flow.flash('info', 'email sent');
flow.flash('error', 'email delivery failed');
flow.flash('info', 'email re-sent');
// => 2

flow.flash('info');
// => ['email sent', 'email re-sent']

flow.flash('info');
// => []

flow.flash();
      // => { error: ['email delivery failed'], info: [] }

详见文档

完成session机制

我已经完成newland.js的内存session与cookie session了

cookie session就直接利用它的maxAge来清除

内存session利用setInterval定期检测mtime属性,发现mtime少于当前时间,清掉它

全新的加载器(兼容CommonJS与Require的AMD与SeaJS)

现在所有模块都将匿名化,同步化。新版的加载器相同说是相当于原生require的加强版,同时require多个模块时,返回一个数组。

var array = require(["./aaa","./bbb","./ccc"])
//相当于
var array = [];
array[array.length] =  require("./aaa")
array[array.length] =  require("./bbb")
array[array.length] =  require("./ccc")

亦可以在后面加函数

var array = require(["./aaa","./bbb","./ccc"],function(a, b, c){
//.......................
})

模块允许多种定义法

//纯node.js方法
var a = require("httpflow")
console.log(a)
//CommonJS的匿名函数法
define({
    aa:1,
    bb:2
})
//CommonJS的匿名函数法
define(function(){
    exports.aaa = "aaa"
})
//CommonJS的匿名函数法
define(function(){
    exports.aaa = "aaa"
   return "xxxx" //注意这时exports对象将变xxxx返回值所取替,当返回为不为undefined时
})
//CommonJS的匿名函数法
define(["./aaa"],function(require, exports, module){
     console.log(module)//指向当前模块
})
//ADM的匿名函数法
define(["./aaa","./bbb"],function(a,b){
     console.log(module)//指向当前模块,module总是存在的
     console.log(a)
})

我们再看一下新旧模块系统实现的对比:

$.mix({
        //模块加载的定义函数
        define: function( name, deps, factory ){//模块名,依赖列表,模块本身
        //这是一个空接口
        },
        //模块加载的请求函数
        require: function( deps, factory, errback ){
            var _deps = {}, args = [], dn = 0, cn = 0;
            factory = typeof factory == "function" ? factory : $.noop;
            String(deps +"").replace( $.rword, function( str ){
                if(str.indexOf("./") === 0){
                    str = str.replace(/^\.\//, "" );
                }
                dn++;
                var match = str.match( rmodule );
                var id  = "@"+ match[1];//模块的ID
                var filename = match[2];//模块的URL
                if(!filename){
                    id = id.replace(/\.js$/,"")
                    filename = $.path.join( factory.parent || $.require.root, match[1] ); //path.join会自动处理../的情况
                    filename = /\.js$/.test(filename) ? filename : filename +".js";
                }
                var input = id;
                try{//先把它当成原生模块进行加载
                    returns[ id ] = require( match[1] );//require自身是缓存请求的
                    mapper[ id ] = {
                        state : 2
                    }
                    process.nextTick( $._checkDeps );//每成功加载一个模块就进行依赖检测
                }catch(e){
                    input = filename
                }
                if( !_deps[ input ] ){
                    args.push( input );
                    _deps[ input ] = "司徒正美";
                }
                if( input === filename &&  !mapper[ input ] ){ //防止重复生成节点与请求
                    mapper[ input ] = {};//state: undefined, 未安装; 1 正在安装; 2 : 已安装
                    loadJS( filename );
                }else if( mapper[ input ].state === 2  ){
                    cn++;
                }
            });
            var id = factory.id || "@cb"+ ( cbi++ ).toString(32);
            if( typeof errback == "function" ){
                errorStack.push( errback );//压入错误堆栈
            }
            mapper[ id ] = mapper[ id ] || {}
            $.mix( mapper[ id ], {//创建或更新模块的状态
                callback: factory,
                id:       id,
                deps:     _deps,
                args:     args,
                state:    1
            }, false);
            //在正常情况下模块只能通过_checkDeps执行
            loadings.unshift( id );
            process.nextTick( $._checkDeps );
        },
        //  模块加载的检测依赖函数,如果一个模块所依赖的其他模块的状态都是2了,那么将它也改成2,并执行回调
        _checkDeps: function (){
            loop:
            for ( var i = loadings.length, filename; filename = loadings[ --i ]; ) {
                var obj = mapper[ filename ], deps = obj.deps || {};
                for( var key in deps ){
                    if( deps.hasOwnProperty( key ) && mapper[ key ].state != 2 ){
                        continue loop;
                    }
                }
                //如果deps是空对象或者其依赖的模块的状态都是2
                if( obj.state !== 2){
                    loadings.splice( i, 1 );//必须先移除再安装,防止在IE下DOM树建完后手动刷新页面,会多次执行它
                    obj.state = 2 ;
                    var  id = obj.id;
                    var  ret = collect_rets( id, obj.args ||[], obj.callback );
                    if( id.indexOf("@cb") === -1 ){
                        returns[ id ] = ret;
                        $.log("已加载" + id + "模块","cyan", 6 );
                        $._checkDeps();
                    }
                }
            }
        }
});
 //把模块有关信息都存放在这里
    var mapper = $.require.cache = {}
    //从returns对象取得依赖列表中的各模块的返回值
    function collect_rets( name, args, fn ){
        for(var i = 0, argv = []; i < args.length ; i++){
            argv.push( returns[ args[i] ] );
        }
        var ret = fn.apply( null, argv );//执行模块工厂,然后把返回值放到returns对象中
        $.debug( name );//想办法取得函法中的exports对象
        return ret;
    }

    //模块加载的加载函数
    function loadJS(  filename ){
        try{
            $.define = function(){//诡变的$.define
                var args = Array.apply([],arguments);
                if( typeof args[1] === "function" ){//处理只有两个参数的情况
                    [].splice.call( args, 1, 0, "" );
                }
                args[2].id = filename; //模块名
                args[2].parent =  filename.slice(0, filename.lastIndexOf( $.path.sep ) + 1) //取得父模块的文件夹
                mapper[ filename ].state = 1;
                process.nextTick( $._checkDeps );//每成功加载一个模块就进行依赖检测
                $.require( args[1], args[2] );
            }
            require( filename );
        }catch( e ){
            $.log( e, "red", 3);
            for(var fn; fn = errorStack.shift(); ){
                fn();//打印错误堆栈
            }
        }
    }

    //用于模块加载失败时的错误回调
    var errorStack = [];

新加载系统则精简许多了

var rparams =  /[^\(]*\(([^\)]*)\)[\d\D]*/
var toString = ({}).toString;
global. define =  function(deps, callback){
            var caller = arguments.callee.caller
            var args = caller.arguments;//取得当前模块的参数列表,依次为exports, require, module, __filename,__dirname
            var common = {
                exports: args[0],
                require: args[1],
                module:  args[2]
            }
            var array = [], ret;
            if(arguments.length === 1 && toString.call(deps) === "[object Object]"){
                ret = deps;//如果是对象,那么它就是exports
            }else if(typeof deps == "string" ){
                deps = deps.match( $.rword );//如果依赖列表是字符串,则转换为数组
            }
            if(Array.isArray(deps)){//如果存在依赖关系,先加载依赖关系
                for(var i = 0,el ; el = deps[i++] ;){
                    array[ array.length ] =  args[1]( el );//require某个模块
                }
            }
            callback = arguments[arguments.length - 1];
            if(typeof callback == "function"){
                var match = callback.toString().replace(rparams,"$1") || [];
                var a = common[match[0]];
                var b = common[match[1]];
                var c = common[match[2]];
                if( a && b && c && a != b && b != c && a != c ){//exports, require, module的位置随便
                    ret =  callback.apply(0, [a, b, c]);
                }else{
                    ret =  callback.apply(0, array);
                }
            }
            if(typeof ret !== "undefined"){
                args[2].exports = ret;
            }
            return args[2].exports;
        }
var $ = {}
$.require = function(deps, callback){
    if(typeof deps == "string"){
        return require(deps)
    }
    var array = [];
    for(var i = 0, el; el = deps[i++];){
        array.push( require(el) )
    }
    if(typeof callback == "function"){
        callback.apply(0, array);
    }
    return array
}

详细的测试用例请见app\public\scripts\test

github上值得关注的前端项目

github-FE-project

github上值得关注的前端项目

综合/资源

  • frontend-dev-bookmarks 一个巨大的前端开发资源清单。star:15000
  • front-end-collect 分享自己长期关注的前端开发相关的优秀网站、博客、以及活跃开发者。star:860
  • Front-end-Interview-questions 史上最全前端开发面试问题及答案
  • f2e-hub 包含Animation,UI,dialog,Carousels,color,image,workflow等。star:100
  • awesome-javascript 一系列很棒的javascript 库,资源。star:3100
  • fks 前端技能汇总,包含前端知识架构,后端知识,linux,书籍推荐等。star:4000
  • node123 node.js中文资料导航。star:1200
  • mobile-web-favorites 移动端web开发收藏夹。star:200

样式/UI

  • Semantic-UI 让你使用任何HTML标签 来表现UI控件。
    这是一款语义化设计的前端框架,为攻城师而制作的可复用的开源前端框架。star:17500
  • primer CSS风格指南。star:3600

测试/工具

  • mocha 一个简单、灵活有趣的 JavaScript 测试框架,用于 Node.js 和浏览器上的 JavaScript 应用测试。 star:6680
  • csscss css代码冗余分析仪,用于分析冗余 。star:2800
  • es6-tools es6 工具集,包括Grunt Tasks,Gulp Plugins,Broccoli Plugins,Brunch Plugins,Webpack plugins等等。star:1860
  • async 一个工具模块,提供了直接而强大的 JavaScript 异步功能。虽然是为 Node.js 设计的,但是它也可以直接在浏览器中使用。star:13000
  • simditor 团队协作工具 Tower 使用的富文本编辑器。star:1300
  • HTMLHint HTML 静态代码分析工具,可以集成到IDE环境或编译系统中。star:900
  • jshint js静态代码分析工具,可以帮你检测js语法错误和潜在的问题。star:5100
  • csslint 分析和优化你的CSS样式表的工具。由Nicholas C.
    Zakas
    所写。star:2700

Workflow/构建工具

  • Grunt 基于Node.js的项目构建工具。拥有数量庞大的插件,是一款优秀的前端自动化工具。star:9500
  • yeoman 一个强健的工具,库,及工作流程的组合。star:960
  • gulp 基于node.js流的新一代前端构建系统。star:14000

canvas/数据可视化

  • echarts 基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。star:6900
  • Chart.js 使用<canvas>标签的简易HTML5图表。star:14600
  • sketch.js 跨平台JavaScript创意编码框架,gzip压缩后仅有2kb。star:1500
  • d3 一个基于数据操作文档的js数据可视化框架,最流行的可视化库之一。star:38000

模块管理/加载器

  • ESL 是一个浏览器端、符合AMD的标准加载器,适合用于现代Web浏览器端应用的入口与模块管理。

ESL vs RequireJS

体积更小 (Smaller)
性能更高 (Higher performance)
更健壮 (More Robustness)
不支持在非浏览器端使用 (Browser only)
依赖模块用时定义 (Lazy define)
  • seajs 一个遵循CommonJS规范的JavaScript模块加载器。提供简单、极致的模块化开发体验。star:4100

动画

  • animate.css 一个跨浏览器的CSS动画库。简单易用易上手。star:23000
  • move.js 极小的 JavaScript 库,支持 CSS3 的动画效果,非常简单优雅。star:2600
  • TweenJS 是一个简单但强大的 Javascript 动画库。CreateJS 套件的一部分。star:1500
  • bounce.js 一个用于制作漂亮的 CSS3 关键帧动画的 JavaScript
    库,使用其特有的方式生成的动画效果。star:3600

插件

  • zepto.fullpage 专注于移动端的全屏滚动插件。star:510
  • fullPage.js pc端的全屏滚动插件。 star:9500 view demo
  • onepage-scroll 可以轻松建立一个动感的响应式的滚动效果页面,比较适用于单页面的专题站。支持现代浏览器和IE8以上版本。View demostar:7700
  • slick 一款完全响应式的 jQuery 图片滚动插件,能够根据容器自动适应宽度。star:10000 view demo
  • superslides 致力于解决网站大部分特效展示问题。网站上常用的“焦点图/幻灯片”“Tab标签切换”“图片滚动”“无缝滚动”等只需要一个SuperSlide即可解决! view demo star:1100
  • jQuery-One-Page-Nav 当用户滚动网页时,实现平滑滚动和智能导航。star:1100
  • slider 一个jquery完全开源的JavaScript代码库,用户可以开发,调试和深度定制自己的滑块。star:850 view demo

框架、库和组件

  • polymer web组件构建框架。一套以“一切皆组件、最少化代码量、最少框架限制”为设计理念的Web UI框架。 star:9900
  • meteor 一个超简单的纯javascript web框架。用于自动化和简化实时运行的 Web 应用程序的开发。可直接在浏览器或者云平台中运行。 star:25300
  • impress.js 创建令人兴奋的演示。使用CSS3的转换和过渡,这个库允许你创建令人印象深刻的演示文稿。view demostar:24300
  • ionic 先进的HTML5 移动端开发框架。帮助开发者使用HTML5, CSS3和js做出不可思议的hybrid appstar:17000
  • reveal.js 基于CSS3的3D幻灯片工具。能够制作绚丽的演示文稿并生成HTML格式,将它发布到web上。star:21500 view demo
  • Modernizr 用来检测浏览器功能支持情况的JavaScript库,可以检测18项CSS3功能以及40多项关于HTML5的功能。star:16000
  • pure.css 一组很小的,响应式的css组件,你可以在网页的项目上到处使用。star:12000
  • three.jsJavaScript编写的WebGL第三方库。提供了非常多的3D显示功能。star:20000
  • TimelineJS 轻松制作时间轴。star:8000
  • jquery-pjaxajaxpushState的封装,让你可以很方便的使用pushState技术,用以实现页面无刷新加载。star:11500
  • highlight.js javascript语法高亮。既可以运行在浏览器端也可以运行在服务端。star:5500
  • commander.js Node.js命令行工具。star:3800
  • togetherjsMozilla打造的一款可以给网站添加实时协作功能的JavaScript库。star:5K
  • HTML.js 轻量级的简化与DOM操作的js库。view demo star:1.5K

MEAN.JS 全栈式javascript,使用MongoDB, Express, AngularJSNode.jsstar:2.2K

移动端

  • Swiper 加速移动触摸滑块与硬件之间的转换。star:5000
  • hammer.js 一个支持多点触摸的手势库。star:11000
  • amDoc 无线Web解决方案 - 文档规范指南

Node.js相关

  • nodeclub 使用 Node.jsMongoDB 开发的社区系统。star:3000
  • N-chat 使用 Express + Socket.IO 搭建的多人聊天室 。star:300
  • N-blog 使用 Express + MongoDB 搭建多人博客。star:1800
  • node-inspector 基于Blink开发者工具的Node.js调试器。star:7000
  • node-lessonsNode.js包教不包会。star:2.5K
  • nodePPT 使用nodejs写的网络幻灯片。可能是迄今为止最好的网页版PPTstar:1.6K view demo
  • hexo 一款快捷,简单,强大的博客框架,基于Nodejsstar:5.2K

React相关

HTML5

  • Browserquest: Mozilla开发的HTML5多人在线游戏。star:5200
  • video.js 开源的HTML5和Flash视频播放器。支持自定义进度条、按钮以及工具栏的底色。star:9.1K

其他

  • javascript-style-guide 最合理的使用javascript的方法。 star:18000
  • Mars 腾讯移动Web前端知识库。star:1600
  • css3please 跨浏览器自动生成css3前缀
  • brackets 一款使用 HTML,CSS,JavaScript 创建的开源的针对 Web 开发的编辑器。star:23000
  • normalize.css 一个可定制的 CSS 文件,使浏览器呈现的所有元素,更一致和符合现代标准。支持IE8+。star:17000
  • Ghost Node.js开发最新博客系统, 简单简洁, 响应式设计, 支持完全自定义, 免费, 专注博客。star:16000
  • io.jsNodeJS里分离出来的一条分支。star:13000
  • 2048 游戏 view demo star:7000
  • jade 一款高性能简洁易懂的模板引擎。star:8500

高产大牛

  • Evan You 前端轻量级框架MVVM框架vue.js作者,前Google工程师。followers:1.6K
  • TJ Holowaychuk Koa、Co、Express、jade、mocha、node-canvas、commander.js 等知名开源项目的创建和贡献者。 followers:14.1K
  • PaulIrish 著名的前端开发工程师,同时他也是Chrome开发者关系团队成员,jQuery团队成员,Modernizr、Yeoman、CSS3 PleaseHTML5 Boilerplatelead developerfollowers:15.7K
  • Mike Bostock 知名可视化库 D3.js的主要作者。followers:8.3K
  • Nicolas Gallagher Normalize.css 作者。followers:3.6K
  • 司徒正美 前端迷你MVVM框架Avalon作者。followers:2.1K

我的主页:http://segmentfault.com/u/trigkit4

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.