diff --git a/docs/Func.md b/docs/Func.md index b207709..db88912 100644 --- a/docs/Func.md +++ b/docs/Func.md @@ -17,7 +17,7 @@ The name of the function. ### `params` Type: `String`
-A `String` representation of the body of the function, between parenthesis, including the parenthesis characters. This value will be parsed and the result placed into the `nodes` property. +A `String` representation of the body of the function, between parenthesis, including the parenthesis characters. This value will be parsed and the result placed into the `nodes` property. This value should be considered only a snapshot for reference. To manipulate function parameters, please leverage the `Container.nodes` property. ### `type` Type: `String` diff --git a/lib/ValuesStringifier.js b/lib/ValuesStringifier.js index 8856cf0..06b4c77 100644 --- a/lib/ValuesStringifier.js +++ b/lib/ValuesStringifier.js @@ -1,11 +1,13 @@ const Stringifier = require('postcss/lib/stringifier'); module.exports = class LessStringifier extends Stringifier { - basic(node) { - const after = this.raw(node, 'after'); + basic(node, value) { + const print = value || node.value; + const after = node.raws.after ? this.raw(node, 'after') || '' : ''; + // NOTE: before is handled by postcss in stringifier.body - this.builder(node.value, node, 'start'); - this.builder(after || '', node, 'end'); + this.builder(print, node, 'start'); + this.builder(after, node, 'end'); } atword(...args) { @@ -23,25 +25,30 @@ module.exports = class LessStringifier extends Stringifier { } func(node) { - const after = this.raw(node, 'after'); + const after = this.raw(node, 'after') || ''; - this.builder(node.name + node.params, node, 'start'); - this.builder(after || '', node, 'end'); + this.builder(`${node.name}(`, node, 'start'); + + for (const child of node.nodes) { + // since we're duplicating this.body here, we have to handle `before` + // but we don't want the postcss default \n value, so check it's non-empty first + const before = child.raws.before ? this.raw(child, 'before') : ''; + if (before) { + this.builder(before); + } + this.stringify(child); + } + + this.builder(`)${after}`, node, 'end'); } interpolation(node) { - const after = this.raw(node, 'after'); - - this.builder(node.prefix + node.params, node, 'start'); - this.builder(after || '', node, 'end'); + this.basic(node, node.prefix + node.params); } numeric(node) { - const start = node.value + node.unit; - const after = this.raw(node, 'after'); - - this.builder(start, node, 'start'); - this.builder(after || '', node, 'end'); + const print = node.value + node.unit; + this.basic(node, print); } operator(node) { diff --git a/lib/index.js b/lib/index.js index 4c149c1..6f74a68 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,8 +13,6 @@ const Input = require('postcss/lib/input'); const Parser = require('./ValuesParser'); const Stringifier = require('./ValuesStringifier'); -// TODO: walk methods for custom nodes - module.exports = { parse(css, options) { const input = new Input(css, options); diff --git a/lib/nodes/Func.js b/lib/nodes/Func.js index cc7b6c5..945cc87 100644 --- a/lib/nodes/Func.js +++ b/lib/nodes/Func.js @@ -84,12 +84,17 @@ class Func extends Container { // use a new parser to parse the params of the function. recursion here makes for easier maint // we must require this here due to circular dependency resolution const { parse } = require('../'); // eslint-disable-line global-require - const { nodes: children } = parse(params, opts); + const root = parse(params, opts); + const { nodes: children } = root; // TODO: correct line and character position (should we just pad the input? probably easiest) for (const child of children) { node.push(child); } + + if (root.raws.after) { + node.last.raws.after = root.raws.after; + } } parser.end(lastToken); diff --git a/test/integration.test.js b/test/integration.test.js index 5e8bb33..ed9d323 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -13,7 +13,8 @@ */ const test = require('ava'); -const { parse } = require('../lib'); +const { nodeToString, parse } = require('../lib'); +const Punctuation = require('../lib/nodes/Punctuation'); test('integration', (t) => { let root = parse(`normal normal 1em/1 'Source Sans Pro', serif`); @@ -26,3 +27,19 @@ test('integration', (t) => { root = parse('1 / -1'); t.is(root.nodes.length, 3); }); + +test('manipulation', (t) => { + const source = 'rgb(100% 100% 100%)'; + const root = parse(source); + const { first } = root; + + let string = nodeToString(root); + t.is(source, string); + + first.nodes.splice(1, 0, new Punctuation({ value: ',', parent: first })); + first.nodes.splice(3, 0, new Punctuation({ value: ',', parent: first })); + + string = nodeToString(root); + t.not(source, string); + t.snapshot(string); +}); diff --git a/test/snapshots/func.test.js.md b/test/snapshots/func.test.js.md index c10ec09..d0d5c88 100644 --- a/test/snapshots/func.test.js.md +++ b/test/snapshots/func.test.js.md @@ -182,7 +182,7 @@ Generated by [AVA](https://ava.li). Numeric { parent: [Circular], raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -344,7 +344,7 @@ Generated by [AVA](https://ava.li). Numeric { parent: [Circular], raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1314,7 +1314,7 @@ Generated by [AVA](https://ava.li). Numeric { parent: [Circular], raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1379,7 +1379,7 @@ Generated by [AVA](https://ava.li). parent: [Circular], quote: '"', raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1443,7 +1443,7 @@ Generated by [AVA](https://ava.li). parent: [Circular], quote: '"', raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1507,7 +1507,7 @@ Generated by [AVA](https://ava.li). parent: [Circular], quote: '\'', raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1571,7 +1571,7 @@ Generated by [AVA](https://ava.li). parent: [Circular], quote: '\'', raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1766,7 +1766,7 @@ Generated by [AVA](https://ava.li). isVariable: false, parent: [Circular], raws: { - after: '', + after: ' ', before: '', }, source: { @@ -1858,7 +1858,7 @@ Generated by [AVA](https://ava.li). isVariable: false, parent: [Circular], raws: { - after: '', + after: ' ', before: ' ', }, source: { @@ -1950,7 +1950,7 @@ Generated by [AVA](https://ava.li). isVariable: false, parent: [Circular], raws: { - after: '', + after: ' ', before: ' ', }, source: { diff --git a/test/snapshots/func.test.js.snap b/test/snapshots/func.test.js.snap index 6deba3e..ba5e040 100644 Binary files a/test/snapshots/func.test.js.snap and b/test/snapshots/func.test.js.snap differ diff --git a/test/snapshots/integration.test.js.md b/test/snapshots/integration.test.js.md new file mode 100644 index 0000000..7f822c2 --- /dev/null +++ b/test/snapshots/integration.test.js.md @@ -0,0 +1,11 @@ +# Snapshot report for `test/integration.test.js` + +The actual snapshot is saved in `integration.test.js.snap`. + +Generated by [AVA](https://ava.li). + +## manipulation + +> Snapshot 1 + + 'rgb(100%, 100%, 100%)' diff --git a/test/snapshots/integration.test.js.snap b/test/snapshots/integration.test.js.snap new file mode 100644 index 0000000..45b9db6 Binary files /dev/null and b/test/snapshots/integration.test.js.snap differ