7

Let me preface with two things. I am currently using grunt for these tasks and I also know about Yeoman which has what I am asking for. I do really like Yeoman however it is just a little too opinionated for this particular project I am working on.

So I have the following HTML file:

<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">

        <!-- START-CSS-MIN:css/build/min.css -->
        <link rel="stylesheet" href="css/bootstrap/bootstrap-2.1.1.css">
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/boilerplate.css">
        <!-- END-CSS-MIN -->

        <!-- START-JS-MIN:js/build/modernizr.js -->
        <script src="js/libraries/modernizr.js"></script>
        <!-- END-JS-MIN -->
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
        <![endif]-->

        <p>Hello world! This is a basline HTML5 template (based on HTML5 Boilerplate).</p>

        <!-- START-JS-MIN:js/build/libraries.js -->
        <script src="js/libraries/underscore.js"></script>
        <script src="js/libraries/jquery/jquery.js"></script>
        <!-- END-JS-MIN -->
    </body>
</html>

Now you can see the CSS-MIN and JS-MIN comments. Right now I already have a custom grunt build task that properly collects all those files in the comments (using htmlparser) and then minifies and concats them as directly based on the comments. The last step in the build process is to create a new version of that HTML file (for production use) that replaces the comments with the new file. For example, the code above would be turned into this:

<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">

        <link rel="stylesheet" href="css/build/min.css">

        <script src="js/build/modernizr.js"></script>
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
        <![endif]-->

        <p>Hello world! This is a basline HTML5 template (based on HTML5 Boilerplate).</p>

        <script src="js/build/libraries.js"></script>
    </body>
</html>

The question I have is how would I be able to do this in NodeJS? The htmlparser NPM module is great for parsing HTML however I now need something where I am modifying the HTML (removing and adding certain elements in specific locations). Is there any good packages/tutorials on how to do this in NodeJS code?

5
  • did you ever solve this? I am working on something similar Commented Jul 18, 2013 at 14:22
  • I ended up using npmjs.org/package/htmlparser Commented Jul 18, 2013 at 14:51
  • cool thanks! I was just looking at cheerio. Any chance you open-sourced your code? seems like a great utility. I am starting to build exact same thing. Commented Jul 18, 2013 at 14:57
  • The code is not packaged up nice a clean but you can look at the build task in this file : github.com/ryanzec/angular-seed-express/blob/master/… Commented Jul 18, 2013 at 16:22
  • ah thanks! that will save me lots of time :) Commented Jul 18, 2013 at 17:48

2 Answers 2

3

I'm not quite sure if this is helpful for comment lines, but that should be less of an issue to solve than DOM reference.

Consider using: https://github.com/tmpvar/jsdom

There are other options out there as well. (https://github.com/joyent/node/wiki/modules)

Sign up to request clarification or add additional context in comments.

Comments

0

You can use cheerio

The following code will produce exactly the output you provided (apart from some minor whitespace differrences)

const $ = require('cheerio').load(inputHtml);

// Returns a filter function that selects the comments with the provided indexes
const commentRemovalFilter = (commentIndexes)=>{
    let commentIndex=-1;
    return (index, node)=>{
        const isComment = node.type === 'comment';
        if(isComment)commentIndex++;
        return isComment && commentIndexes.includes(commentIndex);
    }
}
    

$('head').contents().filter(commentRemovalFilter([0,1,2,3])).remove();
$('head link').remove();
$('head script').remove();

//Cheerio respects whitespace provided here
$('head').append(`
        <link rel="stylesheet" href="css/build/min.css">

        <script src="js/build/modernizr.js"></script>
`)


$('body').contents().filter(commentRemovalFilter([1,2])).remove();
$('body script').remove();
$('body').append(`      <script src="js/build/libraries.js"></script>
`)

console.log($.html())

output:

<html><head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">

        
        
        
        
        

        
        
        
    
        <link rel="stylesheet" href="css/build/min.css">

        <script src="js/build/modernizr.js"></script>
</head>
    <body>
        <!--[if lt IE 7]>
            <p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
        <![endif]-->

        <p>Hello world! This is a basline HTML5 template (based on HTML5 Boilerplate).</p>

        
        
        
        
    
      <script src="js/build/libraries.js"></script>
</body></html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.