Giter Site home page Giter Site logo

grunt-posthtml's Introduction

NPM Tests Coverage Standard Code Style

PostHTML

PostHTML is a tool for transforming HTML/XML with JS plugins. PostHTML itself is very small. It includes only a HTML parser, a HTML node tree API and a node tree stringifier.

All HTML transformations are made by plugins. And these plugins are just small plain JS functions, which receive a HTML node tree, transform it, and return a modified tree.

For more detailed information about PostHTML in general take a look at the docs.

Dependencies

Name Status Description
posthtml-parser npm Parser HTML/XML to PostHTMLTree
posthtml-render npm Render PostHTMLTree to HTML/XML

Create to your project

npm init posthtml

Install

npm i -D posthtml

Usage

API

Sync

import posthtml from 'posthtml'

const html = `
  <component>
    <title>Super Title</title>
    <text>Awesome Text</text>
  </component>
`

const result = posthtml()
  .use(require('posthtml-custom-elements')())
  .process(html, { sync: true })
  .html

console.log(result)
<div class="component">
  <div class="title">Super Title</div>
  <div class="text">Awesome Text</div>
</div>

⚠️ Async Plugins can't be used in sync mode and will throw an Error. It's recommended to use PostHTML asynchronously whenever possible.

Async

import posthtml from 'posthtml'

const html = `
  <html>
    <body>
      <p class="wow">OMG</p>
    </body>
  </html>
`

posthtml(
  [
    require('posthtml-to-svg-tags')(),
    require('posthtml-extend-attrs')({
      attrsTree: {
        '.wow' : {
          id: 'wow_id',
          fill: '#4A83B4',
          'fill-rule': 'evenodd',
          'font-family': 'Verdana'
        }
      }
    })
  ])
  .process(html/*, options */)
  .then((result) =>  console.log(result.html))
<svg xmlns="http://www.w3.org/2000/svg">
  <text
    class="wow"
    id="wow_id"
    fill="#4A83B4"
    fill-rule="evenodd" font-family="Verdana">
      OMG
  </text>
</svg>

Directives

import posthtml from 'posthtml'

const php = `
  <component>
    <title><?php echo $title; ?></title>
    <text><?php echo $article; ?></text>
  </component>
`

const result = posthtml()
  .use(require('posthtml-custom-elements')())
  .process(html, {
    directives: [
      { name: '?php', start: '<', end: '>' }
    ]
  })
  .html

console.log(result)
<div class="component">
  <div class="title"><?php echo $title; ?></div>
  <div class="text"><?php echo $article; ?></div>
</div>
npm i posthtml-cli
"scripts": {
  "posthtml": "posthtml -o output.html -i input.html -c config.json"
}
npm run posthtml
npm i -D gulp-posthtml
import tap from 'gulp-tap'
import posthtml from 'gulp-posthtml'
import { task, src, dest } from 'gulp'

task('html', () => {
  let path

  const plugins = [ require('posthtml-include')({ root: `${path}` }) ]
  const options = {}

  src('src/**/*.html')
    .pipe(tap((file) => path = file.path))
    .pipe(posthtml(plugins, options))
    .pipe(dest('build/'))
})

Check project-stub for an example with Gulp

npm i -D grunt-posthtml
posthtml: {
  options: {
    use: [
      require('posthtml-doctype')({ doctype: 'HTML 5' }),
      require('posthtml-include')({ root: './', encoding: 'utf-8' })
    ]
  },
  build: {
    files: [
      {
        dot: true,
        cwd: 'html/',
        src: ['*.html'],
        dest: 'tmp/',
        expand: true,
      }
    ]
  }
}
npm i -D html-loader posthtml-loader

v1.x

webpack.config.js

const config = {
  module: {
    loaders: [
      {
        test: /\.html$/,
        loader: 'html!posthtml'
      }
    ]
  },
  posthtml: (ctx) => ({
    parser: require('posthtml-pug'),
    plugins: [
      require('posthtml-bem')()
    ]
  })
}

export default config

v2.x

webpack.config.js

import { LoaderOptionsPlugin } from 'webpack'

const config = {
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
            options: { minimize: true }
          },
          {
            loader: 'posthtml-loader'
          }
        ]
      }
    ]
  },
  plugins: [
    new LoaderOptionsPlugin({
      options: {
        posthtml(ctx) {
          return {
            parser: require('posthtml-pug'),
            plugins: [
              require('posthtml-bem')()
            ]
          }
        }
      }
    })
  ]
}

export default config
$ npm i rollup-plugin-posthtml -D
# or
$ npm i rollup-plugin-posthtml-template -D
import { join } from 'path';

import posthtml from 'rollup-plugin-posthtml-template';
// or
// import posthtml from 'rollup-plugin-posthtml';

import sugarml from 'posthtml-sugarml';  // npm i posthtml-sugarml -D
import include from 'posthtml-include';  // npm i posthtml-include -D

export default {
  entry: join(__dirname, 'main.js'),
  dest: join(__dirname, 'bundle.js'),
  format: 'iife',
  plugins: [
    posthtml({
      parser: sugarml(),
      plugins: [include()],
      template: true  // only rollup-plugin-posthtml-template
    })
  ]
};

Parser

import pug from 'posthtml-pug'

posthtml().process(html, { parser: pug(options) }).then((result) => result.html)
Name Status Description
posthtml-pug npm Pug Parser
sugarml npm SugarML Parser

Plugins

In case you want to develop your own plugin, we recommend using posthtml-plugin-starter to get started.

Maintainers


Ivan Demidov

Ivan Voischev

Contributors

Backers

Thank you to all our backers! 🙏 [Become a backer]

grunt-posthtml's People

Contributors

dependabot[bot] avatar scrum avatar tcotton avatar voischev avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

grunt-posthtml's Issues

bug(async): How to use async PostHTML plugins in Grunt?

1. Summary

See header.

2. Problem

By current standards img tag must have height and width attributes again. I want automatically add these attributes to every img tag in my HTML files.

Possibly, I can do it via posthtml-img-autosize plugin, but I don’t understand, how I can use it in my Grunt workflow.

3. MCVE

You can see it in KiraPosthtmlAsync branch of my demo/debugging repository.

  1. Gruntfile.coffee:

    module.exports = (grunt) ->
    
        grunt.loadNpmTasks 'grunt-juwain-posthtml'
    
        grunt.initConfig
    
            posthtml:
                options:
                    use: [
                        require('posthtml-img-autosize')(processEmptySize: true)
                    ]
                single:
                    files: [
                        src: 'KiraPostHTML.html'
                        dest: 'KiraPostHTMLGrunt.html'
                    ]
  2. .travis.yml:

    os: linux
    
    dist: focal
    
    git:
      depth: 1
    
    cache: false
    
    language: node_js
    
    node_js:
    # [INFO] The latest Node.js version:
    # https://docs.travis-ci.com/user/languages/javascript-with-nodejs/#specifying-nodejs-versions
    - node
    
    install:
    - npm install -g grunt-cli
    - npm install
    
    script:
    - grunt posthtml --verbose
  3. KiraPostHtml.html:

    <!doctype html>
    <html>
    
    <head>
        <meta charset="utf-8">
    
        <title>Kira Goddess!</title>
        <style>
            .webp .SashaIconAside {
                background-image: url(NeliaLeaves.webp)
            }
    
            .no-webp .SashaIconAside {
                background-image: url(NeliaLeaves.jpg)
            }
        </style>
    </head>
    
    <body>
        <picture>
            <source srcset="NeliaLeaves.webp" type="image/webp">
            <img src="NeliaLeaves.jpg" alt="Kira Goddess">
        </picture>
        <img alt="Kira Goddess" src="NeliaLeaves.jpg">
        <img alt="Kira Goddess" src="https://i.imgur.com/J17UOiZ.jpg">
    </body>
    
    </html>

4. Behavior

4.1. Desired

Successful addition width and height attributes to every img tag in KiraPostHtml.html

4.2. Current

Travis CI build:

Warning: Can’t process contents in sync mode because of async plugin:  Use --force to continue.

As I understand, I get this error, because “Async Plugins can’t be used in sync mode”.

5. Not helped

I tried to find information about asynchronous plugins usage for Grunt. I read:

  1. Custom tasks and this.async from official Grunt documentation
  2. Asynchronous tasks section from “Getting Started with Grunt” book
  3. Asynchronous Grunt Tasks article

Also, I tried GitHub search queries as this, but I couldn’t find anyone to use async PostHTML plugins in Grunt projects.

Thanks.

feature_request(behavior): handle warnings and errors

1. Summary

It would be nice, if grunt-posthtml will catch errors and warnings as any normal Grunt plugin:

  1. grunt-posthtml will have exit codes and the build to fail if the exit code is not zero.
  2. The plugin would show users error information even if Grunt user set up NODE_NO_WARNINGS 1.

2. Argumentation

2.1. Common cause

grunt-posthtml users’ usability.

2.2. Details

Currently, if something goes wrong, grunt-posthtml:

  1. Doesn’t notify that a warning/error has occurred.
  2. Doesn’t show warning/error details if NODE_NO_WARNINGS 1. I use NODE_NO_WARNINGS 1, because for real project Node.js displays a lot of messages about problems in dependencies that not updated for a long time. They interfere with the normal viewing of the console output.

3. MCVE

You can see this configuration in the KiraPostHTMLImgAutosize branch of my demo/debugging repository.

  1. The part of package.json:

    {
        "devDependencies": {
            "coffeescript": "^2.5.1",
            "grunt": "^1.3.0",
            "grunt-posthtml": "0.5.1",
            "posthtml-img-autosize": "^0.1.6"
        }
    }
  2. Gruntfile.coffee:

    module.exports = (grunt) ->
    
        grunt.loadNpmTasks 'grunt-posthtml'
    
        grunt.initConfig
    
            posthtml:
                options:
                    use: [
                        require('posthtml-img-autosize')(processEmptySize: true)
                    ]
                single:
                    files: [
                        src: 'KiraPostHTML.html'
                        dest: 'KiraImgAutosizeGrunt.html'
                    ]
    
  3. The part of .travis.yml:

    before_install:
    - export NODE_NO_WARNINGS=1
    
    install:
    - npm install -g grunt-cli posthtml-cli posthtml-img-autosize
    - npm install
    
    script:
    - grunt posthtml --verbose
    - posthtml KiraPostHTML.html -o KiraImgAutosizeCLI.html -u posthtml-img-autosize --posthtml-img-autosize.processEmptySize true
    
    after_failure:
    - cat KiraImgAutosizeGrunt.html
  4. KiraPostHTML.html:

    <!doctype html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title>Kira Goddess!</title>
    </head>
    
    <body>
        <img alt="Nelia leaves" src="NeliaLeaves.jpg">
        <img alt="Kira Goddess" src="https://i.imgur.com/J17UOiZ.jpg">
        <img alt="Non existing image" src="KiraNonExistingImage.jpg">
    </body>
    
    </html>

    Image KiraNonExistingImage.jpg not exists.

4. Behavior

4.1. Expected — posthtml-cli

  • Travis CI build:

    $ posthtml KiraPostHTML.html -o KiraImgAutosizeCLI.html -u posthtml-img-autosize --posthtml-img-autosize.processEmptySize true
    
    Error: Promise rejected with value: "ENOENT: no such file or directory, open '/home/travis/build/Kristinita/SashaGruntDebugging/KiraNonExistingImage.jpg'"
    
        at process.<anonymous> (/home/travis/.nvm/versions/node/v14.13.1/lib/node_modules/posthtml-cli/node_modules/hard-rejection/index.js:15:12)
    
        at process.emit (events.js:314:20)
    
        at processPromiseRejections (internal/process/promises.js:245:33)
    
        at processTicksAndRejections (internal/process/task_queues.js:94:32)
    
    The command "posthtml KiraPostHTML.html -o KiraImgAutosizeCLI.html -u posthtml-img-autosize --posthtml-img-autosize.processEmptySize true" exited with 1.

4.2. Unwanted — grunt-posthtml

  • Travis CI build:

    $ grunt posthtml --verbose
    
    Initializing
    
    Command-line options: --verbose, --gruntfile=/home/travis/build/Kristinita/SashaGruntDebugging/Gruntfile.coffee
    
    Reading "Gruntfile.coffee" Gruntfile…OK
    
    Registering Gruntfile tasks.
    
    Registering "grunt-posthtml" local Npm module tasks.
    
    Reading /home/travis/build/Kristinita/SashaGruntDebugging/node_modules/grunt-posthtml/package.json…OK
    
    Parsing /home/travis/build/Kristinita/SashaGruntDebugging/node_modules/grunt-posthtml/package.json…OK
    
    Loading "posthtml.js" tasks…OK
    
    + posthtml
    
    Initializing config…OK
    
    Loading "Gruntfile.coffee" tasks…OK
    
    >> No tasks were registered or unregistered.
    
    Running tasks: posthtml
    
    Running "posthtml" task
    
    Running "posthtml:single" (posthtml) task
    
    Verifying property posthtml.single exists in config…OK
    
    Files: KiraPostHTML.html -> KiraImgAutosizeGrunt.html
    
    Options: use=[null], singleTags=[], closingSingleTag="default", skipParse=null, sync=null
    
    Reading KiraPostHTML.html…OK
    
    The command "grunt posthtml --verbose" exited with 0.

File KiraImgAutosizeGrunt.html was not created:

$ cat KiraImgAutosizeGrunt.html

cat: KiraImgAutosizeGrunt.html: No such file or directory

But there is no information in the output that an error has occurred. Exit code is 0.

Thanks.

bug(documentation): All plugins doesn't work

1. Summary

Any PostHTML plugin doesn't work for me, if I use grunt-posthtml.

Possibly, it not bugs in my own configuration, but, possibly, it:

  • incorrect examples in documentation,

or

  • grunt-posthtml outdated.

2. Configuration

See SashaPosthtml branch of my example repository. I include to this branch files:

  • package.json,
  • Gruntfile.coffee,
  • SashaPosthtmlExample.html — example HTML file.

For example, I try posthtml-alt-always, posthtml-aria-tabs and posthtml-doctype plugins.

3. Steps to reproduce

I run command in console:

grunt posthtml --verbose

4. Expected behavior

Transforming HTML in SashaPosthtmlExample.html as in:

  1. Alt Always example,
  2. Aria Tabs example.

5. Actual behavior

posthtml command run, but file SashaPosthtmlExample.html not modified:

D:\SashaDemoRepositories\SashaGruntDebugging>grunt posthtml --verbose
Initializing
Command-line options: --no-color, --verbose

Reading "Gruntfile.coffee" Gruntfile…OK

Registering Gruntfile tasks.

Registering "grunt-dev-update" local Npm module tasks.
Reading D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-dev-update\package.json…OK
Parsing D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-dev-update\package.json…OK
Loading "dev_update.js" tasks…OK
+ devUpdate

Registering "grunt-postcss" local Npm module tasks.
Reading D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-postcss\package.json…OK
Parsing D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-postcss\package.json…OK
Loading "postcss.js" tasks…OK
+ postcss

Registering "grunt-posthtml" local Npm module tasks.
Reading D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-posthtml\package.json…OK
Parsing D:\SashaDemoRepositories\SashaGruntDebugging\node_modules\grunt-posthtml\package.json…OK
Loading "posthtml.js" tasks…OK
+ posthtml
Initializing config…OK
Loading "Gruntfile.coffee" tasks…OK
+ update

Running tasks: posthtml

Running "posthtml" task

Running "posthtml:single" (posthtml) task
Verifying property posthtml.single exists in config…OK
Files: output/SashaPosthtml/SashaPosthtmlExample.html -> output/SashaPosthtml/SashaPosthtmlExample.html
Options: use=[null,null,null], singleTags=[], closingSingleTag="default", skipParse=null, sync=null
Reading output/SashaPosthtml/SashaPosthtmlExample.html…OK

Done.

6. Not helped

  1. I try building the files object dynamically instead of single file build → I get same behavior.

7. Another Grunt wrappers

Many another Grunt plugins works for me successful, see Gruntfile.coffee of my real repository.

For example, postcss-autoprefixer and another plugins for [**grunt-postcss**](https://github.com/nDmitry/grunt-postcss) successful works for my demo repository.

SashaPosthtmlExample.css before:

.SashaExampleClass {
    tab-size: 4;
}

I run command in console:

grunt postcss

SashaPosthtmlExample.css after:

.SashaExampleClass {
    -moz-tab-size: 4;
      -o-tab-size: 4;
         tab-size: 4;
}

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.