|
1 | | -# 4.0.1 |
| 1 | +# 5.0.0-rc.0 |
2 | 2 |
|
3 | 3 | This release has **BREAKING CHANGES** that were required to fix regressions in 4.0.0. Please read carefully. |
4 | 4 |
|
5 | | -* Combinators |
6 | | - - **Descendant Combinators** The value of descendant combinators used to be all of the spaces found between the selectors. |
7 | | - This made it hard to check for a descendant combinator in comparison to other types of combinators. |
8 | | - In 4.0.1 this changed to being just a single space (`" "`). For descendant selectors with no comments, |
9 | | - additional space is now stored in `node.spaces.before`. Depending on the location of comments, |
10 | | - additional spaces are stored in `node.raws.spaces.before`, `node.raws.spaces.after`, |
11 | | - or `node.raws.value`. |
12 | | - Upgrade hints: |
13 | | - * `node.type === "combinator" && / /.test(node.value)` => `node.type === "combinator" && node.value === " "` |
14 | | - * `node.type === "combinator" && / /.test(node.value)` => `node.type === "combinator" && / /.test(node.toString())` |
15 | | - - **Named Combinators** Although, nonstandard and unlikely to ever become a standard, named combinators |
16 | | - like `/deep/` and `/for/` are now properly parsed as combinators. The value is unescaped and normalized as lowercase. |
17 | | - The original value for the combinator name is stored in `node.raws.value`. |
| 5 | +## Summary of Changes |
| 6 | + |
| 7 | +* The way a descendent combinator that isn't a single space character (E.g. `.a .b`) is stored in the AST has changed. |
| 8 | +* Named Combinators (E.g. `.a /for/ .b`) are now properly parsed as a combinator. |
| 9 | +* It is now possible to look up a node based on the source location of a character in that node and to query nodes if they contain some character. |
| 10 | +* Several bug fixes that caused the parser to hang and run out of memory when a `/` was encountered have been fixed. |
| 11 | + |
| 12 | +### Changes to the Descendent Combinator |
| 13 | + |
| 14 | +In prior releases, the value of a descendant combinator with multiple spaces included all the spaces. |
| 15 | + |
| 16 | +* `.a .b`: Extra spaces are now stored as space before. |
| 17 | + - 3.x: `combinator.value === " "` |
| 18 | + - 4.0: `combinator.value === " " && combinator.spaces.before === " "` |
| 19 | +* `.a /*comment*/.b`: A comment at the end of the combinator causes extra space to become after space. |
| 20 | + - 3.x: `combinator.value === " "` |
| 21 | + - 3.x: `combinator.raws.value === " /*comment/"` |
| 22 | + - 4.0: `combinator.value === " "` |
| 23 | + - 4.0: `combinator.spaces.after === " "` |
| 24 | + - 4.0: `combinator.raws.spaces.after === " /*comment*/"` |
| 25 | +* `.a<newline>.b`: whitespace that doesn't start or end with a single space character is stored as a raw value. |
| 26 | + - 3.x: `combinator.value === "\n"` |
| 27 | + - 3.x: `combinator.raws.value === undefined` |
| 28 | + - 4.0: `combinator.value === " "` |
| 29 | + - 3.x: `combinator.raws.value === "\n"` |
| 30 | + |
| 31 | +### Support for "Named Combinators" |
| 32 | + |
| 33 | +Although, nonstandard and unlikely to ever become a standard, combinators like `/deep/` and `/for/` are now properly supported. |
| 34 | + |
| 35 | +Because they've been taken off the standardization track, there is no spec-official name for combinators of the form `/<ident>/`. However, I talked to [Tab Atkins](https://twitter.com/tabatkins) and we agreed to call them "named combinators" so now they are called that. |
| 36 | + |
| 37 | +Before this release such named combinators were parsed without intention and generated three nodes of type `"tag"` where the first and last nodes had a value of `"/"`. |
| 38 | + |
| 39 | +* `.a /for/ .b` is parsed as a combinator. |
| 40 | + - In prior releases: |
| 41 | + - `root.nodes[0].nodes[1].type === "tag"` |
| 42 | + - `root.nodes[0].nodes[1].value === "/"` |
| 43 | + - New hotness: |
| 44 | + - `root.nodes[0].nodes[1].type === "combinator"` |
| 45 | + - `root.nodes[0].nodes[1].value === "/for/"` |
| 46 | +* `.a /F\6fR/ .b` escapes are handled and uppercase is normalized. |
| 47 | + - In prior releases: |
| 48 | + - `root.nodes[0].nodes[2].type === "tag"` |
| 49 | + - `root.nodes[0].nodes[2].value === "F\\6fR"` |
| 50 | + - New hotness: |
| 51 | + - `root.nodes[0].nodes[1].type === "combinator"` |
| 52 | + - `root.nodes[0].nodes[1].value === "/for/"` |
| 53 | + - `root.nodes[0].nodes[1].raws.value === "/F\\6fR/"` |
| 54 | + |
| 55 | +### Source position checks and lookups |
| 56 | + |
| 57 | +A new API was added to look up a node based on the source location. |
| 58 | + |
| 59 | +```js |
| 60 | +const selectorParser = require("postcss-selector-parser"); |
| 61 | +// You can find the most specific node for any given character |
| 62 | +let combinator = selectorParser.astSync(".a > .b").atPosition(1,4); |
| 63 | +combinator.toString() === " > "; |
| 64 | +// You can check if a node includes a specific character |
| 65 | +// Whitespace surrounding the node that is owned by that node |
| 66 | +// is included in the check. |
| 67 | +[2,3,4,5,6].map(column => combinator.isAtPosition(1, column)); |
| 68 | +// => [false, true, true, true, false] |
| 69 | +``` |
18 | 70 |
|
19 | 71 | # 4.0.0 |
20 | 72 |
|
|
0 commit comments