-
Notifications
You must be signed in to change notification settings - Fork 67.1k
Expand file tree
/
Copy pathindented-data-reference.ts
More file actions
73 lines (59 loc) · 2.51 KB
/
indented-data-reference.ts
File metadata and controls
73 lines (59 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import assert from 'assert'
import { type TagToken, type Liquid } from 'liquidjs'
import { THROW_ON_EMPTY, IndentedDataReferenceError } from './error-handling'
import { getDataByLanguage } from '@/data-directory/lib/get-data'
import { createLogger } from '@/observability/logger'
const logger = createLogger(import.meta.url)
interface LiquidScope {
environments: {
currentLanguage: string
[key: string]: unknown
}
}
// This class supports a tag that expects two parameters, a data reference and `spaces=NUMBER`:
//
// {% indented_data_reference foo.bar spaces=NUMBER %}
// Example: {% indented_data_reference reusables.pages.wildcard-dns-warning spaces=3 %}
//
// This tag renders the given data reference with the specified number of spaces
// prepended to each line. This results in correct formatting when the data
// reference is used inside a block element (like a list or nested list) without
// affecting the formatting when the reference is used elsewhere via {{ site.data.foo.bar }}.
const IndentedDataReference = {
markup: '',
liquid: null as Liquid | null,
parse(tagToken: TagToken): void {
this.markup = tagToken.args.trim()
},
async render(scope: LiquidScope): Promise<string | undefined> {
// obfuscate first legit space, remove all other spaces, then restore legit space
// this way we can support spaces=NUMBER as well as spaces = NUMBER
const input = this.markup
.replace(/\s/, 'REALSPACE')
.replace(/\s/g, '')
.replace('REALSPACE', ' ')
const [dataReference, spaces] = input.split(' ')
// if no spaces are specified, default to 2
const numSpaces: string = spaces ? spaces.replace(/spaces=/, '') : '2'
assert(parseInt(numSpaces) || numSpaces === '0', '"spaces=NUMBER" must include a number')
// Get the referenced value from the context
const text: string | undefined = getDataByLanguage(
dataReference,
scope.environments.currentLanguage,
)
if (text === undefined) {
if (scope.environments.currentLanguage === 'en') {
const message = `Can't find the key 'indented_data_reference ${dataReference}' in the scope.`
if (THROW_ON_EMPTY) {
throw new IndentedDataReferenceError(message)
}
logger.warn(message)
}
return
}
// add spaces to each line
const renderedReferenceWithIndent: string = text.replace(/^/gm, ' '.repeat(parseInt(numSpaces)))
return this.liquid.parseAndRender(renderedReferenceWithIndent, scope.environments)
},
}
export default IndentedDataReference