|
1 | 1 | import type {Dictionary} from 'lodash';
|
2 | 2 |
|
| 3 | +import { |
| 4 | + countLineAmount, |
| 5 | + emplaceSerializedFrontMatter, |
| 6 | + separateAndExtractFrontMatter, |
| 7 | + serializeFrontMatter, |
| 8 | + transformFrontMatterValues, |
| 9 | +} from '../frontmatter'; |
| 10 | + |
3 | 11 | import applySubstitutions from './substitutions';
|
4 | 12 | import {prepareSourceMap} from './sourceMap';
|
5 | 13 | import applyCycles from './cycles';
|
@@ -66,7 +74,7 @@ function repairCode(str: string, codes: string[]) {
|
66 | 74 | return replace(fence, fence, (code) => codes[Number(code)], str);
|
67 | 75 | }
|
68 | 76 |
|
69 |
| -function liquid< |
| 77 | +function liquidSnippet< |
70 | 78 | B extends boolean = false,
|
71 | 79 | C = B extends false ? string : {output: string; sourceMap: Dictionary<string>},
|
72 | 80 | >(
|
@@ -141,6 +149,67 @@ function liquid<
|
141 | 149 | return output as unknown as C;
|
142 | 150 | }
|
143 | 151 |
|
144 |
| -// 'export default' instead of 'export = ' because of circular dependency with './cycles.ts'. |
145 |
| -// somehow it breaks import in './cycles.ts' and imports nothing |
146 |
| -export default liquid; |
| 152 | +type TransformSourceMapOptions = { |
| 153 | + emplacedResultOffset: number; |
| 154 | + emplacedSourceOffset: number; |
| 155 | +}; |
| 156 | + |
| 157 | +function transformSourceMap( |
| 158 | + sourceMap: Dictionary<string>, |
| 159 | + {emplacedResultOffset, emplacedSourceOffset}: TransformSourceMapOptions, |
| 160 | +) { |
| 161 | + return Object.fromEntries( |
| 162 | + Object.entries(sourceMap).map(([lineInResult, lineInSource]) => [ |
| 163 | + (Number(lineInResult) + emplacedResultOffset).toString(), |
| 164 | + (Number(lineInSource) + emplacedSourceOffset).toString(), |
| 165 | + ]), |
| 166 | + ); |
| 167 | +} |
| 168 | + |
| 169 | +function liquidDocument< |
| 170 | + B extends boolean = false, |
| 171 | + C = B extends false ? string : {output: string; sourceMap: Dictionary<string>}, |
| 172 | +>( |
| 173 | + originInput: string, |
| 174 | + vars: Record<string, unknown>, |
| 175 | + path?: string, |
| 176 | + settings?: ArgvSettings & {withSourceMap?: B}, |
| 177 | +): C { |
| 178 | + const {frontMatter, frontMatterStrippedContent, frontMatterLineCount} = |
| 179 | + separateAndExtractFrontMatter(originInput, path); |
| 180 | + |
| 181 | + const transformedFrontMatter = transformFrontMatterValues(frontMatter, (v) => |
| 182 | + typeof v === 'string' |
| 183 | + ? liquidSnippet(v, vars, path, {...settings, withSourceMap: false}) |
| 184 | + : v, |
| 185 | + ); |
| 186 | + const transformedAndSerialized = serializeFrontMatter(transformedFrontMatter); |
| 187 | + |
| 188 | + // -1 comes from the fact that the last line in serialized FM is the same as the first line in stripped content |
| 189 | + const resultFrontMatterOffset = Math.max(0, countLineAmount(transformedAndSerialized) - 1); |
| 190 | + const sourceFrontMatterOffset = Math.max(0, frontMatterLineCount - 1); |
| 191 | + |
| 192 | + const liquidProcessedContent = liquidSnippet(frontMatterStrippedContent, vars, path, settings); |
| 193 | + |
| 194 | + // typeof check for better inference; the catch is that return of liquidSnippet can be an |
| 195 | + // object even with source maps off, see `substitutions.test.ts` |
| 196 | + return (settings?.withSourceMap && typeof liquidProcessedContent === 'object' |
| 197 | + ? { |
| 198 | + output: emplaceSerializedFrontMatter( |
| 199 | + liquidProcessedContent.output, |
| 200 | + transformedAndSerialized, |
| 201 | + ), |
| 202 | + sourceMap: transformSourceMap(liquidProcessedContent.sourceMap, { |
| 203 | + emplacedResultOffset: resultFrontMatterOffset, |
| 204 | + emplacedSourceOffset: sourceFrontMatterOffset, |
| 205 | + }), |
| 206 | + } |
| 207 | + : emplaceSerializedFrontMatter( |
| 208 | + liquidProcessedContent as string, |
| 209 | + transformedAndSerialized, |
| 210 | + )) as unknown as C; |
| 211 | +} |
| 212 | + |
| 213 | +// both default and named exports for convenience |
| 214 | +export {liquidDocument, liquidSnippet}; |
| 215 | +export default liquidDocument; |
0 commit comments