http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/_config.yml ---------------------------------------------------------------------- diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..26c27e9 --- /dev/null +++ b/_config.yml @@ -0,0 +1,71 @@ +# Hexo Configuration +## Docs: https://hexo.io/docs/configuration.html +## Source: https://github.com/hexojs/hexo/ + +# Site +title: Hexo +subtitle: +description: +author: John Doe +language: +timezone: + +# URL +## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/' +url: http://yoursite.com +root: / +permalink: :year/:month/:day/:title/ +permalink_defaults: + +# Directory +source_dir: source +public_dir: public +tag_dir: tags +archive_dir: archives +category_dir: categories +code_dir: downloads/code +i18n_dir: :lang +skip_render: + +# Writing +new_post_name: :title.md # File name of new posts +default_layout: post +titlecase: false # Transform title into titlecase +external_link: true # Open external links in new tab +filename_case: 0 +render_drafts: false +post_asset_folder: false +relative_link: false +future: true +highlight: + enable: true + line_number: true + auto_detect: false + tab_replace: + +# Category & Tag +default_category: uncategorized +category_map: +tag_map: + +# Date / Time format +## Hexo uses Moment.js to parse and display date +## You can customize the date format as defined in +## http://momentjs.com/docs/#/displaying/format/ +date_format: YYYY-MM-DD +time_format: HH:mm:ss + +# Pagination +## Set per_page to 0 to disable pagination +per_page: 10 +pagination_dir: page + +# Extensions +## Plugins: https://hexo.io/plugins/ +## Themes: https://hexo.io/themes/ +theme: landscape + +# Deployment +## Docs: https://hexo.io/docs/deployment.html +deploy: + type:
http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/db.json ---------------------------------------------------------------------- diff --git a/db.json b/db.json new file mode 100644 index 0000000..675a1dc --- /dev/null +++ b/db.json @@ -0,0 +1 @@ +{"meta":{"version":1,"warehouse":"2.2.0"},"models":{"Asset":[{"_id":"themes/landscape/source/css/style.styl","path":"css/style.styl","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/blank.gif","path":"fancybox/blank.gif","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/fancybox_loading.gif","path":"fancybox/fancybox_loading.gif","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/[email protected]","path":"fancybox/[email protected]","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/fancybox_overlay.png","path":"fancybox/fancybox_overlay.png","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/[email protected]","path":"fancybox/[email protected]","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/fancybox_sprite.png","path":"fancybox/fancybox_sprite.png","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.css"," path":"fancybox/jquery.fancybox.css","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.pack.js","path":"fancybox/jquery.fancybox.pack.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.js","path":"fancybox/jquery.fancybox.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/js/script.js","path":"js/script.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/fonts/FontAwesome.otf","path":"css/fonts/FontAwesome.otf","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.eot","path":"css/fonts/fontawesome-webfont.eot","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.woff","path":"css/fonts/fontawesome-webfont.woff","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/helpers/fancybox_buttons.png","path":"fancybox/helpers/fancybox_buttons.png","modified":0,"renderable":1},{"_id":"themes/lands cape/source/fancybox/helpers/jquery.fancybox-media.js","path":"fancybox/helpers/jquery.fancybox-media.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.css","path":"fancybox/helpers/jquery.fancybox-thumbs.css","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.js","path":"fancybox/helpers/jquery.fancybox-thumbs.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.css","path":"fancybox/helpers/jquery.fancybox-buttons.css","modified":0,"renderable":1},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.js","path":"fancybox/helpers/jquery.fancybox-buttons.js","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.ttf","path":"css/fonts/fontawesome-webfont.ttf","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.svg","path":"css/fonts/fo ntawesome-webfont.svg","modified":0,"renderable":1},{"_id":"themes/landscape/source/css/images/banner.jpg","path":"css/images/banner.jpg","modified":0,"renderable":1}],"Cache":[{"_id":"themes/landscape/.gitignore","hash":"58d26d4b5f2f94c2d02a4e4a448088e4a2527c77","modified":1490029954000},{"_id":"themes/landscape/LICENSE","hash":"c480fce396b23997ee23cc535518ffaaf7f458f8","modified":1490029954000},{"_id":"themes/landscape/README.md","hash":"c7e83cfe8f2c724fc9cac32bd71bb5faf9ceeddb","modified":1490029954000},{"_id":"themes/landscape/_config.yml","hash":"fb8c98a0f6ff9f962637f329c22699721854cd73","modified":1490029954000},{"_id":"themes/landscape/package.json","hash":"85358dc34311c6662e841584e206a4679183943f","modified":1490029954000},{"_id":"themes/landscape/Gruntfile.js","hash":"71adaeaac1f3cc56e36c49d549b8d8a72235c9b9","modified":1490029954000},{"_id":"source/_posts/hello.md","hash":"ee65bc00faf8e1730426d221f5ddc5d9ac0eaeae","modified":1490030414000},{"_id":"source/_posts/hello-world .md","hash":"8a02477044e2b77f1b262da2c48c01429e4a32e4","modified":1490029946000},{"_id":"themes/landscape/layout/archive.ejs","hash":"2703b07cc8ac64ae46d1d263f4653013c7e1666b","modified":1490029954000},{"_id":"themes/landscape/layout/category.ejs","hash":"765426a9c8236828dc34759e604cc2c52292835a","modified":1490029954000},{"_id":"themes/landscape/layout/index.ejs","hash":"aa1b4456907bdb43e629be3931547e2d29ac58c8","modified":1490029954000},{"_id":"themes/landscape/layout/layout.ejs","hash":"f155824ca6130080bb057fa3e868a743c69c4cf5","modified":1490029954000},{"_id":"themes/landscape/layout/page.ejs","hash":"7d80e4e36b14d30a7cd2ac1f61376d9ebf264e8b","modified":1490029954000},{"_id":"themes/landscape/layout/post.ejs","hash":"7d80e4e36b14d30a7cd2ac1f61376d9ebf264e8b","modified":1490029954000},{"_id":"themes/landscape/layout/tag.ejs","hash":"eaa7b4ccb2ca7befb90142e4e68995fb1ea68b2e","modified":1490029954000},{"_id":"themes/landscape/languages/fr.yml","hash":"84ab164b37c6abf625473e9a0c18f6 f815dd5fd9","modified":1490029954000},{"_id":"themes/landscape/languages/nl.yml","hash":"12ed59faba1fc4e8cdd1d42ab55ef518dde8039c","modified":1490029954000},{"_id":"themes/landscape/languages/no.yml","hash":"965a171e70347215ec726952e63f5b47930931ef","modified":1490029954000},{"_id":"themes/landscape/languages/ru.yml","hash":"4fda301bbd8b39f2c714e2c934eccc4b27c0a2b0","modified":1490029954000},{"_id":"themes/landscape/languages/zh-CN.yml","hash":"ca40697097ab0b3672a80b455d3f4081292d1eed","modified":1490029954000},{"_id":"themes/landscape/languages/zh-TW.yml","hash":"53ce3000c5f767759c7d2c4efcaa9049788599c3","modified":1490029954000},{"_id":"themes/landscape/languages/default.yml","hash":"3083f319b352d21d80fc5e20113ddf27889c9d11","modified":1490029954000},{"_id":"themes/landscape/scripts/fancybox.js","hash":"aa411cd072399df1ddc8e2181a3204678a5177d9","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/article.ejs","hash":"c4c835615d96a950d51fa2c3b5d64d0596534fed","modifie d":1490029954000},{"_id":"themes/landscape/layout/_partial/archive.ejs","hash":"931aaaffa0910a48199388ede576184ff15793ee","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/google-analytics.ejs","hash":"f921e7f9223d7c95165e0f835f353b2938e40c45","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/head.ejs","hash":"4fe8853e864d192701c03e5cd3a5390287b90612","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/header.ejs","hash":"c21ca56f419d01a9f49c27b6be9f4a98402b2aa3","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/sidebar.ejs","hash":"930da35cc2d447a92e5ee8f835735e6fd2232469","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/after-footer.ejs","hash":"82a30f81c0e8ba4a8af17acd6cc99e93834e4d5e","modified":1490029954000},{"_id":"themes/landscape/layout/_widget/category.ejs","hash":"dd1e5af3c6af3f5d6c85dfd5ca1766faed6a0b05","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/archive-post.ejs", "hash":"c7a71425a946d05414c069ec91811b5c09a92c47","modified":1490029954000},{"_id":"themes/landscape/layout/_widget/tag.ejs","hash":"2de380865df9ab5f577f7d3bcadf44261eb5faae","modified":1490029954000},{"_id":"themes/landscape/layout/_widget/tagcloud.ejs","hash":"b4a2079101643f63993dcdb32925c9b071763b46","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/footer.ejs","hash":"93518893cf91287e797ebac543c560e2a63b8d0e","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/mobile-nav.ejs","hash":"e952a532dfc583930a666b9d4479c32d4a84b44e","modified":1490029954000},{"_id":"themes/landscape/layout/_widget/archive.ejs","hash":"beb4a86fcc82a9bdda9289b59db5a1988918bec3","modified":1490029954000},{"_id":"themes/landscape/layout/_widget/recent_posts.ejs","hash":"0d4f064733f8b9e45c0ce131fe4a689d570c883a","modified":1490029954000},{"_id":"themes/landscape/source/css/_extend.styl","hash":"222fbe6d222531d61c1ef0f868c90f747b1c2ced","modified":1490029954000},{"_id":"themes/ landscape/source/css/_variables.styl","hash":"5e37a6571caf87149af83ac1cc0cdef99f117350","modified":1490029954000},{"_id":"themes/landscape/source/css/style.styl","hash":"a70d9c44dac348d742702f6ba87e5bb3084d65db","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/blank.gif","hash":"2daeaa8b5f19f0bc209d976c02bd6acb51b00b0a","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/fancybox_loading.gif","hash":"1a755fb2599f3a313cc6cfdb14df043f8c14a99c","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/[email protected]","hash":"273b123496a42ba45c3416adb027cd99745058b0","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/fancybox_overlay.png","hash":"b3a4ee645ba494f52840ef8412015ba0f465dbe0","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/[email protected]","hash":"30c58913f327e28f466a00f4c1ac8001b560aed8","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/fancybox_sprite.png","hash":" 17df19f97628e77be09c352bf27425faea248251","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.css","hash":"aaa582fb9eb4b7092dc69fcb2d5b1c20cca58ab6","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.pack.js","hash":"9e0d51ca1dbe66f6c0c7aefd552dc8122e694a6e","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/jquery.fancybox.js","hash":"d08b03a42d5c4ba456ef8ba33116fdbb7a9cabed","modified":1490029954000},{"_id":"themes/landscape/source/js/script.js","hash":"2876e0b19ce557fca38d7c6f49ca55922ab666a1","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/post/gallery.ejs","hash":"3d9d81a3c693ff2378ef06ddb6810254e509de5b","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/post/nav.ejs","hash":"16a904de7bceccbb36b4267565f2215704db2880","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/post/tag.ejs","hash":"2fcb0bf9c8847a644167a27824c9bb19ac74dd14","modified":14900299 54000},{"_id":"themes/landscape/layout/_partial/post/title.ejs","hash":"2f275739b6f1193c123646a5a31f37d48644c667","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/post/category.ejs","hash":"c6bcd0e04271ffca81da25bcff5adf3d46f02fc0","modified":1490029954000},{"_id":"themes/landscape/layout/_partial/post/date.ejs","hash":"6197802873157656e3077c5099a7dda3d3b01c29","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/archive.styl","hash":"db15f5677dc68f1730e82190bab69c24611ca292","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/article.styl","hash":"10685f8787a79f79c9a26c2f943253450c498e3e","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/comment.styl","hash":"79d280d8d203abb3bd933ca9b8e38c78ec684987","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/footer.styl","hash":"e35a060b8512031048919709a8e7b1ec0e40bc1b","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/heade r.styl","hash":"85ab11e082f4dd86dde72bed653d57ec5381f30c","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/highlight.styl","hash":"bf4e7be1968dad495b04e83c95eac14c4d0ad7c0","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/mobile.styl","hash":"a399cf9e1e1cec3e4269066e2948d7ae5854d745","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/sidebar-bottom.styl","hash":"8fd4f30d319542babfd31f087ddbac550f000a8a","modified":1490029954000},{"_id":"themes/landscape/source/css/_util/grid.styl","hash":"0bf55ee5d09f193e249083602ac5fcdb1e571aed","modified":1490029954000},{"_id":"themes/landscape/source/css/fonts/FontAwesome.otf","hash":"b5b4f9be85f91f10799e87a083da1d050f842734","modified":1490029954000},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.eot","hash":"7619748fe34c64fb157a57f6d4ef3678f63a8f5e","modified":1490029954000},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.woff","hash":"04c3bf56d87a08289 35bd6b4aee859995f321693","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/sidebar-aside.styl","hash":"890349df5145abf46ce7712010c89237900b3713","modified":1490029954000},{"_id":"themes/landscape/source/css/_partial/sidebar.styl","hash":"404ec059dc674a48b9ab89cd83f258dec4dcb24d","modified":1490029954000},{"_id":"themes/landscape/source/css/_util/mixin.styl","hash":"44f32767d9fd3c1c08a60d91f181ee53c8f0dbb3","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/fancybox_buttons.png","hash":"e385b139516c6813dcd64b8fc431c364ceafe5f3","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-media.js","hash":"294420f9ff20f4e3584d212b0c262a00a96ecdb3","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.css","hash":"4ac329c16a5277592fc12a37cca3d72ca4ec292f","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.js","hash":"47da1 ae5401c24b5c17cc18e2730780f5c1a7a0c","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.css","hash":"1a9d8e5c22b371fcc69d4dbbb823d9c39f04c0c8","modified":1490029954000},{"_id":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.js","hash":"dc3645529a4bf72983a39fa34c1eb9146e082019","modified":1490029954000},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.ttf","hash":"7f09c97f333917034ad08fa7295e916c9f72fd3f","modified":1490029954000},{"_id":"themes/landscape/source/css/fonts/fontawesome-webfont.svg","hash":"46fcc0194d75a0ddac0a038aee41b23456784814","modified":1490029954000},{"_id":"themes/landscape/source/css/images/banner.jpg","hash":"f44aa591089fcb3ec79770a1e102fd3289a7c6a6","modified":1490029954000}],"Category":[],"Data":[],"Page":[],"Post":[{"title":"hello","date":"2017-03-20T17:20:14.000Z","_content":"","source":"_posts/hello.md","raw":"---\ntitle: hello\ndate: 2017-03-20 10:20:14\ntags:\n---\n","slug":" hello","published":1,"updated":"2017-03-20T17:20:14.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cj0ief9mp0000i3pozs4qmmyx","content":"","excerpt":"","more":""},{"title":"Hello World","_content":"Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\n$ hexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\n$ hexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\n$ hexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\n$ hexo deploy\n```\n\nMore info : [Deployment](https://hexo.io/docs/deployment.html)\n","source":"_posts/hello-world.md","raw":"---\ntitle: Hello World\n---\nWelcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\n$ hexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\n$ hexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\n$ hexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\n$ hexo deploy\n```\n\nMore info: [Deployment](https://hexo.io/docs/deployment.html)\n","slug":"hello-world","published": 1,"date":"2017-03-20T17:12:26.000Z","updated":"2017-03-20T17:12:26.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cj0ief9mt0001i3po2si4b8t3","content":"<p>Welcome to <a href=\"https://hexo.io/\" target=\"_blank\" rel=\"external\">Hexo</a>! This is your very first post. Check <a href=\"https://hexo.io/docs/\" target=\"_blank\" rel=\"external\">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href=\"https://hexo.io/docs/troubleshooting.html\" target=\"_blank\" rel=\"external\">troubleshooting</a> or you can ask me on <a href=\"https://github.com/hexojs/hexo/issues\" target=\"_blank\" rel=\"external\">GitHub</a>.</p>\n<h2 id=\"Quick-Start\"><a href=\"#Quick-Start\" class=\"headerlink\" title=\"Quick Start\"></a>Quick Start</h2><h3 id=\"Create-a-new-post\"><a href=\"#Create-a-new-post\" class=\"headerlink\" title=\"Create a new post\"></a>Create a new post</h3><figure class=\"highlight bash\"><table><tr><td class=\" gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo new <span class=\"string\">\"My New Post\"</span></div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/writing.html\" target=\"_blank\" rel=\"external\">Writing</a></p>\n<h3 id=\"Run-server\"><a href=\"#Run-server\" class=\"headerlink\" title=\"Run server\"></a>Run server</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo server</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/server.html\" target=\"_blank\" rel=\"external\">Server</a></p>\n<h3 id=\"Generate-static-files\"><a href=\"#Generate-static-files\" class=\"headerlink\" title=\"Generate static files\"></a>Generate static files</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class= \"code\"><pre><div class=\"line\">$ hexo generate</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/generating.html\" target=\"_blank\" rel=\"external\">Generating</a></p>\n<h3 id=\"Deploy-to-remote-sites\"><a href=\"#Deploy-to-remote-sites\" class=\"headerlink\" title=\"Deploy to remote sites\"></a>Deploy to remote sites</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo deploy</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/deployment.html\" target=\"_blank\" rel=\"external\">Deployment</a></p>\n","excerpt":"","more":"<p>Welcome to <a href=\"https://hexo.io/\">Hexo</a>! This is your very first post. Check <a href=\"https://hexo.io/docs/\">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href=\"https://hexo.io/docs/troubleshooting.html\">troublesh ooting</a> or you can ask me on <a href=\"https://github.com/hexojs/hexo/issues\">GitHub</a>.</p>\n<h2 id=\"Quick-Start\"><a href=\"#Quick-Start\" class=\"headerlink\" title=\"Quick Start\"></a>Quick Start</h2><h3 id=\"Create-a-new-post\"><a href=\"#Create-a-new-post\" class=\"headerlink\" title=\"Create a new post\"></a>Create a new post</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo new <span class=\"string\">\"My New Post\"</span></div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/writing.html\">Writing</a></p>\n<h3 id=\"Run-server\"><a href=\"#Run-server\" class=\"headerlink\" title=\"Run server\"></a>Run server</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo server</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/server.html\">Server</a></p>\n<h3 id=\"Generate-static-files\"><a href=\"#Generate-static-files\" class=\"headerlink\" title=\"Generate static files\"></a>Generate static files</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo generate</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/generating.html\">Generating</a></p>\n<h3 id=\"Deploy-to-remote-sites\"><a href=\"#Deploy-to-remote-sites\" class=\"headerlink\" title=\"Deploy to remote sites\"></a>Deploy to remote sites</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><div class=\"line\">1</div></pre></td><td class=\"code\"><pre><div class=\"line\">$ hexo deploy</div></pre></td></tr></table></figure>\n<p>More info: <a href=\"https://hexo.io/docs/deployment.html\">Deployment</a></p>\n"}],"PostAsset":[],"PostCategory":[],"PostTag":[] ,"Tag":[]}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/.bin/JSONStream ---------------------------------------------------------------------- diff --git a/node_modules/.bin/JSONStream b/node_modules/.bin/JSONStream new file mode 100755 index 0000000..6d68a19 --- /dev/null +++ b/node_modules/.bin/JSONStream @@ -0,0 +1,253 @@ +#! /usr/bin/env node + +'use strict' + +var Parser = require('jsonparse') + , through = require('through') + +/* + + the value of this.stack that creationix's jsonparse has is weird. + + it makes this code ugly, but his problem is way harder that mine, + so i'll forgive him. + +*/ + +exports.parse = function (path, map) { + var header, footer + var parser = new Parser() + var stream = through(function (chunk) { + if('string' === typeof chunk) + chunk = new Buffer(chunk) + parser.write(chunk) + }, + function (data) { + if(data) + stream.write(data) + if (header) + stream.emit('header', header) + if (footer) + stream.emit('footer', footer) + stream.queue(null) + }) + + if('string' === typeof path) + path = path.split('.').map(function (e) { + if (e === '$*') + return {emitKey: true} + else if (e === '*') + return true + else if (e === '') // '..'.split('.') returns an empty string + return {recurse: true} + else + return e + }) + + + var count = 0, _key + if(!path || !path.length) + path = null + + parser.onValue = function (value) { + if (!this.root) + stream.root = value + + if(! path) return + + var i = 0 // iterates on path + var j = 0 // iterates on stack + var emitKey = false; + var emitPath = false; + while (i < path.length) { + var key = path[i] + var c + j++ + + if (key && !key.recurse) { + c = (j === this.stack.length) ? this : this.stack[j] + if (!c) return + if (! check(key, c.key)) { + setHeaderFooter(c.key, value) + return + } + emitKey = !!key.emitKey; + emitPath = !!key.emitPath; + i++ + } else { + i++ + var nextKey = path[i] + if (! nextKey) return + while (true) { + c = (j === this.stack.length) ? this : this.stack[j] + if (!c) return + if (check(nextKey, c.key)) { + i++; + if (!Object.isFrozen(this.stack[j])) + this.stack[j].value = null + break + } else { + setHeaderFooter(c.key, value) + } + j++ + } + } + + } + + // emit header + if (header) { + stream.emit('header', header); + header = false; + } + if (j !== this.stack.length) return + + count ++ + var actualPath = this.stack.slice(1).map(function(element) { return element.key }).concat([this.key]) + var data = this.value[this.key] + if(null != data) + if(null != (data = map ? map(data, actualPath) : data)) { + if (emitKey || emitPath) { + data = { value: data }; + if (emitKey) + data["key"] = this.key; + if (emitPath) + data["path"] = actualPath; + } + + stream.queue(data) + } + delete this.value[this.key] + for(var k in this.stack) + if (!Object.isFrozen(this.stack[k])) + this.stack[k].value = null + } + parser._onToken = parser.onToken; + + parser.onToken = function (token, value) { + parser._onToken(token, value); + if (this.stack.length === 0) { + if (stream.root) { + if(!path) + stream.queue(stream.root) + count = 0; + stream.root = null; + } + } + } + + parser.onError = function (err) { + if(err.message.indexOf("at position") > -1) + err.message = "Invalid JSON (" + err.message + ")"; + stream.emit('error', err) + } + + return stream + + function setHeaderFooter(key, value) { + // header has not been emitted yet + if (header !== false) { + header = header || {} + header[key] = value + } + + // footer has not been emitted yet but header has + if (footer !== false && header === false) { + footer = footer || {} + footer[key] = value + } + } +} + +function check (x, y) { + if ('string' === typeof x) + return y == x + else if (x && 'function' === typeof x.exec) + return x.exec(y) + else if ('boolean' === typeof x || 'object' === typeof x) + return x + else if ('function' === typeof x) + return x(y) + return false +} + +exports.stringify = function (op, sep, cl, indent) { + indent = indent || 0 + if (op === false){ + op = '' + sep = '\n' + cl = '' + } else if (op == null) { + + op = '[\n' + sep = '\n,\n' + cl = '\n]\n' + + } + + //else, what ever you like + + var stream + , first = true + , anyData = false + stream = through(function (data) { + anyData = true + try { + var json = JSON.stringify(data, null, indent) + } catch (err) { + return stream.emit('error', err) + } + if(first) { first = false ; stream.queue(op + json)} + else stream.queue(sep + json) + }, + function (data) { + if(!anyData) + stream.queue(op) + stream.queue(cl) + stream.queue(null) + }) + + return stream +} + +exports.stringifyObject = function (op, sep, cl, indent) { + indent = indent || 0 + if (op === false){ + op = '' + sep = '\n' + cl = '' + } else if (op == null) { + + op = '{\n' + sep = '\n,\n' + cl = '\n}\n' + + } + + //else, what ever you like + + var first = true + var anyData = false + var stream = through(function (data) { + anyData = true + var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent) + if(first) { first = false ; this.queue(op + json)} + else this.queue(sep + json) + }, + function (data) { + if(!anyData) this.queue(op) + this.queue(cl) + + this.queue(null) + }) + + return stream +} + +if(!module.parent && process.title !== 'browser') { + process.stdin + .pipe(exports.parse(process.argv[2])) + .pipe(exports.stringify('[', ',\n', ']\n', 2)) + .pipe(process.stdout) +} + http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/.bin/acorn ---------------------------------------------------------------------- diff --git a/node_modules/.bin/acorn b/node_modules/.bin/acorn new file mode 100755 index 0000000..db07909 --- /dev/null +++ b/node_modules/.bin/acorn @@ -0,0 +1,71 @@ +#!/usr/bin/env node +"use strict"; + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } } + +var _path = require("path"); + +var _fs = require("fs"); + +var _distAcornJs = require("../dist/acorn.js"); + +var acorn = _interopRequireWildcard(_distAcornJs); + +var infile = undefined, + forceFile = undefined, + silent = false, + compact = false, + tokenize = false; +var options = {}; + +function help(status) { + var print = status == 0 ? console.log : console.error; + print("usage: " + (0, _path.basename)(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]"); + print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]"); + process.exit(status); +} + +for (var i = 2; i < process.argv.length; ++i) { + var arg = process.argv[i]; + if ((arg == "-" || arg[0] != "-") && !infile) infile = arg;else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i];else if (arg == "--ecma3") options.ecmaVersion = 3;else if (arg == "--ecma5") options.ecmaVersion = 5;else if (arg == "--ecma6") options.ecmaVersion = 6;else if (arg == "--locations") options.locations = true;else if (arg == "--allow-hash-bang") options.allowHashBang = true;else if (arg == "--silent") silent = true;else if (arg == "--compact") compact = true;else if (arg == "--help") help(0);else if (arg == "--tokenize") tokenize = true;else if (arg == "--module") options.sourceType = 'module';else help(1); +} + +function run(code) { + var result = undefined; + if (!tokenize) { + try { + result = acorn.parse(code, options); + } catch (e) { + console.error(e.message);process.exit(1); + } + } else { + result = []; + var tokenizer = acorn.tokenizer(code, options), + token = undefined; + while (true) { + try { + token = tokenizer.getToken(); + } catch (e) { + console.error(e.message);process.exit(1); + } + result.push(token); + if (token.type == acorn.tokTypes.eof) break; + } + } + if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)); +} + +if (forceFile || infile && infile != "-") { + run((0, _fs.readFileSync)(infile, "utf8")); +} else { + (function () { + var code = ""; + process.stdin.resume(); + process.stdin.on("data", function (chunk) { + return code += chunk; + }); + process.stdin.on("end", function () { + return run(code); + }); + })(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-griffin-site/blob/4f8fa326/node_modules/.bin/bunyan ---------------------------------------------------------------------- diff --git a/node_modules/.bin/bunyan b/node_modules/.bin/bunyan new file mode 100755 index 0000000..73cf458 --- /dev/null +++ b/node_modules/.bin/bunyan @@ -0,0 +1,1665 @@ +#!/usr/bin/env node +/** + * Copyright 2016 Trent Mick + * Copyright 2016 Joyent Inc. + * + * bunyan -- filter and pretty-print Bunyan log files (line-delimited JSON) + * + * See <https://github.com/trentm/node-bunyan>. + * + * -*- mode: js -*- + * vim: expandtab:ts=4:sw=4 + */ + +var VERSION = '1.8.8'; + +var p = console.log; +var util = require('util'); +var pathlib = require('path'); +var vm = require('vm'); +var http = require('http'); +var fs = require('fs'); +var warn = console.warn; +var child_process = require('child_process'), + spawn = child_process.spawn, + exec = child_process.exec, + execFile = child_process.execFile; +var assert = require('assert'); + +try { + var moment = require('moment'); +} catch (e) { + moment = null; +} + + +//---- globals and constants + +var nodeVer = process.versions.node.split('.').map(Number); +var nodeSpawnSupportsStdio = (nodeVer[0] > 0 || nodeVer[1] >= 8); + +// Internal debug logging via `console.warn`. +var _DEBUG = false; + +// Output modes. +var OM_LONG = 1; +var OM_JSON = 2; +var OM_INSPECT = 3; +var OM_SIMPLE = 4; +var OM_SHORT = 5; +var OM_BUNYAN = 6; +var OM_FROM_NAME = { + 'long': OM_LONG, + 'paul': OM_LONG, /* backward compat */ + 'json': OM_JSON, + 'inspect': OM_INSPECT, + 'simple': OM_SIMPLE, + 'short': OM_SHORT, + 'bunyan': OM_BUNYAN +}; + + +// Levels +var TRACE = 10; +var DEBUG = 20; +var INFO = 30; +var WARN = 40; +var ERROR = 50; +var FATAL = 60; + +var levelFromName = { + 'trace': TRACE, + 'debug': DEBUG, + 'info': INFO, + 'warn': WARN, + 'error': ERROR, + 'fatal': FATAL +}; +var nameFromLevel = {}; +var upperNameFromLevel = {}; +var upperPaddedNameFromLevel = {}; +Object.keys(levelFromName).forEach(function (name) { + var lvl = levelFromName[name]; + nameFromLevel[lvl] = name; + upperNameFromLevel[lvl] = name.toUpperCase(); + upperPaddedNameFromLevel[lvl] = ( + name.length === 4 ? ' ' : '') + name.toUpperCase(); +}); + + +// Display time formats. +var TIME_UTC = 1; // the default, bunyan's native format +var TIME_LOCAL = 2; + +// Timezone formats: output format -> momentjs format string +var TIMEZONE_UTC_FORMATS = { + long: '[[]YYYY-MM-DD[T]HH:mm:ss.SSS[Z][]]', + short: 'HH:mm:ss.SSS[Z]' +}; +var TIMEZONE_LOCAL_FORMATS = { + long: '[[]YYYY-MM-DD[T]HH:mm:ss.SSSZ[]]', + short: 'HH:mm:ss.SSS' +}; + + +// The current raw input line being processed. Used for `uncaughtException`. +var currLine = null; + +// Child dtrace process, if any. Used for signal-handling. +var child = null; + +// Whether ANSI codes are being used. Used for signal-handling. +var usingAnsiCodes = false; + +// Used to tell the 'uncaughtException' handler that '-c CODE' is being used. +var gUsingConditionOpts = false; + +// Pager child process, and output stream to which to write. +var pager = null; +var stdout = process.stdout; + +// Whether we are reading from stdin. +var readingStdin = false; + + + +//---- support functions + +function getVersion() { + return VERSION; +} + + +var format = util.format; +if (!format) { + /* BEGIN JSSTYLED */ + // If not node 0.6, then use its `util.format`: + // <https://github.com/joyent/node/blob/master/lib/util.js#L22>: + var inspect = util.inspect; + var formatRegExp = /%[sdj%]/g; + format = function format(f) { + if (typeof f !== 'string') { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function (x) { + if (i >= len) + return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': return JSON.stringify(args[i++]); + case '%%': return '%'; + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (x === null || typeof x !== 'object') { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; + }; + /* END JSSTYLED */ +} + +function indent(s) { + return ' ' + s.split(/\r?\n/).join('\n '); +} + +function objCopy(obj) { + if (obj === null) { + return null; + } else if (Array.isArray(obj)) { + return obj.slice(); + } else { + var copy = {}; + Object.keys(obj).forEach(function (k) { + copy[k] = obj[k]; + }); + return copy; + } +} + +function printHelp() { + /* BEGIN JSSTYLED */ + p('Usage:'); + p(' bunyan [OPTIONS] [FILE ...]'); + p(' ... | bunyan [OPTIONS]'); + p(' bunyan [OPTIONS] -p PID'); + p(''); + p('Filter and pretty-print Bunyan log file content.'); + p(''); + p('General options:'); + p(' -h, --help print this help info and exit'); + p(' --version print version of this command and exit'); + p(''); + p('Runtime log snooping (via DTrace, only on supported platforms):'); + p(' -p PID Process bunyan:log-* probes from the process'); + p(' with the given PID. Can be used multiple times,'); + p(' or specify all processes with "*", or a set of'); + p(' processes whose command & args match a pattern'); + p(' with "-p NAME".'); + p(''); + p('Filtering options:'); + p(' -l, --level LEVEL'); + p(' Only show messages at or above the specified level.'); + p(' You can specify level *names* or the internal numeric'); + p(' values.'); + p(' -c, --condition CONDITION'); + p(' Run each log message through the condition and'); + p(' only show those that return truish. E.g.:'); + p(' -c \'this.pid == 123\''); + p(' -c \'this.level == DEBUG\''); + p(' -c \'this.msg.indexOf("boom") != -1\''); + p(' "CONDITION" must be legal JS code. `this` holds'); + p(' the log record. The TRACE, DEBUG, ... FATAL values'); + p(' are defined to help with comparing `this.level`.'); + p(' --strict Suppress all but legal Bunyan JSON log lines. By default'); + p(' non-JSON, and non-Bunyan lines are passed through.'); + p(''); + p('Output options:'); + p(' --pager Pipe output into `less` (or $PAGER if set), if'); + p(' stdout is a TTY. This overrides $BUNYAN_NO_PAGER.'); + p(' Note: Paging is only supported on node >=0.8.'); + p(' --no-pager Do not pipe output into a pager.'); + p(' --color Colorize output. Defaults to try if output'); + p(' stream is a TTY.'); + p(' --no-color Force no coloring (e.g. terminal doesn\'t support it)'); + p(' -o, --output MODE'); + p(' Specify an output mode/format. One of'); + p(' long: (the default) pretty'); + p(' json: JSON output, 2-space indent'); + p(' json-N: JSON output, N-space indent, e.g. "json-4"'); + p(' bunyan: 0 indented JSON, bunyan\'s native format'); + p(' inspect: node.js `util.inspect` output'); + p(' short: like "long", but more concise'); + p(' simple: level, followed by "-" and then the message'); + p(' -j shortcut for `-o json`'); + p(' -0 shortcut for `-o bunyan`'); + p(' -L, --time local'); + p(' Display time field in local time, rather than UTC.'); + p(''); + p('Environment Variables:'); + p(' BUNYAN_NO_COLOR Set to a non-empty value to force no output '); + p(' coloring. See "--no-color".'); + p(' BUNYAN_NO_PAGER Disable piping output to a pager. '); + p(' See "--no-pager".'); + p(''); + p('See <https://github.com/trentm/node-bunyan> for more complete docs.'); + p('Please report bugs to <https://github.com/trentm/node-bunyan/issues>.'); + /* END JSSTYLED */ +} + +/* + * If the user specifies multiple input sources, we want to print out records + * from all sources in a single, chronologically ordered stream. To do this + * efficiently, we first assume that all records within each source are ordered + * already, so we need only keep track of the next record in each source and + * the time of the last record emitted. To avoid excess memory usage, we + * pause() streams that are ahead of others. + * + * 'streams' is an object indexed by source name (file name) which specifies: + * + * stream Actual stream object, so that we can pause and resume it. + * + * records Array of log records we've read, but not yet emitted. Each + * record includes 'line' (the raw line), 'rec' (the JSON + * record), and 'time' (the parsed time value). + * + * done Whether the stream has any more records to emit. + */ +var streams = {}; + +function gotRecord(file, line, rec, opts, stylize) +{ + var time = new Date(rec.time); + + streams[file]['records'].push({ line: line, rec: rec, time: time }); + emitNextRecord(opts, stylize); +} + +function filterRecord(rec, opts) +{ + if (opts.level && rec.level < opts.level) { + return false; + } + + if (opts.condFuncs) { + var recCopy = objCopy(rec); + for (var i = 0; i < opts.condFuncs.length; i++) { + var pass = opts.condFuncs[i].call(recCopy); + if (!pass) + return false; + } + } else if (opts.condVm) { + for (var i = 0; i < opts.condVm.length; i++) { + var pass = opts.condVm[i].runInNewContext(rec); + if (!pass) + return false; + } + } + + return true; +} + +function emitNextRecord(opts, stylize) +{ + var ofile, ready, minfile, rec; + + for (;;) { + /* + * Take a first pass through the input streams to see if we have a + * record from all of them. If not, we'll pause any streams for + * which we do already have a record (to avoid consuming excess + * memory) and then wait until we have records from the others + * before emitting the next record. + * + * As part of the same pass, we look for the earliest record + * we have not yet emitted. + */ + minfile = undefined; + ready = true; + for (ofile in streams) { + + if (streams[ofile].stream === null || + (!streams[ofile].done && streams[ofile].records.length === 0)) { + ready = false; + break; + } + + if (streams[ofile].records.length > 0 && + (minfile === undefined || + streams[minfile].records[0].time > + streams[ofile].records[0].time)) { + minfile = ofile; + } + } + + if (!ready || minfile === undefined) { + for (ofile in streams) { + if (!streams[ofile].stream || streams[ofile].done) + continue; + + if (streams[ofile].records.length > 0) { + if (!streams[ofile].paused) { + streams[ofile].paused = true; + streams[ofile].stream.pause(); + } + } else if (streams[ofile].paused) { + streams[ofile].paused = false; + streams[ofile].stream.resume(); + } + } + + return; + } + + /* + * Emit the next record for 'minfile', and invoke ourselves again to + * make sure we emit as many records as we can right now. + */ + rec = streams[minfile].records.shift(); + emitRecord(rec.rec, rec.line, opts, stylize); + } +} + +/** + * Return a function for the given JS code that returns. + * + * If no 'return' in the given javascript snippet, then assume we are a single + * statement and wrap in 'return (...)'. This is for convenience for short + * '-c ...' snippets. + */ +function funcWithReturnFromSnippet(js) { + // auto-"return" + if (js.indexOf('return') === -1) { + if (js.substring(js.length - 1) === ';') { + js = js.substring(0, js.length - 1); + } + js = 'return (' + js + ')'; + } + + // Expose level definitions to condition func context + var varDefs = []; + Object.keys(upperNameFromLevel).forEach(function (lvl) { + varDefs.push(format('var %s = %d;', + upperNameFromLevel[lvl], lvl)); + }); + varDefs = varDefs.join('\n') + '\n'; + + return (new Function(varDefs + js)); +} + +/** + * Parse the command-line options and arguments into an object. + * + * { + * 'args': [...] // arguments + * 'help': true, // true if '-h' option given + * // etc. + * } + * + * @return {Object} The parsed options. `.args` is the argument list. + * @throws {Error} If there is an error parsing argv. + */ +function parseArgv(argv) { + var parsed = { + args: [], + help: false, + color: null, + paginate: null, + outputMode: OM_LONG, + jsonIndent: 2, + level: null, + strict: false, + pids: null, + pidsType: null, + timeFormat: TIME_UTC // one of the TIME_ constants + }; + + // Turn '-iH' into '-i -H', except for argument-accepting options. + var args = argv.slice(2); // drop ['node', 'scriptname'] + var newArgs = []; + var optTakesArg = {'d': true, 'o': true, 'c': true, 'l': true, 'p': true}; + for (var i = 0; i < args.length; i++) { + if (args[i].charAt(0) === '-' && args[i].charAt(1) !== '-' && + args[i].length > 2) + { + var splitOpts = args[i].slice(1).split(''); + for (var j = 0; j < splitOpts.length; j++) { + newArgs.push('-' + splitOpts[j]); + if (optTakesArg[splitOpts[j]]) { + var optArg = splitOpts.slice(j+1).join(''); + if (optArg.length) { + newArgs.push(optArg); + } + break; + } + } + } else { + newArgs.push(args[i]); + } + } + args = newArgs; + + // Expose level definitions to condition vm context + var condDefines = []; + Object.keys(upperNameFromLevel).forEach(function (lvl) { + condDefines.push( + format('Object.prototype.%s = %s;', upperNameFromLevel[lvl], lvl)); + }); + condDefines = condDefines.join('\n') + '\n'; + + var endOfOptions = false; + while (args.length > 0) { + var arg = args.shift(); + switch (arg) { + case '--': + endOfOptions = true; + break; + case '-h': // display help and exit + case '--help': + parsed.help = true; + break; + case '--version': + parsed.version = true; + break; + case '--strict': + parsed.strict = true; + break; + case '--color': + parsed.color = true; + break; + case '--no-color': + parsed.color = false; + break; + case '--pager': + parsed.paginate = true; + break; + case '--no-pager': + parsed.paginate = false; + break; + case '-o': + case '--output': + var name = args.shift(); + var idx = name.lastIndexOf('-'); + if (idx !== -1) { + var indentation = Number(name.slice(idx+1)); + if (! isNaN(indentation)) { + parsed.jsonIndent = indentation; + name = name.slice(0, idx); + } + } + parsed.outputMode = OM_FROM_NAME[name]; + if (parsed.outputMode === undefined) { + throw new Error('unknown output mode: "'+name+'"'); + } + break; + case '-j': // output with JSON.stringify + parsed.outputMode = OM_JSON; + break; + case '-0': + parsed.outputMode = OM_BUNYAN; + break; + case '-L': + parsed.timeFormat = TIME_LOCAL; + if (!moment) { + throw new Error( + 'could not find moment package required for "-L"'); + } + break; + case '--time': + var timeArg = args.shift(); + switch (timeArg) { + case 'utc': + parsed.timeFormat = TIME_UTC; + break + case 'local': + parsed.timeFormat = TIME_LOCAL; + if (!moment) { + throw new Error('could not find moment package ' + + 'required for "--time=local"'); + } + break + case undefined: + throw new Error('missing argument to "--time"'); + default: + throw new Error(format('invalid time format: "%s"', + timeArg)); + } + break; + case '-p': + if (!parsed.pids) { + parsed.pids = []; + } + var pidArg = args.shift(); + var pid = +(pidArg); + if (!isNaN(pid) || pidArg === '*') { + if (parsed.pidsType && parsed.pidsType !== 'num') { + throw new Error(format('cannot mix PID name and ' + + 'number arguments: "%s"', pidArg)); + } + parsed.pidsType = 'num'; + if (!parsed.pids) { + parsed.pids = []; + } + parsed.pids.push(isNaN(pid) ? pidArg : pid); + } else { + if (parsed.pidsType && parsed.pidsType !== 'name') { + throw new Error(format('cannot mix PID name and ' + + 'number arguments: "%s"', pidArg)); + } + parsed.pidsType = 'name'; + parsed.pids = pidArg; + } + break; + case '-l': + case '--level': + var levelArg = args.shift(); + var level = +(levelArg); + if (isNaN(level)) { + level = +levelFromName[levelArg.toLowerCase()]; + } + if (isNaN(level)) { + throw new Error('unknown level value: "'+levelArg+'"'); + } + parsed.level = level; + break; + case '-c': + case '--condition': + gUsingConditionOpts = true; + var condition = args.shift(); + if (Boolean(process.env.BUNYAN_EXEC && + process.env.BUNYAN_EXEC === 'vm')) + { + parsed.condVm = parsed.condVm || []; + var scriptName = 'bunyan-condition-'+parsed.condVm.length; + var code = condDefines + condition; + var script; + try { + script = vm.createScript(code, scriptName); + } catch (complErr) { + throw new Error(format('illegal CONDITION code: %s\n' + + ' CONDITION script:\n' + + '%s\n' + + ' Error:\n' + + '%s', + complErr, indent(code), indent(complErr.stack))); + } + + // Ensure this is a reasonably safe CONDITION. + try { + script.runInNewContext(minValidRecord); + } catch (condErr) { + throw new Error(format( + /* JSSTYLED */ + 'CONDITION code cannot safely filter a minimal Bunyan log record\n' + + ' CONDITION script:\n' + + '%s\n' + + ' Minimal Bunyan log record:\n' + + '%s\n' + + ' Filter error:\n' + + '%s', + indent(code), + indent(JSON.stringify(minValidRecord, null, 2)), + indent(condErr.stack) + )); + } + parsed.condVm.push(script); + } else { + parsed.condFuncs = parsed.condFuncs || []; + parsed.condFuncs.push(funcWithReturnFromSnippet(condition)); + } + break; + default: // arguments + if (!endOfOptions && arg.length > 0 && arg[0] === '-') { + throw new Error('unknown option "'+arg+'"'); + } + parsed.args.push(arg); + break; + } + } + //TODO: '--' handling and error on a first arg that looks like an option. + + return parsed; +} + + +function isInteger(s) { + return (s.search(/^-?[0-9]+$/) == 0); +} + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +// Suggested colors (some are unreadable in common cases): +// - Good: cyan, yellow (limited use), bold, green, magenta, red +// - Bad: blue (not visible on cmd.exe), grey (same color as background on +// Solarized Dark theme from <https://github.com/altercation/solarized>, see +// issue #160) +var colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +function stylizeWithColor(str, color) { + if (!str) + return ''; + var codes = colors[color]; + if (codes) { + return '\033[' + codes[0] + 'm' + str + + '\033[' + codes[1] + 'm'; + } else { + return str; + } +} + +function stylizeWithoutColor(str, color) { + return str; +} + + +/** + * Is this a valid Bunyan log record. + */ +function isValidRecord(rec) { + if (rec.v == null || + rec.level == null || + rec.name == null || + rec.hostname == null || + rec.pid == null || + rec.time == null || + rec.msg == null) { + // Not valid Bunyan log. + return false; + } else { + return true; + } +} +var minValidRecord = { + v: 0, //TODO: get this from bunyan.LOG_VERSION + level: INFO, + name: 'name', + hostname: 'hostname', + pid: 123, + time: Date.now(), + msg: 'msg' +}; + + +/** + * Parses the given log line and either emits it right away (for invalid + * records) or enqueues it for emitting later when it's the next line to show. + */ +function handleLogLine(file, line, opts, stylize) { + currLine = line; // intentionally global + + // Emit non-JSON lines immediately. + var rec; + if (!line) { + if (!opts.strict) emit(line + '\n'); + return; + } else if (line[0] !== '{') { + if (!opts.strict) emit(line + '\n'); // not JSON + return; + } else { + try { + rec = JSON.parse(line); + } catch (e) { + if (!opts.strict) emit(line + '\n'); + return; + } + } + + if (!isValidRecord(rec)) { + if (!opts.strict) emit(line + '\n'); + return; + } + + if (!filterRecord(rec, opts)) + return; + + if (file === null) + return emitRecord(rec, line, opts, stylize); + + return gotRecord(file, line, rec, opts, stylize); +} + +/** + * Print out a single result, considering input options. + */ +function emitRecord(rec, line, opts, stylize) { + var short = false; + + switch (opts.outputMode) { + case OM_SHORT: + short = true; + /* jsl:fall-thru */ + + case OM_LONG: + // [time] LEVEL: name[/comp]/pid on hostname (src): msg* (extras...) + // msg* + // -- + // long and multi-line extras + // ... + // If 'msg' is single-line, then it goes in the top line. + // If 'req', show the request. + // If 'res', show the response. + // If 'err' and 'err.stack' then show that. + if (!isValidRecord(rec)) { + return emit(line + '\n'); + } + + delete rec.v; + + // Time. + var time; + if (!short && opts.timeFormat === TIME_UTC) { + // Fast default path: We assume the raw `rec.time` is a UTC time + // in ISO 8601 format (per spec). + time = '[' + rec.time + ']'; + } else if (!moment && opts.timeFormat === TIME_UTC) { + // Don't require momentjs install, as long as not using TIME_LOCAL. + time = rec.time.substr(11); + } else { + var tzFormat; + var moTime = moment(rec.time); + switch (opts.timeFormat) { + case TIME_UTC: + tzFormat = TIMEZONE_UTC_FORMATS[short ? 'short' : 'long']; + moTime.utc(); + break; + case TIME_LOCAL: + tzFormat = TIMEZONE_LOCAL_FORMATS[short ? 'short' : 'long']; + break; + default: + throw new Error('unexpected timeFormat: ' + opts.timeFormat); + }; + time = moTime.format(tzFormat); + } + time = stylize(time, 'XXX'); + delete rec.time; + + var nameStr = rec.name; + delete rec.name; + + if (rec.component) { + nameStr += '/' + rec.component; + } + delete rec.component; + + if (!short) + nameStr += '/' + rec.pid; + delete rec.pid; + + var level = (upperPaddedNameFromLevel[rec.level] || 'LVL' + rec.level); + if (opts.color) { + var colorFromLevel = { + 10: 'white', // TRACE + 20: 'yellow', // DEBUG + 30: 'cyan', // INFO + 40: 'magenta', // WARN + 50: 'red', // ERROR + 60: 'inverse', // FATAL + }; + level = stylize(level, colorFromLevel[rec.level]); + } + delete rec.level; + + var src = ''; + if (rec.src && rec.src.file) { + var s = rec.src; + if (s.func) { + src = format(' (%s:%d in %s)', s.file, s.line, s.func); + } else { + src = format(' (%s:%d)', s.file, s.line); + } + src = stylize(src, 'green'); + } + delete rec.src; + + var hostname = rec.hostname; + delete rec.hostname; + + var extras = []; + var details = []; + + if (rec.req_id) { + extras.push('req_id=' + rec.req_id); + } + delete rec.req_id; + + var onelineMsg; + if (rec.msg.indexOf('\n') !== -1) { + onelineMsg = ''; + details.push(indent(stylize(rec.msg, 'cyan'))); + } else { + onelineMsg = ' ' + stylize(rec.msg, 'cyan'); + } + delete rec.msg; + + if (rec.req && typeof (rec.req) === 'object') { + var req = rec.req; + delete rec.req; + var headers = req.headers; + if (!headers) { + headers = ''; + } else if (typeof (headers) === 'string') { + headers = '\n' + headers; + } else if (typeof (headers) === 'object') { + headers = '\n' + Object.keys(headers).map(function (h) { + return h + ': ' + headers[h]; + }).join('\n'); + } + var s = format('%s %s HTTP/%s%s', req.method, + req.url, + req.httpVersion || '1.1', + headers + ); + delete req.url; + delete req.method; + delete req.httpVersion; + delete req.headers; + if (req.body) { + s += '\n\n' + (typeof (req.body) === 'object' + ? JSON.stringify(req.body, null, 2) : req.body); + delete req.body; + } + if (req.trailers && Object.keys(req.trailers) > 0) { + s += '\n' + Object.keys(req.trailers).map(function (t) { + return t + ': ' + req.trailers[t]; + }).join('\n'); + } + delete req.trailers; + details.push(indent(s)); + // E.g. for extra 'foo' field on 'req', add 'req.foo' at + // top-level. This *does* have the potential to stomp on a + // literal 'req.foo' key. + Object.keys(req).forEach(function (k) { + rec['req.' + k] = req[k]; + }) + } + + if (rec.client_req && typeof (rec.client_req) === 'object') { + var client_req = rec.client_req; + delete rec.client_req; + var headers = client_req.headers; + var hostHeaderLine = ''; + var s = ''; + if (client_req.address) { + hostHeaderLine = '\nHost: ' + client_req.address; + if (client_req.port) + hostHeaderLine += ':' + client_req.port; + } + delete client_req.headers; + delete client_req.address; + delete client_req.port; + s += format('%s %s HTTP/%s%s%s', client_req.method, + client_req.url, + client_req.httpVersion || '1.1', + hostHeaderLine, + (headers ? + '\n' + Object.keys(headers).map( + function (h) { + return h + ': ' + headers[h]; + }).join('\n') : + '')); + delete client_req.method; + delete client_req.url; + delete client_req.httpVersion; + if (client_req.body) { + s += '\n\n' + (typeof (client_req.body) === 'object' ? + JSON.stringify(client_req.body, null, 2) : + client_req.body); + delete client_req.body; + } + // E.g. for extra 'foo' field on 'client_req', add + // 'client_req.foo' at top-level. This *does* have the potential + // to stomp on a literal 'client_req.foo' key. + Object.keys(client_req).forEach(function (k) { + rec['client_req.' + k] = client_req[k]; + }) + details.push(indent(s)); + } + + function _res(res) { + var s = ''; + if (res.statusCode !== undefined) { + s += format('HTTP/1.1 %s %s\n', res.statusCode, + http.STATUS_CODES[res.statusCode]); + delete res.statusCode; + } + // Handle `res.header` or `res.headers` as either a string or + // and object of header key/value pairs. Prefer `res.header` if set + // (TODO: Why? I don't recall. Typical of restify serializer? + // Typical JSON.stringify of a core node HttpResponse?) + var headerTypes = {string: true, object: true}; + var headers; + if (res.header && headerTypes[typeof (res.header)]) { + headers = res.header; + delete res.header; + } else if (res.headers && headerTypes[typeof (res.headers)]) { + headers = res.headers; + delete res.headers; + } + if (headers === undefined) { + /* pass through */ + } else if (typeof (headers) === 'string') { + s += headers.trimRight(); + } else { + s += Object.keys(headers).map( + function (h) { return h + ': ' + headers[h]; }).join('\n'); + } + if (res.body !== undefined) { + var body = (typeof (res.body) === 'object' + ? JSON.stringify(res.body, null, 2) : res.body); + if (body.length > 0) { s += '\n\n' + body }; + delete res.body; + } else { + s = s.trimRight(); + } + if (res.trailer) { + s += '\n' + res.trailer; + } + delete res.trailer; + if (s) { + details.push(indent(s)); + } + // E.g. for extra 'foo' field on 'res', add 'res.foo' at + // top-level. This *does* have the potential to stomp on a + // literal 'res.foo' key. + Object.keys(res).forEach(function (k) { + rec['res.' + k] = res[k]; + }); + } + + if (rec.res && typeof (rec.res) === 'object') { + _res(rec.res); + delete rec.res; + } + if (rec.client_res && typeof (rec.client_res) === 'object') { + _res(rec.client_res); + delete rec.client_res; + } + + if (rec.err && rec.err.stack) { + var err = rec.err + if (typeof (err.stack) !== 'string') { + details.push(indent(err.stack.toString())); + } else { + details.push(indent(err.stack)); + } + delete err.message; + delete err.name; + delete err.stack; + // E.g. for extra 'foo' field on 'err', add 'err.foo' at + // top-level. This *does* have the potential to stomp on a + // literal 'err.foo' key. + Object.keys(err).forEach(function (k) { + rec['err.' + k] = err[k]; + }) + delete rec.err; + } + + var leftover = Object.keys(rec); + for (var i = 0; i < leftover.length; i++) { + var key = leftover[i]; + var value = rec[key]; + var stringified = false; + if (typeof (value) !== 'string') { + value = JSON.stringify(value, null, 2); + stringified = true; + } + if (value.indexOf('\n') !== -1 || value.length > 50) { + details.push(indent(key + ': ' + value)); + } else if (!stringified && (value.indexOf(' ') != -1 || + value.length === 0)) + { + extras.push(key + '=' + JSON.stringify(value)); + } else { + extras.push(key + '=' + value); + } + } + + extras = stylize( + (extras.length ? ' (' + extras.join(', ') + ')' : ''), 'XXX'); + details = stylize( + (details.length ? details.join('\n --\n') + '\n' : ''), 'XXX'); + if (!short) + emit(format('%s %s: %s on %s%s:%s%s\n%s', + time, + level, + nameStr, + hostname || '<no-hostname>', + src, + onelineMsg, + extras, + details)); + else + emit(format('%s %s %s:%s%s\n%s', + time, + level, + nameStr, + onelineMsg, + extras, + details)); + break; + + case OM_INSPECT: + emit(util.inspect(rec, false, Infinity, true) + '\n'); + break; + + case OM_BUNYAN: + emit(JSON.stringify(rec, null, 0) + '\n'); + break; + + case OM_JSON: + emit(JSON.stringify(rec, null, opts.jsonIndent) + '\n'); + break; + + case OM_SIMPLE: + /* JSSTYLED */ + // <http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/SimpleLayout.html> + if (!isValidRecord(rec)) { + return emit(line + '\n'); + } + emit(format('%s - %s\n', + upperNameFromLevel[rec.level] || 'LVL' + rec.level, + rec.msg)); + break; + default: + throw new Error('unknown output mode: '+opts.outputMode); + } +} + + +var stdoutFlushed = true; +function emit(s) { + try { + stdoutFlushed = stdout.write(s); + } catch (e) { + // Handle any exceptions in stdout writing in `stdout.on('error', ...)`. + } +} + + +/** + * A hacked up version of 'process.exit' that will first drain stdout + * before exiting. *WARNING: This doesn't stop event processing.* IOW, + * callers have to be careful that code following this call isn't + * accidentally executed. + * + * In node v0.6 "process.stdout and process.stderr are blocking when they + * refer to regular files or TTY file descriptors." However, this hack might + * still be necessary in a shell pipeline. + */ +function drainStdoutAndExit(code) { + if (_DEBUG) warn('(drainStdoutAndExit(%d))', code); + stdout.on('drain', function () { + cleanupAndExit(code); + }); + if (stdoutFlushed) { + cleanupAndExit(code); + } +} + + +/** + * Process all input from stdin. + * + * @params opts {Object} Bunyan options object. + * @param stylize {Function} Output stylize function to use. + * @param callback {Function} `function ()` + */ +function processStdin(opts, stylize, callback) { + readingStdin = true; + var leftover = ''; // Left-over partial line from last chunk. + var stdin = process.stdin; + stdin.resume(); + stdin.setEncoding('utf8'); + stdin.on('data', function (chunk) { + var lines = chunk.split(/\r\n|\n/); + var length = lines.length; + if (length === 1) { + leftover += lines[0]; + return; + } + + if (length > 1) { + handleLogLine(null, leftover + lines[0], opts, stylize); + } + leftover = lines.pop(); + length -= 1; + for (var i = 1; i < length; i++) { + handleLogLine(null, lines[i], opts, stylize); + } + }); + stdin.on('end', function () { + if (leftover) { + handleLogLine(null, leftover, opts, stylize); + leftover = ''; + } + callback(); + }); +} + + +/** + * Process bunyan:log-* probes from the given pid. + * + * @params opts {Object} Bunyan options object. + * @param stylize {Function} Output stylize function to use. + * @param callback {Function} `function (code)` + */ +function processPids(opts, stylize, callback) { + var leftover = ''; // Left-over partial line from last chunk. + + /** + * Get the PIDs to dtrace. + * + * @param cb {Function} `function (errCode, pids)` + */ + function getPids(cb) { + if (opts.pidsType === 'num') { + return cb(null, opts.pids); + } + if (process.platform === 'sunos') { + execFile('/bin/pgrep', ['-lf', opts.pids], + function (pidsErr, stdout, stderr) { + if (pidsErr) { + warn('bunyan: error getting PIDs for "%s": %s\n%s\n%s', + opts.pids, pidsErr.message, stdout, stderr); + return cb(1); + } + var pids = stdout.trim().split('\n') + .map(function (line) { + return line.trim().split(/\s+/)[0] + }) + .filter(function (pid) { + return Number(pid) !== process.pid + }); + if (pids.length === 0) { + warn('bunyan: error: no matching PIDs found for "%s"', + opts.pids); + return cb(2); + } + cb(null, pids); + } + ); + } else { + var regex = opts.pids; + if (regex && /[a-zA-Z0-9_]/.test(regex[0])) { + // 'foo' -> '[f]oo' trick to exclude the 'grep' PID from its + // own search. + regex = '[' + regex[0] + ']' + regex.slice(1); + } + exec(format('ps -A -o pid,command | grep \'%s\'', regex), + function (pidsErr, stdout, stderr) { + if (pidsErr) { + warn('bunyan: error getting PIDs for "%s": %s\n%s\n%s', + opts.pids, pidsErr.message, stdout, stderr); + return cb(1); + } + var pids = stdout.trim().split('\n') + .map(function (line) { + return line.trim().split(/\s+/)[0]; + }) + .filter(function (pid) { + return Number(pid) !== process.pid; + }); + if (pids.length === 0) { + warn('bunyan: error: no matching PIDs found for "%s"', + opts.pids); + return cb(2); + } + cb(null, pids); + } + ); + } + } + + getPids(function (errCode, pids) { + if (errCode) { + return callback(errCode); + } + + var probes = pids.map(function (pid) { + if (!opts.level) + return format('bunyan%s:::log-*', pid); + + var rval = [], l; + + for (l in levelFromName) { + if (levelFromName[l] >= opts.level) + rval.push(format('bunyan%s:::log-%s', pid, l)); + } + + if (rval.length != 0) + return rval.join(','); + + warn('bunyan: error: level (%d) exceeds maximum logging level', + opts.level); + return drainStdoutAndExit(1); + }).join(','); + var argv = ['dtrace', '-Z', '-x', 'strsize=4k', + '-x', 'switchrate=10hz', '-qn', + format('%s{printf("%s", copyinstr(arg0))}', probes)]; + //console.log('dtrace argv: %s', argv); + var dtrace = spawn(argv[0], argv.slice(1), + // Share the stderr handle to have error output come + // straight through. Only supported in v0.8+. + {stdio: ['pipe', 'pipe', process.stderr]}); + dtrace.on('error', function (e) { + if (e.syscall === 'spawn' && e.errno === 'ENOENT') { + console.error('bunyan: error: could not spawn "dtrace" ' + + '("bunyan -p" is only supported on platforms with dtrace)'); + } else { + console.error('bunyan: error: unexpected dtrace error: %s', e); + } + callback(1); + }) + child = dtrace; // intentionally global + + function finish(code) { + if (leftover) { + handleLogLine(null, leftover, opts, stylize); + leftover = ''; + } + callback(code); + } + + dtrace.stdout.setEncoding('utf8'); + dtrace.stdout.on('data', function (chunk) { + var lines = chunk.split(/\r\n|\n/); + var length = lines.length; + if (length === 1) { + leftover += lines[0]; + return; + } + if (length > 1) { + handleLogLine(null, leftover + lines[0], opts, stylize); + } + leftover = lines.pop(); + length -= 1; + for (var i = 1; i < length; i++) { + handleLogLine(null, lines[i], opts, stylize); + } + }); + + if (nodeSpawnSupportsStdio) { + dtrace.on('exit', finish); + } else { + // Fallback (for < v0.8) to pipe the dtrace process' stderr to + // this stderr. Wait for all of (1) process 'exit', (2) stderr + // 'end', and (2) stdout 'end' before returning to ensure all + // stderr is flushed (issue #54). + var returnCode = null; + var eventsRemaining = 3; + function countdownToFinish(code) { + returnCode = code; + eventsRemaining--; + if (eventsRemaining == 0) { + finish(returnCode); + } + } + dtrace.stderr.pipe(process.stderr); + dtrace.stderr.on('end', countdownToFinish); + dtrace.stderr.on('end', countdownToFinish); + dtrace.on('exit', countdownToFinish); + } + }); +} + + +/** + * Process all input from the given log file. + * + * @param file {String} Log file path to process. + * @params opts {Object} Bunyan options object. + * @param stylize {Function} Output stylize function to use. + * @param callback {Function} `function ()` + */ +function processFile(file, opts, stylize, callback) { + var stream = fs.createReadStream(file); + if (/\.gz$/.test(file)) { + stream = stream.pipe(require('zlib').createGunzip()); + } + // Manually decode streams - lazy load here as per node/lib/fs.js + var decoder = new (require('string_decoder').StringDecoder)('utf8'); + + streams[file].stream = stream; + + stream.on('error', function (err) { + streams[file].done = true; + callback(err); + }); + + var leftover = ''; // Left-over partial line from last chunk. + stream.on('data', function (data) { + var chunk = decoder.write(data); + if (!chunk.length) { + return; + } + var lines = chunk.split(/\r\n|\n/); + var length = lines.length; + if (length === 1) { + leftover += lines[0]; + return; + } + + if (length > 1) { + handleLogLine(file, leftover + lines[0], opts, stylize); + } + leftover = lines.pop(); + length -= 1; + for (var i = 1; i < length; i++) { + handleLogLine(file, lines[i], opts, stylize); + } + }); + + stream.on('end', function () { + streams[file].done = true; + if (leftover) { + handleLogLine(file, leftover, opts, stylize); + leftover = ''; + } else { + emitNextRecord(opts, stylize); + } + callback(); + }); +} + + +/** + * From node async module. + */ +/* BEGIN JSSTYLED */ +function asyncForEach(arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + arr.forEach(function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); +}; +/* END JSSTYLED */ + + + +/** + * Cleanup and exit properly. + * + * Warning: this doesn't stop processing, i.e. process exit might be delayed. + * It is up to the caller to ensure that no subsequent bunyan processing + * is done after calling this. + * + * @param code {Number} exit code. + * @param signal {String} Optional signal name, if this was exitting because + * of a signal. + */ +var cleanedUp = false; +function cleanupAndExit(code, signal) { + // Guard one call. + if (cleanedUp) { + return; + } + cleanedUp = true; + if (_DEBUG) warn('(bunyan: cleanupAndExit)'); + + // Clear possibly interrupted ANSI code (issue #59). + if (usingAnsiCodes) { + stdout.write('\033[0m'); + } + + // Kill possible dtrace child. + if (child) { + child.kill(signal); + } + + if (pager) { + // Let pager know that output is done, then wait for pager to exit. + stdout.end(); + pager.on('exit', function (pagerCode) { + if (_DEBUG) + warn('(bunyan: pager exit -> process.exit(%s))', + pagerCode || code); + process.exit(pagerCode || code); + }); + } else { + if (_DEBUG) warn('(bunyan: process.exit(%s))', code); + process.exit(code); + } +} + + + +//---- mainline + +process.on('SIGINT', function () { + /** + * Ignore SIGINT (Ctrl+C) if processing stdin -- we should process + * remaining output from preceding process in the pipeline and + * except *it* to close. + */ + if (!readingStdin) { + cleanupAndExit(1, 'SIGINT'); + } +}); +process.on('SIGQUIT', function () { cleanupAndExit(1, 'SIGQUIT'); }); +process.on('SIGTERM', function () { cleanupAndExit(1, 'SIGTERM'); }); +process.on('SIGHUP', function () { cleanupAndExit(1, 'SIGHUP'); }); + +process.on('uncaughtException', function (err) { + function _indent(s) { + var lines = s.split(/\r?\n/); + for (var i = 0; i < lines.length; i++) { + lines[i] = '* ' + lines[i]; + } + return lines.join('\n'); + } + + var title = encodeURIComponent(format( + 'Bunyan %s crashed: %s', getVersion(), String(err))); + var e = console.error; + e('```'); + e('* The Bunyan CLI crashed!'); + e('*'); + if (err.name === 'ReferenceError' && gUsingConditionOpts) { + /* BEGIN JSSTYLED */ + e('* This crash was due to a "ReferenceError", which is often the result of given'); + e('* `-c CONDITION` code that doesn\'t guard against undefined values. If that is'); + /* END JSSTYLED */ + e('* not the problem:'); + e('*'); + } + e('* Please report this issue and include the details below:'); + e('*'); + e('* https://github.com/trentm/node-bunyan/issues/new?title=%s', title); + e('*'); + e('* * *'); + e('* platform:', process.platform); + e('* node version:', process.version); + e('* bunyan version:', getVersion()); + e('* argv: %j', process.argv); + e('* log line: %j', currLine); + e('* stack:'); + e(_indent(err.stack)); + e('```'); + process.exit(1); +}); + + +function main(argv) { + try { + var opts = parseArgv(argv); + } catch (e) { + warn('bunyan: error: %s', e.message); + return drainStdoutAndExit(1); + } + if (opts.help) { + printHelp(); + return; + } + if (opts.version) { + console.log('bunyan ' + getVersion()); + return; + } + if (opts.pid && opts.args.length > 0) { + warn('bunyan: error: can\'t use both "-p PID" (%s) and file (%s) args', + opts.pid, opts.args.join(' ')); + return drainStdoutAndExit(1); + } + if (opts.color === null) { + if (process.env.BUNYAN_NO_COLOR && + process.env.BUNYAN_NO_COLOR.length > 0) { + opts.color = false; + } else { + opts.color = process.stdout.isTTY; + } + } + usingAnsiCodes = opts.color; // intentionally global + var stylize = (opts.color ? stylizeWithColor : stylizeWithoutColor); + + // Pager. + var paginate = ( + process.stdout.isTTY && + process.stdin.isTTY && + !opts.pids && // Don't page if following process output. + opts.args.length > 0 && // Don't page if no file args to process. + process.platform !== 'win32' && + (nodeVer[0] > 0 || nodeVer[1] >= 8) && + (opts.paginate === true || + (opts.paginate !== false && + (!process.env.BUNYAN_NO_PAGER || + process.env.BUNYAN_NO_PAGER.length === 0)))); + if (paginate) { + var pagerCmd = process.env.PAGER || 'less'; + /* JSSTYLED */ + assert.ok(pagerCmd.indexOf('"') === -1 && pagerCmd.indexOf("'") === -1, + 'cannot parse PAGER quotes yet'); + var argv = pagerCmd.split(/\s+/g); + var env = objCopy(process.env); + if (env.LESS === undefined) { + // git's default is LESS=FRSX. I don't like the 'S' here because + // lines are *typically* wide with bunyan output and scrolling + // horizontally is a royal pain. Note a bug in Mac's `less -F`, + // such that SIGWINCH can kill it. If that rears too much then + // I'll remove 'F' from here. + env.LESS = 'FRX'; + } + if (_DEBUG) warn('(pager: argv=%j, env.LESS=%j)', argv, env.LESS); + // `pager` and `stdout` intentionally global. + pager = spawn(argv[0], argv.slice(1), + // Share the stderr handle to have error output come + // straight through. Only supported in v0.8+. + {env: env, stdio: ['pipe', 1, 2]}); + stdout = pager.stdin; + + // Early termination of the pager: just stop. + pager.on('exit', function (pagerCode) { + if (_DEBUG) warn('(bunyan: pager exit)'); + pager = null; + stdout.end() + stdout = process.stdout; + cleanupAndExit(pagerCode); + }); + } + + // Stdout error handling. (Couldn't setup until `stdout` was determined.) + stdout.on('error', function (err) { + if (_DEBUG) warn('(stdout error event: %s)', err); + if (err.code === 'EPIPE') { + drainStdoutAndExit(0); + } else if (err.toString() === 'Error: This socket is closed.') { + // Could get this if the pager closes its stdin, but hasn't + // exited yet. + drainStdoutAndExit(1); + } else { + warn(err); + drainStdoutAndExit(1); + } + }); + + var retval = 0; + if (opts.pids) { + processPids(opts, stylize, function (code) { + cleanupAndExit(code); + }); + } else if (opts.args.length > 0) { + var files = opts.args; + files.forEach(function (file) { + streams[file] = { stream: null, records: [], done: false } + }); + asyncForEach(files, + function (file, next) { + processFile(file, opts, stylize, function (err) { + if (err) { + warn('bunyan: %s', err.message); + retval += 1; + } + next(); + }); + }, + function (err) { + if (err) { + warn('bunyan: unexpected error: %s', err.stack || err); + return drainStdoutAndExit(1); + } + cleanupAndExit(retval); + } + ); + } else { + processStdin(opts, stylize, function () { + cleanupAndExit(retval); + }); + } +} + +if (require.main === module) { + // HACK guard for <https://github.com/trentm/json/issues/24>. + // We override the `process.stdout.end` guard that core node.js puts in + // place. The real fix is that `.end()` shouldn't be called on stdout + // in node core. Node v0.6.9 fixes that. Only guard for v0.6.0..v0.6.8. + if ([0, 6, 0] <= nodeVer && nodeVer <= [0, 6, 8]) { + var stdout = process.stdout; + stdout.end = stdout.destroy = stdout.destroySoon = function () { + /* pass */ + }; + } + + main(process.argv); +}
