shellscape/postcss-values-parser

Cannot parse proprietary IE functions

dalbitresb12 opened this issue · 3 comments

  • Operating System (or Browser): Ubuntu 20.04 running on WSL 2 (Windows 10 2004)
  • Node Version: v14.16.0
  • postcss-values-parser Version: v3.2.1 and v5.0.0

How Do We Reproduce?

Using this block of CSS with postcss-env-function v3.0.0 (which uses v3.2.1 of this library internally), the parser hangs indefinitely:

.leaflet-oldie .leaflet-popup-tip {
  filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}

The previous CSS block was modified from this block of CSS from Leaflet.

With a recent PR (#134), the previous bug was fixed. The patch from that PR can be applied to both versions and it fixes the issue where the parser hangs indefinitely. After applying that patch locally to both versions, I tried that same block of code again with postcss-env-function with this script:

const postcss = require('postcss');
const postcssEnvFunction = require('postcss-env-function');

const plugins = [postcssEnvFunction()];

const css = `
.leaflet-oldie .leaflet-popup-tip {
  filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
`;

postcss(plugins)
  .process(css, { from: undefined })
  .then(result => {
    console.log(result.css);
  })
  .catch(err => {
    console.log(err);
  });

It now throws this error:

CssSyntaxError: <css input>:1:1: Unknown word
    at <input css DopWqP>:3:3
    at Input.error ([redacted]/node_modules/postcss-env-function/node_modules/postcss/lib/input.js:128:16)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss-env-function/node_modules/postcss/lib/parser.js:561:22)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:195:15)
    at ValuesParser.other ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:110:10)
    at ValuesParser.parse ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:135:16)
    at parse ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/index.js:21:12)
    at Function.fromTokens ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/nodes/Func.js:177:20)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:152:12)
    at ValuesParser.other ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:110:10)
    at ValuesParser.parse ([redacted]/node_modules/postcss-env-function/node_modules/postcss-values-parser/lib/ValuesParser.js:135:16) {
  reason: 'Unknown word',
  source: 'M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678',
  line: 1,
  column: 1,
  input: {
    line: 1,
    column: 1,
    source: 'M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678'
  },
  postcssNode: Declaration {
    raws: { before: '\n  ', between: ': ' },
    type: 'decl',
    parent: Rule {
      raws: [Object],
      type: 'rule',
      nodes: [Array],
      parent: [Root],
      source: [Object],
      selector: '.leaflet-oldie .leaflet-popup-tip',
      lastEach: 1,
      indexes: [Object],
      [Symbol(isClean)]: false
    },
    source: { start: [Object], input: [Input], end: [Object] },
    prop: 'filter',
    value: 'progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)',
    [Symbol(isClean)]: false
  },
  plugin: 'postcss-env-fn'
}

Using v5.0.0 (the latest release of this library) with this script gives the same result:

const { parse } = require('postcss-values-parser');

const css = 'progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)';
const ast = parse(css);
console.log(ast.toString());

Running the previous script results in this error like the previous one:

[redacted]/node_modules/postcss/lib/parser.js:518
    throw this.input.error('Unknown word', tokens[0][2])
    ^

CssSyntaxError: <css input>:1:1: Unknown word
    at Input.error ([redacted]/node_modules/postcss/lib/input.js:123:16)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss/lib/parser.js:518:22)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:195:15)
    at ValuesParser.other ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:110:10)
    at ValuesParser.parse ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:135:16)
    at parse ([redacted]/node_modules/postcss-values-parser/lib/index.js:21:12)
    at Function.fromTokens ([redacted]/node_modules/postcss-values-parser/lib/nodes/Func.js:177:20)
    at ValuesParser.unknownWord ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:152:12)
    at ValuesParser.other ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:110:10)
    at ValuesParser.parse ([redacted]/node_modules/postcss-values-parser/lib/ValuesParser.js:135:16) {
  reason: 'Unknown word',
  source: 'M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678',
  line: 1,
  column: 1,
  input: {
    line: 1,
    column: 1,
    source: 'M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678'
  }
}

Expected Behavior

It should probably ignore these types of proprietary functions from IE.

Actual Behavior

It throws the errors I mentioned before.

I've found that using ignoreUnknownWords set to true parses successfully the CSS block, but I'm not sure if a special case should be added for this case. Maybe we could treat it completely as a string (since its just for legacy purposes). I haven't worked with IE filters before, so I'm not sure if it is possible to ignore anything that starts with progid.

Thanks for the issue. PRs are welcome

The next major version is being upgraded to handle everything that is spec compliant. Unfortunately, IE filters are not. I'm planning on a non-spec-compliant mode, but that will likely take some time. As this isn't spec compliant, and ignoreUnknownWords workaround works, closing this one.