Using grunt js, how can I dynamically add the to static html files?</a></h1> </div> <div class="grid fw-wrap pb8 mb16 bb bc-black-075"> <div class="grid--cell ws-nowrap mr16 mb8" title="2016-01-12 19:07:53Z"> <span class="fc-light mr2">Asked</span> <time itemprop="dateCreated" datetime="2012-10-19T21:00:07.747" class="fromnow">Oct 19 '12 at 21:00</time> </div> <div class="grid--cell ws-nowrap mr16 mb8"> <span class="fc-light mr2">Active</span> <time class="fromnow" title="2014-03-18T21:52:26.193" datetime="2014-03-18T21:52:26.193">Mar 18 '14 at 21:52</a> </div> <div class="grid--cell ws-nowrap mb8" title="Viewed 7,821 times"> <span class="fc-light mr2">Viewed</span> 7,821 times </div> </div> <div id="mainbar" role="main" aria-label="questions and answers"> <div id="question" class="question" data-questionid="12982396" data-ownerid="1267639" data-score="7"> <div class="post-layout"> <div class="votecell post-layout--left"> <div class="js-voting-container grid jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="12982396"> <button class="js-vote-up-btn grid--cell s-btn s-btn__unset c-pointer"><svg aria-hidden="true" class="m0 svg-icon iconArrowUpLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 26h32L18 10 2 26z"></path></svg></button> <div class="js-vote-count grid--cell fc-black-500 fs-title grid fd-column ai-center" itemprop="upvoteCount" data-value="7">7</div> <button class="js-bookmark-btn s-btn s-btn__unset c-pointer py4"> <svg aria-hidden="true" class="svg-icon iconBookmark" width="18" height="18" viewBox="0 0 18 18"><path d="M6 1a2 2 0 00-2 2v14l5-4 5 4V3a2 2 0 00-2-2H6zm3.9 3.83h2.9l-2.35 1.7.9 2.77L9 7.59l-2.35 1.7.9-2.76-2.35-1.7h2.9L9 2.06l.9 2.77z"></path></svg> <div class="js-bookmark-count mt4" data-value="0">0</div> </button> </div> </div> <div class="postcell post-layout--right"> <div class="s-prose js-post-body" itemprop="text"><p>More specifically, I want to add the titles by referencing an external JSON file, let's call it titles.json. </p> <p>One of the things I use grunt for is to build static HTML files for design and debugging. This would be really helpful during development, not just for titles but potentially other data as well, such as setting the active nav link. </p> <p>I'm currently concatenating HTML files using the process described by the accepted answer here: <a href="../../questions/12722855/using-grunt-concat-how-would-i-automate-the-concatenation-of-the-same-file-to-?lq=1">Using grunt concat, how would I automate the concatenation of the same file to many other files?</a></p> <p>EDIT: <strong>I now use <a class="external-link" href="http://github.com/assemble/assemble" rel="nofollow noreferrer">assemble</a> for this</strong>, it was created to make working with templates and external data very easy. </p></div> <div class="mt24 mb12"> <div class="post-taglist grid gs4 gsy fd-column"> <div class="grid ps-relative"> <a href="../../questions/tagged/html" class="post-tag js-gps-track" title="show questions tagged 'html'" rel="tag">html</a> <a href="../../questions/tagged/json" class="post-tag js-gps-track" title="show questions tagged 'json'" rel="tag">json</a> <a href="../../questions/tagged/build-process" class="post-tag js-gps-track" title="show questions tagged 'build-process'" rel="tag">build-process</a> <a href="../../questions/tagged/concatenation" class="post-tag js-gps-track" title="show questions tagged 'concatenation'" rel="tag">concatenation</a> <a href="../../questions/tagged/gruntjs" class="post-tag js-gps-track" title="show questions tagged 'gruntjs'" rel="tag">gruntjs</a> </div> </div> </div> <div class="mb0"> <div class="mt16 grid gs8 gsy fw-wrap jc-end ai-start pt4 mb16"> <div class="grid--cell mr16 fl1 w96"></div> <div class="post-signature grid--cell"> <div class="s-user-card s-user-card"> <time class="s-user-card--time" datetime="edited May 23 '17 at 12:12">edited May 23 '17 at 12:12</time> <a href="../../users/-1/community" class="s-avatar s-avatar__32 s-user-card--avatar"> <img class="s-avatar--image" src="../../users/profiles/-1.webp" data-jdenticon-width="32" data-jdenticon-height="32" data-jdenticon-value="Community" /> </a> <div class="s-user-card--info"> <a href="../../users/-1/community" class="s-user-card--link">Community</a> <ul class="s-user-card--awards"> <li class="s-user-card--rep" title="reputation score">1</li> <li class="s-award-bling s-award-bling__silver" title="1 silver badges">1</li> </ul> </div> </div> </div> <div class="post-signature owner grid--cell"> <div class="s-user-card s-user-card"> <time class="s-user-card--time" datetime="asked Oct 19 '12 at 21:00">asked Oct 19 '12 at 21:00</time> <a href="../../users/1267639/jonschlinkert" class="s-avatar s-avatar__32 s-user-card--avatar"> <img class="s-avatar--image" src="../../users/profiles/1267639.webp" data-jdenticon-width="32" data-jdenticon-height="32" data-jdenticon-value="jonschlinkert" /> </a> <div class="s-user-card--info"> <a href="../../users/1267639/jonschlinkert" class="s-user-card--link">jonschlinkert</a> <ul class="s-user-card--awards"> <li class="s-user-card--rep" title="reputation score">10,872</li> <li class="s-award-bling s-award-bling__gold" title="4 gold badges">4</li> <li class="s-award-bling s-award-bling__silver" title="43 silver badges">43</li> <li class="s-award-bling s-award-bling__bronze" title="50 bronze badges">50</li> </ul> </div> </div> </div> </div> </div> </div> <div class="post-layout--right js-post-comments-component"> <div id="comments-12982396" class="comments js-comments-container bt bc-black-075 mt12 " data-post-id="12982396" data-min-length="15"> <ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"> <li id="comment-17624899" class="comment js-comment " data-comment-id="17624899" data-comment-owner-id="1033615" data-comment-score="0"> <div class="js-comment-actions comment-actions"> <div class="comment-score js-comment-edit-hide"> </div> </div> <div class="comment-text js-comment-text-and-form"> <a name="comment17624899_12982396"></a> <div class="comment-body js-comment-edit-hide"> <span class="comment-copy">How do you actually want to link titles to html pages? Do you reference html files in titles.json? And what about links? It would be easier to help you out with this if you provided a sample json definition you would like to be able to use</span> – <a href="../../users/1033615/dmitry-pashkevich" title="13,431 reputation" class="comment-user ">Dmitry Pashkevich</a> <span class="comment-date" dir="ltr"><a class="comment-link" href="../../questions/12982396/using-grunt-js-how-can-i-dynamically-add-the-title-to-static-html-files#comment17624899_12982396"><span title="2012-10-20T20:44:25.087 License: CC BY-SA 3.0" class="relativetime-clean">Oct 20 '12 at 20:44</span></a></span> </div> </div> </li> <li id="comment-17624916" class="comment js-comment " data-comment-id="17624916" data-comment-owner-id="1033615" data-comment-score="0"> <div class="js-comment-actions comment-actions"> <div class="comment-score js-comment-edit-hide"> </div> </div> <div class="comment-text js-comment-text-and-form"> <a name="comment17624916_12982396"></a> <div class="comment-body js-comment-edit-hide"> <span class="comment-copy">Also, if you have such long-going plans, you might want to consider static website generators like [Jekyll](https://github.com/mojombo/jekyll/wiki/usage). They should already have all the common functionality you describe.</span> – <a href="../../users/1033615/dmitry-pashkevich" title="13,431 reputation" class="comment-user ">Dmitry Pashkevich</a> <span class="comment-date" dir="ltr"><a class="comment-link" href="../../questions/12982396/using-grunt-js-how-can-i-dynamically-add-the-title-to-static-html-files#comment17624916_12982396"><span title="2012-10-20T20:45:42.153 License: CC BY-SA 3.0" class="relativetime-clean">Oct 20 '12 at 20:45</span></a></span> </div> </div> </li> <li id="comment-17625728" class="comment js-comment " data-comment-id="17625728" data-comment-owner-id="1267639" data-comment-score="0"> <div class="js-comment-actions comment-actions"> <div class="comment-score js-comment-edit-hide"> </div> </div> <div class="comment-text js-comment-text-and-form"> <a name="comment17625728_12982396"></a> <div class="comment-body js-comment-edit-hide"> <span class="comment-copy">Good questions. And thanks again for helping with the last question - it has made a big impact on my time. I'm going to keep this simple in my projects, so there might be two json files: titles.json, and links.json. It seems to make sense to use the names of the html files to match the data. Since I work on a lot of small projects where the file names are almost always the same: index.html, about.html, contact.html etc. So I'm thinking that when index.html compiles, the script would set the active class on the nav for that file. I'll link a jsfiddle in a minute to show exactly what I mean</span> – <a href="../../users/1267639/jonschlinkert" title="10,872 reputation" class="comment-user owner">jonschlinkert</a> <span class="comment-date" dir="ltr"><a class="comment-link" href="../../questions/12982396/using-grunt-js-how-can-i-dynamically-add-the-title-to-static-html-files#comment17625728_12982396"><span title="2012-10-20T21:46:01.297 License: CC BY-SA 3.0" class="relativetime-clean">Oct 20 '12 at 21:46</span></a></span> </div> </div> </li> <li id="comment-17625874" class="comment js-comment " data-comment-id="17625874" data-comment-owner-id="1267639" data-comment-score="0"> <div class="js-comment-actions comment-actions"> <div class="comment-score js-comment-edit-hide"> </div> </div> <div class="comment-text js-comment-text-and-form"> <a name="comment17625874_12982396"></a> <div class="comment-body js-comment-edit-hide"> <span class="comment-copy">actually, I don't think I need an external json file to do this. Seems like it would make more sense to do this right inside the gruntfile. Here is the jsfiddle for the nav: http://jsfiddle.net/jonschlinkert/hprTQ/ To your point about Jekyll, I appreciate where you're coming from. I'm very familiar with Jekyll, but I'm moving towards a different goal with this. I'm happy to provide more detail on the "big picture", but it's probably better explained in a different format so the gods of SO don't rain down upon me...</span> – <a href="../../users/1267639/jonschlinkert" title="10,872 reputation" class="comment-user owner">jonschlinkert</a> <span class="comment-date" dir="ltr"><a class="comment-link" href="../../questions/12982396/using-grunt-js-how-can-i-dynamically-add-the-title-to-static-html-files#comment17625874_12982396"><span title="2012-10-20T21:59:45.773 License: CC BY-SA 3.0" class="relativetime-clean">Oct 20 '12 at 21:59</span></a></span> </div> </div> </li> </ul> </div> </div> </div> </div> <div id="answers"> <a name="tab-top"></a> <div id="answers-header"> <div class="answers-subheader grid ai-center mb8"> <div class="grid--cell fl1"> <h2 class="mb0" data-answercount="9">1 Answers<span style="display:none;" itemprop="answerCount">1</span></h2> </div> </div> </div> <a name="13001372"></a> <div id="answer-13001372" class="answer accepted-answer" data-answerid="13001372" data-ownerid="1033615" data-score="15" itemprop="acceptedAnswer" itemscope="" itemtype="https://schema.org/Answer"> <div class="post-layout"> <div class="votecell post-layout--left"> <div class="js-voting-container grid jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="13001372"> <button class="js-vote-up-btn grid--cell s-btn s-btn__unset c-pointer"><svg aria-hidden="true" class="m0 svg-icon iconArrowUpLg" width="36" height="36" viewBox="0 0 36 36"><path d="M2 26h32L18 10 2 26z"></path></svg></button> <div class="js-vote-count grid--cell fc-black-500 fs-title grid fd-column ai-center" itemprop="upvoteCount" data-value="15">15</div> <div class="js-accepted-answer-indicator grid--cell fc-green-500 py6 mtn8"><div class="ta-center"><svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewBox="0 0 36 36"><path d="m6 14 8 8L30 6v8L14 30l-8-8v-8z"></path></svg></div></div> </div> </div> <div class="postcell post-layout--right"> <div class="s-prose js-post-body" itemprop="text"><p>Here is my take on this. Uses grunt's standard template mechanism, page metadata is defined in an object, outside of actual page files, as you suggested (I can't say I like this).</p> <p><strong>gruntfile</strong> (including the <code>wrap</code> task from <a href="../../questions/12722855/using-grunt-concat-how-would-i-automate-the-concatenation-of-the-same-file-to-?lq=1">Using grunt concat, how would I automate the concatenation of the same file to many other files?</a>):</p> <pre><code>/*global module:false*/ module.exports = function(grunt) { // Project configuration. grunt.initConfig({ meta: { version: '0.1.0', banner: '/*! PROJECT_NAME - v<%= meta.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + '* http://PROJECT_WEBSITE/\n' + '* Copyright (c) <%= grunt.template.today("yyyy") %> ' + 'YOUR_NAME; Licensed MIT */' }, // Paths project: { partials: 'assets/partials', // don't put trailing slash pages: 'assets/pages', // don't put trailing slash less: 'assets/less', css: 'assets/css', img: 'assets/img', js: 'assets/js' }, // Used for page title and nav generation. // It's an array to ensure correct order for nav pages: [{ file: 'index.html', title: 'My homepage' /* This format can be extended to something like: * { * title: 'My homepage', * header: 'Welcome to my site', * navtitle: 'Home' * } * Although I think it's best to keep page metadata as close to content as possible, * i.e. right inside pages files (think YAML headers in Jekyll pages) */ }, { file: 'about.html', title: 'About me' }, { file: 'contact.html', title: 'Contact' }], // wraps files with header and footer wrap: { html: { header: '<%= project.partials %>/head.tmpl', footer: '<%= project.partials %>/footer.tmpl', src: [ '<%= project.pages %>/index.html', '<%= project.pages %>/about.html', '<%= project.pages %>/contact.html' ], dest: '.' // destination *directory*, probably better than specifying same file names twice } }, // processes templates in page files buildPages: { pages: '<config:pages>', // page files metadata dir: '.' // page files location dir } }); // Default task. grunt.registerTask('default', 'wrap buildPages'); grunt.registerMultiTask('wrap', 'Wraps source files with specified header and footer', function() { var data = this.data, path = require('path'), dest = grunt.template.process(data.dest), files = grunt.file.expandFiles(this.file.src), header = grunt.file.read(grunt.template.process(data.header)), footer = grunt.file.read(grunt.template.process(data.footer)), sep = grunt.utils.linefeed; files.forEach(function(f) { var p = dest + '/' + path.basename(f), contents = grunt.file.read(f); grunt.file.write(p, header + sep + contents + sep + footer); grunt.log.writeln('File "' + p + '" created.'); }); }); grunt.registerTask('buildPages', 'Processes templates in page files', function() { // NOTE: current implementation replaces files var data = grunt.config('buildPages'), pages = data.pages, dir = data.dir, contents, curPath; pages.forEach(function(page) { curPath = dir + '/' + page.file; contents = grunt.file.read(curPath); // feed the entire pages array and current entry to the template grunt.file.write(curPath, grunt.template.process(contents, { pages: pages, curPage: page })); grunt.log.writeln('Page at "' + curPath + '" built.'); }); }); }; </code></pre> <p><strong>head.tmpl:</strong></p> <pre><code><!DOCTYPE html> <html> <head> <title><%= curPage.title %></title> </head> <body> <!-- NAV --> <ul class="nav"> <% pages.forEach(function(p) { print( '<li class="' + ((curPage === p) ? 'active' : '') + '">' + ((curPage === p) ? p.title : ('<a href="' + p.file + '">' + p.title + '</a>')) + '</li>\n' ); }); %> </ul> <!-- /NAV --> <!-- MAIN CONTENT --> <div class="main"> </code></pre> <p><strong>footer.tmpl:</strong></p> <pre><code> </div> <!-- /MAIN CONTENT --> </body> </html> </code></pre></div> <div class="mb0"> <div class="mt16 grid gs8 gsy fw-wrap jc-end ai-start pt4 mb16"> <div class="grid--cell mr16 fl1 w96"></div> <div class="post-signature grid--cell"> <div class="s-user-card s-user-card"> <time class="s-user-card--time" datetime="edited May 23 '17 at 12:20">edited May 23 '17 at 12:20</time> <a href="../../users/-1/community" class="s-avatar s-avatar__32 s-user-card--avatar"> <img class="s-avatar--image" src="../../users/profiles/-1.webp" data-jdenticon-width="32" data-jdenticon-height="32" data-jdenticon-value="Community" /> </a> <div class="s-user-card--info"> <a href="../../users/-1/community" class="s-user-card--link">Community</a> <ul class="s-user-card--awards"> <li class="s-user-card--rep" title="reputation score">1</li> <li class="s-award-bling s-award-bling__silver" title="1 silver badges">1</li> </ul> </div> </div> </div> <div class="post-signature grid--cell"> <div class="s-user-card s-user-card"> <time class="s-user-card--time" datetime="answered Oct 21 '12 at 19:26">answered Oct 21 '12 at 19:26</time> <a href="../../users/1033615/dmitry-pashkevich" class="s-avatar s-avatar__32 s-user-card--avatar"> <img class="s-avatar--image" src="../../users/profiles/1033615.webp" data-jdenticon-width="32" data-jdenticon-height="32" data-jdenticon-value="Dmitry Pashkevich" /> </a> <div class="s-user-card--info"> <a href="../../users/1033615/dmitry-pashkevich" class="s-user-card--link">Dmitry Pashkevich</a> <ul class="s-user-card--awards"> <li class="s-user-card--rep" title="reputation score">13,431</li> <li class="s-award-bling s-award-bling__gold" title="9 gold badges">9</li> <li class="s-award-bling s-award-bling__silver" title="55 silver badges">55</li> <li class="s-award-bling s-award-bling__bronze" title="73 bronze badges">73</li> </ul> </div> </div> </div> </div> </div> </div> <div class="post-layout--right js-post-comments-component"> <div id="comments-13001372" class="comments js-comments-container bt bc-black-075 mt12 " data-post-id="13001372" data-min-length="15"> <ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"> <li id="comment-17644659" class="comment js-comment " data-comment-id="17644659" data-comment-owner-id="1267639" data-comment-score="0"> <div class="js-comment-actions comment-actions"> <div class="comment-score js-comment-edit-hide"> </div> </div> <div class="comment-text js-comment-text-and-form"> <a name="comment17644659_13001372"></a> <div class="comment-body js-comment-edit-hide"> <span class="comment-copy">worked like a charm, thanks! I really appreciate how much help you've been</span> – <a href="../../users/1267639/jonschlinkert" title="10,872 reputation" class="comment-user owner">jonschlinkert</a> <span class="comment-date" dir="ltr"><a class="comment-link" href="../../questions/12982396/using-grunt-js-how-can-i-dynamically-add-the-title-to-static-html-files#comment17644659_13001372"><span title="2012-10-22T01:44:46.787 License: CC BY-SA 3.0" class="relativetime-clean">Oct 22 '12 at 01:44</span></a></span> </div> </div> </li> </ul> </div> </div> </div> </div> </div> </div> </div> </div> <script src="../../static/js/stack-icons.js"></script> <script src="../../static/js/fromnow.js"></script> </body> </html>