Giter Club home page Giter Club logo

postcss-html's Introduction

PostCSS HTML Syntax

NPM license NPM version NPM downloads NPM downloads NPM downloads Build Status

PostCSS syntax for parsing HTML (and HTML-like)

Getting Started

First thing's first, install the module:

npm install postcss-html --save-dev

If you want support SCSS/SASS/LESS/SugarSS syntax, you need to install the corresponding module.

Use Cases

const postcss = require('postcss');
const syntax = require('postcss-html')({
    // syntax for parse scss (non-required options)
    scss: require('postcss-scss'),
    // syntax for parse less (non-required options)
    less: require('postcss-less'),
    // syntax for parse css blocks (non-required options)
    css: require('postcss-safe-parser'),
});
postcss(plugins).process(source, { syntax: syntax }).then(function (result) {
    // An alias for the result.css property. Use it with syntaxes that generate non-CSS output.
    result.content
});

If you want support SCSS/SASS/LESS/SugarSS syntax, you need to install these module:

Advanced Use Cases

Options

const options = {
    rules: [
        {
            // custom language
            test: /^postcss$/i,
            lang: 'scss'
        },
        {
            // custom language
            test: /^customcss$/i,
            lang: 'custom'
        },
    ],

    // custom parser for CSS (using `postcss-safe-parser`)
    css: 'postcss-safe-parser',
    // custom parser for SASS (PostCSS-compatible syntax.)
    sass: require('postcss-sass'),
    // custom parser for SCSS (by module name)
    scss: 'postcss-scss',
    // custom parser for LESS (by module path)
    less: require.resolve('./node_modules/postcss-less'),
    // custom parser for SugarSS
    sugarss: require('sugarss'),
    // custom parser for custom language
    custom: require('postcss-custom-syntax'),
}
const syntax = require('postcss-html')(options);

Turning PostCSS off from within your HTML

PostCSS can be temporarily turned off by using special comments in your HTML. For example:

<html>
<body>
<!-- postcss-ignore -->
<a style="color: red;" description="style is not parsed."></a>

<a style="color: red;" description="style is parsed."></a>
<html>
<body>
<!-- postcss-disable -->
<a style="color: red;" description="style is not parsed."></a>
<a style="color: red;" description="style is not parsed."></a>
<!-- postcss-enable -->

<a style="color: red;" description="style is parsed."></a>

Linting with Stylelint

The main use case of this plugin is to apply linting with Stylelint to <style> tags and <div style="*"> property in HTML (and HTML-like).

You can use it by configuring your stylelint config as follows:

{
    "overrides": [
        {
            "files": ["*.html", "**/*.html"],
            "customSyntax": "postcss-html"
        }
    ]
}

You can use it more easily if you use an already configured sharable config.

{
+    "extends": [
+        "stylelint-config-html",
         // If you are using Vue.
+        "stylelint-config-recommended-vue"
+    ],
-    "overrides": [
-        {
-            "files": ["*.html", "**/*.html"],
-            "customSyntax": "postcss-html"
-        }
-    ]
}

postcss-html's People

Contributors

ai avatar ajcwebdev avatar gucong3000 avatar hudochenkov avatar kagawagao avatar ota-meshi avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

postanu ai ntnyq-dev

postcss-html's Issues

Official Svelte Support

Hey there! I've been struggling with getting Svelte working in VS-Code again since stylelint v14. It would be great to have some official support for Svelte, or perhaps just a section in the docs for any Svelte-specific instructions. If I can figure this out, I'll try to make a PR if appropriate. Thanks!!

webpack error

I couldn't find any information about this anywhere, so I might be missing something obvious - sorry if that's the case.

I use postcss-html to parse html content to get style tag . But when I used webpack to package, an exception occurred

  "devDependencies": {
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2"
  },
  "dependencies": {
    "postcss": "^8.4.12",
    "postcss-html": "^1.3.0"
  }

the code like

const postcss = require('postcss');
const syntax = require('postcss-html')({});

const source = `
<template>
    <div>1</div>
</template>
<script>
</script>
<style>
  .a{
    color:red
  }
</style>
<style>
  .b{
    color:red
  }
</style>
`
async function a(){
    const {root} = await postcss().process(source, { syntax })
    root.walkDecls('color', (del) => {
        console.log(del)
    })
}
a()

the webpack.config.js

const path = require('path');
module.exports = {
	entry: './index.js',
	mode: 'production',
	output: {
		filename: 'extension.js',
		path: path.join(__dirname, 'out')
	}
}

the error

Module not found: Error: Can't resolve 'postcss-sass' 
Module not found: Error: Can't resolve 'postcss-scss' 
Module not found: Error: Can't resolve 'postcss-less'
Module not found: Error: Can't resolve 'sugarss' 
Module not found: Error: Can't resolve 'postcss-styl'

Under webpack, the dependencies here will be checked?

const standardModuleResolvers = {

How to support angular inline styles

This is a great library ,
i would like to to know if this can support angular inline styles
check this syntax for angular component

@Component({
  selector: 'app-root',
  template: `
    <h1>Tour of Heroes</h1>
    <app-hero-main [hero]="hero"></app-hero-main>
  `,
  styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}

https://angular.io/guide/component-styles
angular component inline styles are defined as a property styles defined on @component decorator inside a ts file

<style lang="scss"> not effect

image

module.exports = {
  extends: ['stylelint-config-standard'],
  plugins: ['stylelint-order'],
  overrides: [
    {
      files: ['*.html', '**/*.html', '**/*.vue'],
      customSyntax: 'postcss-html',
    },
  ],
  rules: {
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'justify-content',
      'align-items',
      'float',
      'clear',
      'overflow',
      'overflow-x',
      'overflow-y',
      'width',
      'min-width',
      'max-width',
      'height',
      'min-height',
      'max-height',
      'padding',
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left',
      'margin',
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left',
      'font-size',
      'font-family',
      'font-weight',
      'text-align',
      'text-justify',
      'text-indent',
      'text-overflow',
      'text-decoration',
      'white-space',
      'color',
      'border',
      'border-style',
      'border-width',
      'border-color',
      'border-top',
      'border-top-style',
      'border-top-width',
      'border-top-color',
      'border-right',
      'border-right-style',
      'border-right-width',
      'border-right-color',
      'border-bottom',
      'border-bottom-style',
      'border-bottom-width',
      'border-bottom-color',
      'border-left',
      'border-left-style',
      'border-left-width',
      'border-left-color',
      'border-radius',
      'background',
      'background-position',
      'background-repeat',
      'background-size',
      'background-color',
      'background-clip',
      'opacity',
      'filter',
      'list-style',
      'outline',
      'visibility',
      'box-shadow',
      'text-shadow',
      'resize',
      'transition',
    ],
  },
}

Ignore `style="..."` attributes

I couldn't find any information about this anywhere, so I might be missing something obvious - sorry if that's the case.

Is there any way to have the parser handle <style> tags but not <div style="..."> attributes? I've set this up with a Svelte project, and while the linting is working as I'd hoped in my main style tags, it seems a bit bizarre for the linter to flag things like "Expected empty line before custom property" in a single-line style attribute.

Is there an option that can be configured, or have I messed up some default? And if not, is it something that could be corrected?

Thanks!

`media` attribute contents are missing in the AST

I might be overlooking something but it seems that media attribute contents of style tags are missing in the AST.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.foo {
			color: red;
		}
	</style>
	<style media="(min-width: 500px)">
		.foo {
			color: green;
		}
	</style>
</head>
<body>
</body>
</html>

I would expect the media contents (min-width: 500px) to be present in the AST.
They are there as part of raws.codeBefore but this is a raw string.

To add support for Document and postcss-html in postcss-preset-env we need to be able to distinguish unconditional from conditional style tags.

Is this something that can be added?

This might need to be part of the PostCSS API, so we don't need to have syntax plugin specific code in postcss-preset-env.


AST

[
  <ref *2> Root {
    raws: {
      semicolon: false,
      after: '\n',
      codeBefore: '<!DOCTYPE html>\n' +
        '<html lang="en">\n' +
        '<head>\n' +
        '\t<meta charset="UTF-8">\n' +
        '\t<meta http-equiv="X-UA-Compatible" content="IE=edge">\n' +
        '\t<meta name="viewport" content="width=device-width, initial-scale=1.0">\n' +
        '\t<title>Document</title>\n' +
        '\t<style>\n'
    },
    type: 'root',
    nodes: [ [Rule] ],
    source: {
      input: [Input],
      start: [Object],
      inline: false,
      lang: 'css',
      syntax: [Object]
    },
    lastEach: 1,
    indexes: {},
    document: <ref *1> Document {
      raws: {},
      type: 'document',
      nodes: [Array],
      source: [Object],
      proxyCache: [Circular *1],
      [Symbol(isClean)]: true,
      [Symbol(my)]: true
    },
    proxyCache: [Circular *2],
    [Symbol(isClean)]: false,
    [Symbol(my)]: true
  },
  <ref *3> Root {
    raws: {
      semicolon: false,
      after: '\n',
      codeBefore: '\t</style>\n\t<style media="(min-width: 500px)">\n',
      codeAfter: '\t</style>\n</head>\n<body>\n</body>\n</html>\n'
    },
    type: 'root',
    nodes: [ [Rule] ],
    source: {
      input: [Input],
      start: [Object],
      inline: false,
      lang: 'css',
      syntax: [Object]
    },
    lastEach: 1,
    indexes: {},
    document: <ref *1> Document {
      raws: {},
      type: 'document',
      nodes: [Array],
      source: [Object],
      proxyCache: [Circular *1],
      [Symbol(isClean)]: true,
      [Symbol(my)]: true
    },
    proxyCache: [Circular *3],
    [Symbol(isClean)]: false,
    [Symbol(my)]: true
  }
]

issue when used with postcss-custom-properties

I have an issue with html parsing and postcss-custom-properties. I have the following code

import postcss from 'postcss'
import postcssCustomProperties from 'postcss-custom-properties'
import postcssHtml from 'postcss-html'

const html = `
<!DOCTYPE html>
<html>
<head>
    <style>
        :root {
          --blue: blue
        }
        
        body td {
            color: var(--blue)
        }
        
        @media all and (max-width: 600px) {
            body {
                color: red;
            }
        }
    </style>
</head>
    <body>
        <table border="0" cellpadding="0" cellspacing="0" class="elm_container_wrapper">
            <tr>
                <td>
                    <table border="0" cellpadding="0" cellspacing="0" class="elm_container">
                        <tr class="elm_header">
                            <td>
                                <table border="0" cellpadding="0" cellspacing="0" class="elm_inner_container">
                                    <tr>
                                        <td>
                                            <br>
                                            <a href="#"><img src="https://via.placeholder.com/160x60" width="160" alt="" style="width: 160px"></a>
                                            <br>
                                            <br>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>

                    </table>
                </td>
            </tr>
        </table>
    </body>
</html>
`
const result = postcss([postcssCustomProperties({
    preserve: true
})]).process(html, { syntax: postcssHtml() })

console.log(result.content)

And the problem is that custom properties are not converted corectly.

This should be result, but the css is not processed. It only works when I add <!-- postcss-disable --> before body or if I change the image to text inside the td.

    <style>
        :root {
          --blue: blue
        }
        
        body td {
            color: blue
        ;
            color: var(--blue)
        }
        
        @media all and (max-width: 600px) {
            body {
                color: red;
            }
        }
    </style>

Am I missing something in config or is this a bug? Anyway for my usecase I can add the disable comment and that fixes my problem, but seems hacky.

[vue2] Use `lang="scss"` .vue file, stylelint not working

playground: https://github.com/yamanoku-playground/2021-11-11-postcss-html-issue


If it's just a <style>, it works fine, but if you use <lang="scss">, you will get the following error.

npm run lint-css
> [email protected] lint-css /yamanoku/2021-11-11-postcss-html-issue
> stylelint "**/*.vue"

TypeError: Class extends value undefined is not a constructor or null
    at Object.<anonymous> (/yamanoku/2021-11-11-postcss-html-issue/node_modules/postcss-scss/lib/nested-declaration.js:3:33)
    at Module._compile (/yamanoku/2021-11-11-postcss-html-issue/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (/yamanoku/2021-11-11-postcss-html-issue/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at Object.<anonymous> (/yamanoku/2021-11-11-postcss-html-issue/node_modules/postcss-scss/lib/scss-parser.js:4:25)
    at Module._compile (/yamanoku/2021-11-11-postcss-html-issue/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] lint-css: `stylelint "**/*.vue"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] lint-css script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /yamanoku/.npm/_logs/2021-11-11T03_56_49_433Z-debug.log

If the current playground setup is not enough, I apologize.

v1.0.0

This is a list of what will change in version 1.0.0.

If you want to use it now you can install it using the next tag.

npm install postcss-html@next --save-dev

Changes

  • Upgrade postcss to v8.
  • Removed dependency on postcss-syntax.
  • Changes due to dependency changes.
  • Drop support for node <v12 && v13.
  • Change to use the Document node.
  • Replace Root.raws.beforeStart with Root.raws.codeBefore.
  • Replace Document.raws.afterEnd with Root.raws.codeAfter.
  • Remove postcss patch.
  • Refactor

TypeScript type definition export mismatch in lib/index.d.ts and lib/index.js

There is a mismatch between the exports in the lib/index.d.ts TypeScript definition file and the lib/index.js JavaScript implementation file.

Specifically:

lib/index.d.ts exports a postcssHtml constant of type Syntax from PostCSS:

import type { Syntax } from 'postcss';
const postcssHtml: Syntax;  
export = postcssHtml;

However, lib/index.js exports a postcssHtml function that returns a Syntax:

function postcssHtml() {
  const syntax = { ... }
  return syntax; 
}

module.exports = postcssHtml;

This mismatch between the TypeScript types and JavaScript implementation will cause errors for consumers expecting postcssHtml to be of type Syntax.

Could you please resolve this mismatch and export the same thing from both definition and implementation? Let me know if any other details would be helpful!

Question: how to set separate rule for each language code block for stylelint?

If we have a vue file like this

<script setup lang="ts">
</script>
<template>
    <div style="color: red"></div>
</template>
<style scoped>
// some css code
</style>
<style lang="less" scoped>
// some less code
</style>
<style lang="scss" scoped>
// some scss code
</style>
<style lang="stylus" scoped>
// some stylus code
</style>

I need some stylelint config like this

module.exports = {
    overrides: [
        {
            // Enable the postcss-html processor for all .vue files.
            files: ['**/*.vue'],
            customSyntax: 'postcss-html',
        },
        {
            files: ['**/*.vue/template-*.css'],
            rules: {
                // customize the stylelint rules configuration for vue's template inline style
            },
        },
        {
            files: ['**/*.vue/style-*.css'],
            rules: {
                // customize the stylelint rules configuration for vue's css style block
            },
        },
        {
            files: ['**/*.vue/style-*.less'],
            rules: {
                // customize the stylelint rules configuration for vue's less style block
            },
        },
        {
            files: ['**/*.vue/style-*.scss'],
            rules: {
                // customize the stylelint rules configuration for vue's scss style block
            },
        },
        {
            files: ['**/*.vue/style-*.stylus'],
            rules: {
                // customize the stylelint rules configuration for vue's stylus style block
            },
        },
    ],
};

Releated example:
https://github.com/eslint/eslint-plugin-markdown#advanced-configuration

Svelte: parser hangs on svelte assignment syntax

Given the component:

<label value={something} />

<style>
	label {
		/* styles go here */
	}
</style>

the parser hangs. This is a pretty basic Svelte component, I'm surprised this is happening?

If you take away the value={something}, the parser runs fine.

I am using this with stylelint, so maybe something is going on there..!

sourcemaps are broken and this can throw with the latest PostCSS version

The easiest way to reproduce the issue is to take test/html.js and set map to inline around line 59 :

.process(html, {
	syntax,
	from: "append.html",
	map: {
		inline: true,
	},
})
       stringify for append node:
     Error: Invalid mapping: {"generated":{"column":-1,"line":3},"source":"append.html","original":{"column":0,"line":6},"name":null}
      at SourceMapGenerator.SourceMapGenerator_validateMapping [as _validateMapping] (node_modules/source-map-js/lib/source-map-generator.js:298:13)
      at SourceMapGenerator.SourceMapGenerator_addMapping [as addMapping] (node_modules/source-map-js/lib/source-map-generator.js:110:12)

I can not recreate this error with PostCSS alone.
So it seems to be a bug in postcss-html.

Before this change sourcemaps would also be broken and would contain <no source>.

I tried to look for an obvious source and/or solution but I don't know the codebase here and didn't spot anything.


Workaround for users :

  • disable sourcemaps
  • they were broken anyway

[vue2/3]<style lang="postcss">

when the language is explicitly specified, the linter does not want to work, how can I fix it?
i am using Vue Single-File Component (SFC)

linter not work
image
all done 😥
image

vscode.setting

  // stylelint
  "stylelint.enable": true,
  "stylelint.autoFixOnSave": true,
  "stylelint.useLocal": true,
  "stylelint.validate": ["vue", "postcss", "pcss", "css"],

  "stylelint.packageManager": "yarn",
  // "stylelint.validate": [
  //   "css",
  //   "postcss"
  // ],
  "stylelint.snippet": ["css", "postcss"],
  "stylelint.customSyntax": "postcss-html",
  "stylelint.configFile": "stylelint.config.js"

  // "volar.style.defaultLanguage": "postcss",
  // "tailwindCSS.validate": true

stylelint.config.js

module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-prettier',
    'stylelint-config-html/vue',
    'stylelint-config-html',
    'stylelint-config-recommended-vue',
  ],
  overrides: [
    {
      files: ['**/*.vue'],
      customSyntax: 'postcss-html',
    },
  ],

  rules: {
    'color-function-notation': 'modern',
    'at-rule-semicolon-newline-after': null,
    'block-closing-brace-empty-line-before': null,
    'block-closing-brace-newline-after': 'never-single-line',
    'block-no-empty': null,
    'comment-empty-line-before': null,
    'declaration-block-semicolon-newline-after': null,
    'declaration-colon-space-after': 'always-single-line',
    'declaration-colon-space-before': 'never',
    'function-parentheses-space-inside': null,
    indentation: null,
    'media-feature-colon-space-after': null,
    'media-feature-colon-space-before': null,
    'media-feature-range-operator-space-after': 'never',
    'media-feature-range-operator-space-before': 'never',
    'named-grid-areas-no-invalid': null,
    'no-empty-source': null,
    'no-eol-whitespace': null,
    'rule-empty-line-before': null,
    'string-quotes': 'single',
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'for',
          'if',
          'else',
          'each',
          'mixin',
          'custom-media',
          'define-mixin',
          'include',
          'media',
          'rgba',
        ],
      },
    ],
    'property-no-unknown': [
      true,
      {
        ignoreProperties: ['user-drag'],
      },
    ],
  },
};

.stylelintignore

node_modules
node_modules/
static/
build/
assets/scss/vendors/
assets/scss/templates/
.output/
dist/
bin/
obj/

*.*
!*.vue
!*.html
!*.postcss
!*.pcss 
!*.css 

redirect

Dependency Dashboard

This issue provides visibility into Renovate updates and their statuses. Learn more

This repository currently has no open or pending branches.


  • Check this box to trigger a request for Renovate to run again on this repository

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.