* Stringifies PostCSS nodes while taking interpolated expressions * into account.
| 58 | * into account. |
| 59 | */ |
| 60 | class LinariaStringifier extends Stringifier { |
| 61 | /** @inheritdoc */ |
| 62 | public constructor(builder: Builder) { |
| 63 | const wrappedBuilder: Builder = ( |
| 64 | str: string, |
| 65 | node?: AnyNode, |
| 66 | type?: 'start' | 'end' |
| 67 | ): void => { |
| 68 | // We purposely ignore the root node since the only thing we should |
| 69 | // be stringifying here is already JS (before/after raws) so likely |
| 70 | // already contains backticks on purpose. |
| 71 | // |
| 72 | // Similarly, if there is no node, we're probably stringifying |
| 73 | // pure JS which never contained any CSS. Or something really weird |
| 74 | // we don't want to touch anyway. |
| 75 | // |
| 76 | // For everything else, we want to escape backticks. |
| 77 | if (!node || node?.type === 'root') { |
| 78 | builder(str, node, type); |
| 79 | } else { |
| 80 | builder(str.replace(/\\/g, '\\\\').replace(/`/g, '\\`'), node, type); |
| 81 | } |
| 82 | }; |
| 83 | super(wrappedBuilder); |
| 84 | } |
| 85 | |
| 86 | public override atrule(node: AtRule, semicolon?: boolean) { |
| 87 | const { params } = node; |
| 88 | |
| 89 | const expressionStrings = node.root().raws.linariaTemplateExpressions; |
| 90 | if (params.includes(placeholderText)) { |
| 91 | // eslint-disable-next-line no-param-reassign |
| 92 | node.params = substitutePlaceholders(params, expressionStrings); |
| 93 | } |
| 94 | |
| 95 | super.atrule(node, semicolon); |
| 96 | } |
| 97 | |
| 98 | /** @inheritdoc */ |
| 99 | public override comment(node: Comment): void { |
| 100 | const placeholderPattern = new RegExp(`^${placeholderText}:\\d+$`); |
| 101 | if (placeholderPattern.test(node.text)) { |
| 102 | const [, expressionIndexString] = node.text.split(':'); |
| 103 | const expressionIndex = Number(expressionIndexString); |
| 104 | const root = node.root(); |
| 105 | const expressionStrings = root.raws.linariaTemplateExpressions; |
| 106 | |
| 107 | if (expressionStrings && !Number.isNaN(expressionIndex)) { |
| 108 | const expression = expressionStrings[expressionIndex]; |
| 109 | |
| 110 | if (expression) { |
| 111 | this.builder(expression, node); |
| 112 | return; |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | super.comment(node); |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…