Skip to content

Commit 988e68f

Browse files
author
Peter Bengtsson
authored
JIT data (#32140)
1 parent 2ff4a43 commit 988e68f

24 files changed

Lines changed: 212 additions & 174 deletions

components/context/MainContext.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type DataT = {
4040
version_was_deprecated: string
4141
version_will_be_deprecated: string
4242
deprecation_details: string
43-
isOldestReleaseDeprecated: boolean
43+
isOldestReleaseDeprecated?: boolean
4444
}
4545
policies: {
4646
translation: string
@@ -130,12 +130,27 @@ export const getMainContext = async (req: any, res: any): Promise<MainContextT>
130130
error: req.context.error ? req.context.error.toString() : '',
131131
data: {
132132
ui: req.context.site.data.ui,
133+
133134
reusables: {
134-
enterprise_deprecation: req.context.site.data.reusables.enterprise_deprecation,
135-
policies: req.context.site.data.reusables.policies,
135+
enterprise_deprecation: {
136+
version_was_deprecated: req.context.getDottedData(
137+
'reusables.enterprise_deprecation.version_was_deprecated'
138+
),
139+
version_will_be_deprecated: req.context.getDottedData(
140+
'reusables.enterprise_deprecation.version_will_be_deprecated'
141+
),
142+
deprecation_details: req.context.getDottedData(
143+
'reusables.enterprise_deprecation.deprecation_details'
144+
),
145+
},
146+
policies: {
147+
translation: req.context.getDottedData('reusables.policies.translation'),
148+
},
136149
},
137150
variables: {
138-
release_candidate: req.context.site.data.variables.release_candidate,
151+
release_candidate: {
152+
version: req.context.getDottedData('variables.release_candidate.version') || null,
153+
},
139154
},
140155
},
141156
currentCategory: req.context.currentCategory || '',

content/get-started/quickstart/github-glossary.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ versions:
1313
---
1414
{% for glossary in glossaries %}
1515
### {{ glossary.term }}
16-
{{ glossary.description}}
16+
{{ glossary.description }}
1717
---
1818
{% endfor %}
1919

lib/get-applicable-versions.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import path from 'path'
21
import { reduce, sortBy } from 'lodash-es'
32
import { allVersions } from './all-versions.js'
43
import versionSatisfiesRange from './version-satisfies-range.js'
54
import checkIfNextVersionOnly from './check-if-next-version-only.js'
6-
import dataDirectory from './data-directory.js'
7-
import encodeBracketedParentheses from './encode-bracketed-parentheses.js'
8-
9-
const featuresDir = path.join('data', 'features')
5+
import { getDeepDataByLanguage } from './get-data.js'
106

117
let featureData = null
128

@@ -24,10 +20,7 @@ function getApplicableVersions(frontmatterVersions, filepath) {
2420
}
2521

2622
if (!featureData) {
27-
featureData = dataDirectory(featuresDir, {
28-
preprocess: (dataString) => encodeBracketedParentheses(dataString.trimEnd()),
29-
ignorePatterns: [/README\.md$/],
30-
})
23+
featureData = getDeepDataByLanguage('features', 'en')
3124
}
3225

3326
// Check for frontmatter that includes a feature name, like:

lib/get-data.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { merge, get } from 'lodash-es'
77

88
import languages from './languages.js'
99

10+
// If you run `export DEBUG_JIT_DATA_READS=true` in your terminal,
11+
// next time it will mention every file it reads from disk.
12+
const DEBUG_JIT_DATA_READS = Boolean(JSON.parse(process.env.DEBUG_JIT_DATA_READS || 'false'))
13+
1014
// This is a list of files that we should always immediately fall back to
1115
// English for.
1216
// Having this is safer than trying to wrangle the translations to NOT
@@ -237,7 +241,7 @@ const getMarkdownContent = memoize((root, relPath, englishRoot) => {
237241

238242
const getFileContent = (root, relPath, englishRoot) => {
239243
const filePath = root ? path.join(root, relPath) : relPath
240-
if (process.env.NODE_ENV === 'development') console.log('READ', filePath)
244+
if (DEBUG_JIT_DATA_READS) console.log('READ', filePath)
241245
try {
242246
return fs.readFileSync(filePath, 'utf-8')
243247
} catch (err) {

lib/get-english-headings.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { fromMarkdown } from 'mdast-util-from-markdown'
22
import { toString } from 'mdast-util-to-string'
33
import { visit } from 'unist-util-visit'
4+
45
import findPage from './find-page.js'
6+
import { getDataByLanguage } from './get-data.js'
57

68
// for any translated page, first get corresponding English markdown
79
// then get the headings on both the translated and English pageMap
@@ -11,7 +13,7 @@ export default function getEnglishHeadings(page, context) {
1113
// generated programatically.
1214
if (page.relativePath.endsWith('/github-glossary.md')) {
1315
// Return an object of `{ localized-term: english-slug }`
14-
const languageGlossary = context.site.data.glossaries.external
16+
const languageGlossary = getDataByLanguage('glossaries.external', 'en')
1517
return languageGlossary.reduce((prev, curr) => {
1618
prev[curr.term] = curr.slug
1719
return prev

lib/liquid-tags/data.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { TokenizationError } from 'liquidjs'
2-
import matter from 'gray-matter'
32

43
import { THROW_ON_EMPTY, DataReferenceError } from './error-handling.js'
4+
import { getDataByLanguage } from '../get-data.js'
55

66
const Syntax = /([a-z0-9/\\_.\-[\]]+)/i
77
const SyntaxHelp = "Syntax Error in 'data' - Valid syntax: data [path]"
@@ -16,8 +16,8 @@ export default {
1616
},
1717

1818
async render(scope) {
19-
let value = await this.liquid.evalValue(`site.data.${this.path}`, scope)
20-
if (typeof value !== 'string') {
19+
const text = getDataByLanguage(this.path, scope.environments.currentLanguage)
20+
if (text === undefined) {
2121
const message = `Can't find the key 'site.data.${this.path}' in the scope.`
2222
if (THROW_ON_EMPTY) {
2323
throw new DataReferenceError(message)
@@ -26,12 +26,6 @@ export default {
2626
return
2727
}
2828

29-
// Drop any frontmatter since reusable Markdown files aren't currently
30-
// expected to use frontmatter. This is useful since our current translation
31-
// process adds YAML frontmatter properties to any Markdown file that gets
32-
// translated and we don't want to render that information.
33-
;({ content: value } = matter(value))
34-
35-
return this.liquid.parseAndRender(value, scope.environments)
29+
return this.liquid.parseAndRender(text, scope.environments)
3630
},
3731
}

lib/liquid-tags/indented-data-reference.js

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import assert from 'assert'
22

33
import { THROW_ON_EMPTY, IndentedDataReferenceError } from './error-handling.js'
4+
import { getDataByLanguage } from '../get-data.js'
45

56
// This class supports a tag that expects two parameters, a data reference and `spaces=NUMBER`:
67
//
@@ -33,20 +34,8 @@ export default {
3334
assert(parseInt(numSpaces) || numSpaces === '0', '"spaces=NUMBER" must include a number')
3435

3536
// Get the referenced value from the context
36-
const value = await this.liquid.evalValue(`site.data.${dataReference}`, scope)
37-
38-
// If value is falsy it can be because we completely failed to look
39-
// it up. But it can also be literally an empty string.
40-
// For example, the reusable could be entirely something like this:
41-
//
42-
// {% if some condition %}The meat{% endif %}
43-
//
44-
// Then it's working as expected. But if the reference is wrong, e.g.
45-
//
46-
// {% indented_data_reference reusables.foo.tyypu spaces=3 %}
47-
//
48-
// Or if the file simple doesn't exist, you get an undefined for the value.
49-
if (typeof value !== 'string' && !value) {
37+
const text = getDataByLanguage(dataReference, scope.environments.currentLanguage)
38+
if (text === undefined) {
5039
const message = `Can't find the key 'site.data.${dataReference}' in the scope.`
5140
if (THROW_ON_EMPTY) {
5241
throw new IndentedDataReferenceError(message)
@@ -56,7 +45,7 @@ export default {
5645
}
5746

5847
// add spaces to each line
59-
const renderedReferenceWithIndent = value.replace(/^/gm, ' '.repeat(numSpaces))
48+
const renderedReferenceWithIndent = text.replace(/^/gm, ' '.repeat(numSpaces))
6049

6150
return this.liquid.parseAndRender(renderedReferenceWithIndent, scope.environments)
6251
},

lib/page-data.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import path from 'path'
2+
23
import languages from './languages.js'
34
import { allVersions } from './all-versions.js'
45
import createTree, { getBasePath } from './create-tree.js'
5-
import loadSiteData from './site-data.js'
66
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
77
import Page from './page.js'
88

@@ -60,8 +60,7 @@ export async function loadUnversionedTree(languagesOnly = null) {
6060
*
6161
* Order of languages and versions doesn't matter, but order of child page arrays DOES matter (for navigation).
6262
*/
63-
export async function loadSiteTree(unversionedTree, siteData) {
64-
const site = siteData || loadSiteData()
63+
export async function loadSiteTree(unversionedTree) {
6564
const rawTree = Object.assign({}, unversionedTree || (await loadUnversionedTree()))
6665
const siteTree = {}
6766

@@ -76,8 +75,7 @@ export async function loadSiteTree(unversionedTree, siteData) {
7675
treePerVersion[version] = await versionPages(
7776
Object.assign({}, rawTree[langCode]),
7877
version,
79-
langCode,
80-
site
78+
langCode
8179
)
8280
})
8381
)
@@ -89,7 +87,7 @@ export async function loadSiteTree(unversionedTree, siteData) {
8987
return siteTree
9088
}
9189

92-
export async function versionPages(obj, version, langCode, site) {
90+
export async function versionPages(obj, version, langCode) {
9391
// Add a versioned href as a convenience for use in layouts.
9492
obj.href = obj.page.permalinks.find(
9593
(pl) =>
@@ -103,7 +101,7 @@ export async function versionPages(obj, version, langCode, site) {
103101
// Drop child pages that do not apply to the current version
104102
.filter((childPage) => childPage.page.applicableVersions.includes(version))
105103
// Version the child pages recursively.
106-
.map((childPage) => versionPages(Object.assign({}, childPage), version, langCode, site))
104+
.map((childPage) => versionPages(Object.assign({}, childPage), version, langCode))
107105
)
108106

109107
obj.childPages = [...versionedChildPages]

lib/process-learning-tracks.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import renderContent from './render-content/index.js'
22
import getLinkData from './get-link-data.js'
33
import getApplicableVersions from './get-applicable-versions.js'
4+
import { getDataByLanguage } from './get-data.js'
45

56
const renderOpts = { textOnly: true, encodeEntities: true }
67

@@ -23,11 +24,20 @@ export default async function processLearningTracks(rawLearningTracks, context)
2324
if (!renderedTrackName) continue
2425

2526
// Find the data for the current product and track name.
26-
const trackDataForProduct = context.site.data['learning-tracks'][context.currentProduct]
27-
if (!trackDataForProduct) {
28-
throw new Error(`No learning track data for product "${context.currentProduct}".`)
27+
28+
if (context.currentProduct.includes('.')) {
29+
throw new Error(`currentProduct can not contain a . (${context.currentProduct})`)
30+
}
31+
if (renderedTrackName.includes('.')) {
32+
throw new Error(`renderedTrackName can not contain a . (${renderedTrackName})`)
2933
}
30-
const track = trackDataForProduct[renderedTrackName]
34+
35+
// Note: this will use the translated learning tracks and automatically
36+
// fall back to English if they don't exist on disk in the translation.
37+
const track = getDataByLanguage(
38+
`learning-tracks.${context.currentProduct}.${renderedTrackName}`,
39+
context.currentLanguage
40+
)
3141
if (!track) {
3242
throw new Error(`No learning track called '${renderedTrackName}'.`)
3343
}

lib/warm-server.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import statsd from './statsd.js'
22
import { loadUnversionedTree, loadSiteTree, loadPages, loadPageMap } from './page-data.js'
33
import loadRedirects from './redirects/precompile.js'
4-
import loadSiteData from './site-data.js'
54

65
// Instrument these functions so that
76
// it's wrapped in a timer that reports to Datadog
@@ -11,7 +10,6 @@ const dog = {
1110
loadPages: statsd.asyncTimer(loadPages, 'load_pages'),
1211
loadPageMap: statsd.asyncTimer(loadPageMap, 'load_page_map'),
1312
loadRedirects: statsd.asyncTimer(loadRedirects, 'load_redirects'),
14-
loadSiteData: statsd.timer(loadSiteData, 'load_site_data'),
1513
}
1614

1715
// For multiple-triggered Promise sharing
@@ -25,8 +23,7 @@ async function warmServer() {
2523
}
2624

2725
const unversionedTree = await dog.loadUnversionedTree()
28-
const site = dog.loadSiteData()
29-
const siteTree = await dog.loadSiteTree(unversionedTree, site)
26+
const siteTree = await dog.loadSiteTree(unversionedTree)
3027
const pageList = await dog.loadPages(unversionedTree)
3128
const pageMap = await dog.loadPageMap(pageList)
3229
const redirects = await dog.loadRedirects(pageList)
@@ -43,7 +40,6 @@ async function warmServer() {
4340

4441
return {
4542
pages: pageMap,
46-
site,
4743
redirects,
4844
unversionedTree,
4945
siteTree,

0 commit comments

Comments
 (0)