Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"check-github-github-links": "node src/links/scripts/check-github-github-links.js",
"close-dangling-prs": "tsx src/workflows/close-dangling-prs.ts",
"content-changes-table-comment": "tsx src/workflows/content-changes-table-comment.ts",
"convert-liquid-markdown-tables": "tsx src/tools/scripts/convert-liquid-markdown-tables.ts",
"copy-fixture-data": "node src/tests/scripts/copy-fixture-data.js",
"count-translation-corruptions": "tsx src/languages/scripts/count-translation-corruptions.ts",
"debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES=en nodemon --inspect src/frame/server.ts",
Expand All @@ -42,6 +43,7 @@
"lint": "eslint '**/*.{js,mjs,ts,tsx}'",
"lint-content": "node src/content-linter/scripts/lint-content.js",
"lint-translation": "vitest src/content-linter/tests/lint-files.js",
"liquid-markdown-tables": "tsx src/tools/scripts/liquid-markdown-tables/index.ts",
"generate-code-scanning-query-list": "tsx src/code-scanning/scripts/generate-code-scanning-query-list.ts",
"generate-content-linter-docs": "tsx src/content-linter/scripts/generate-docs.ts",
"move-content": "node src/content-render/scripts/move-content.js",
Expand Down
2 changes: 1 addition & 1 deletion src/fixtures/tests/playwright-rendering.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ test.describe('translations', () => {

test('switch to Japanese from English using widget on article', async ({ page }) => {
await page.goto('/get-started/start-your-journey/hello-world')
await expect(page).toHaveURL('/en/get-started/start-your-journey/hello-world')
await page.getByRole('button', { name: 'Select language: current language is English' }).click()
await page.getByRole('menuitemradio', { name: '日本語' }).click()
await expect(page).toHaveURL('/ja/get-started/start-your-journey/hello-world')
Expand All @@ -631,7 +632,6 @@ test.describe('translations', () => {
// If you go, with the Japanese cookie, to the English page directly,
// it will offer a link to the Japanese URL in a banner.
await page.goto('/en/get-started/start-your-journey/hello-world')
await page.getByRole('link', { name: 'Japanese' }).click()
await expect(page).toHaveURL('/ja/get-started/start-your-journey/hello-world')
})
})
Expand Down
21 changes: 21 additions & 0 deletions src/frame/components/ClientSideLanguageRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect } from 'react'
import { useRouter } from 'next/router'

import { useLanguages } from 'src/languages/components/LanguagesContext'
import Cookies from 'src/frame/components/lib/cookies'
import { USER_LANGUAGE_COOKIE_NAME } from 'src/frame/lib/constants.js'

export function ClientSideLanguageRedirect() {
const { locale, asPath, replace } = useRouter()
const { languages } = useLanguages()
const availableLanguageKeys = new Set(Object.keys(languages))

useEffect(() => {
const cookieValue = Cookies.get(USER_LANGUAGE_COOKIE_NAME)
if (cookieValue && cookieValue !== locale && availableLanguageKeys.has(cookieValue)) {
const newPath = `/${cookieValue}${asPath}`
replace(newPath, undefined, { locale: cookieValue })
}
}, [locale, availableLanguageKeys, asPath])
return null
}
2 changes: 2 additions & 0 deletions src/frame/components/DefaultLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useMainContext } from 'src/frame/components/context/MainContext'
import { useTranslation } from 'src/languages/components/useTranslation'
import { Breadcrumbs } from 'src/frame/components/page-header/Breadcrumbs'
import { useLanguages } from 'src/languages/components/LanguagesContext'
import { ClientSideLanguageRedirect } from './ClientSideLanguageRedirect'
import { DomainNameEditProvider } from 'src/links/components/useEditableDomainContext'

const MINIMAL_RENDER = Boolean(JSON.parse(process.env.MINIMAL_RENDER || 'false'))
Expand Down Expand Up @@ -124,6 +125,7 @@ export const DefaultLayout = (props: Props) => {
Skip to main content
</a>
<Header />
<ClientSideLanguageRedirect />
<div className="d-lg-flex">
{isHomepageVersion ? null : <SidebarNav />}
{/* Need to set an explicit height for sticky elements since we also
Expand Down
43 changes: 43 additions & 0 deletions src/tools/scripts/liquid-markdown-tables/convert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* See docstring in index.ts for more information about how to use this script.
*/
import fs from 'fs'

import chalk from 'chalk'

import { processFile } from './lib'

type Options = {
dryRun: boolean
}

export async function convert(files: string[], options: Options) {
if (!files.length) {
console.error(chalk.red('No files specified'))
process.exit(1)
}

for (const file of files) {
const info = fs.statSync(file)
if (info.isDirectory()) {
console.error(chalk.red('Directories are currently not supported. Only files.'))
process.exit(1)
}
}

for (const file of files) {
console.log(chalk.grey(`Processing file ${chalk.bold(file)}`))
const content = fs.readFileSync(file, 'utf8')
const newContent = await processFile(content)
if (content !== newContent) {
if (options.dryRun) {
console.log(chalk.green('Would have written changes to disk'))
} else {
console.log(chalk.green(`Updating ${chalk.bold(file)}`))
fs.writeFileSync(file, newContent, 'utf-8')
}
} else {
console.log(chalk.yellow('No changes needed'))
}
}
}
45 changes: 45 additions & 0 deletions src/tools/scripts/liquid-markdown-tables/find.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fs from 'fs'

import chalk from 'chalk'
import walk from 'walk-sync'

import { processFile } from './lib'

type Options = {
filter?: string[]
}

export async function find(options: Options) {
const files = [
...walk('data', {
includeBasePath: true,
globs: ['**/*.md'],
ignore: ['**/README.md'],
}),
...walk('content', {
includeBasePath: true,
globs: ['**/*.md'],
ignore: ['**/README.md'],
}),
].filter((filePath) => {
if (options.filter && options.filter.length) {
return options.filter.some((filter) => filePath.includes(filter))
}
return true
})
console.log(chalk.grey(`${chalk.bold(files.length.toLocaleString())} files to search.`))

const found: string[] = []
for (const filePath of files) {
const content = fs.readFileSync(filePath, 'utf8')
const newContent = await processFile(content)
if (content !== newContent) {
console.log(chalk.green(filePath))
found.push(filePath)
}
}
console.log('\n')
console.log(
chalk.grey(`Found ${chalk.bold(found.length.toLocaleString())} files that can be converted.`),
)
}
69 changes: 69 additions & 0 deletions src/tools/scripts/liquid-markdown-tables/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* This script helps you rewrite Markdown files that might contain
* tables with Liquid `ifversion` tags the old/wrong way.
* For example:
*
* | Header | Header 2 |
* |--------|----------|
* | bla | bla |{% ifversion dependency-review-action-licenses %}
* | foo | foo |{% endif %}{% ifversion dependency-review-action-fail-on-scopes %}
* | bar | bar |{% endif %}
* | baz | baz |
* {%- ifversion dependency-review-action-licenses %}
* | qux | qux |{% endif %}
*
* Will become:
*
* | Header | Header 2 |
* |--------|----------|
* | bla | bla |
* | {% ifversion dependency-review-action-licenses %} |
* | foo | foo |
* | {% endif %} |
* | {% ifversion dependency-review-action-fail-on-scopes %} |
* | bar | bar |
* | {% endif %} |
* | baz | baz |
* | {% ifversion dependency-review-action-licenses %} |
* | qux | qux |
* | {% endif %} |
*
* Run the script like this:
*
* npm run liquid-markdown-tables -- convert content/path/to/article.md
* git diff
*
* To *find* files that you *can* convert, use:
*
* npm run liquid-markdown-tables -- find
* # or
* npm run liquid-markdown-tables -- find --filter content/mydocset
*
* This will print out paths to files that most likely contain the old/wrong Liquid `ifversion` tags.
*
*/

import { program } from 'commander'

import { convert } from './convert'
import { find } from './find'

program
.name('liquid-markdown-tables')
.description('CLI for finding and converting Liquid in Markdown tables')

program
.command('convert')
.description('Clean up Markdown tables that use Liquid `ifversion` tags the old/wrong way')
.option('--dry-run', "Don't actually write changes to disk", false)
// .arguments('[files-or-directories...]', '')
.arguments('[files...]')
.action(convert)

program
.command('find')
.description('Find Markdown tables that use Liquid `ifversion` tags the old/wrong way')
.option('--filter <filter...>', 'Filter by file path')
.action(find)

program.parse(process.argv)
68 changes: 68 additions & 0 deletions src/tools/scripts/liquid-markdown-tables/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// E.g. `{%- ifversion dependency-review-action-licenses %}\n`
const ifVersionRegex = /^{%-?\s*ifversion\s+([\w- ]+)\s*-?%}\n/
const ifVersionEndRegex = /\|({%-?\s*ifversion\s+([\w- ]+)\s*-?%})\n/
// E.g. `... |{% endif %}{% ifversion dependency-review-action-fail-on-scopes %}\n`
const endifIfVersionRegex = /\|({%-?\s*endif\s*%})({%-?\sifversion\s+([\w- ]+)\s*-?%})\n/
const endifRegex = /\|({%-?\s*endif\s*%})\n/
const endifAloneRegex = /^({%-?\s*endif\s*%})\n/

// Split a string by newlines while keeping the newlines
function splitAndKeepNewlines(str: string) {
const lines = str.split(/(\r\n|\r|\n)/)
const result: string[] = []
for (let i = 0; i < lines.length; i++) {
if (lines[i].match(/(\r\n|\r|\n)/)) {
result[result.length - 1] += lines[i]
} else {
result.push(lines[i])
}
}
return result
}

export async function processFile(content: string) {
let inTable = false
let inFrontmatter = false
let inMarkdown = false
const newLines: string[] = []
for (let line of splitAndKeepNewlines(content)) {
if (line === '---\n') {
if (!inFrontmatter) {
inFrontmatter = true
} else {
inFrontmatter = false
inMarkdown = true
}
}
if (inMarkdown) {
if (line.startsWith('|') && line.endsWith('|\n')) {
inTable = true
} else if (inTable && line === '\n') {
inTable = false
}
if (inTable) {
// E.g. `{%- ifversion dependency-review-action-licenses %}\n`
if (ifVersionRegex.test(line)) {
const better = line.replace('{%-', '{%').replace('-%}', '%}').trim()
line = `| ${better} |\n`
} else if (ifVersionEndRegex.test(line)) {
line = line
.replace(ifVersionEndRegex, '|\n| $1 |\n')
.replace('{%-', '{%')
.replace('-%}', '%}')
} else if (endifIfVersionRegex.test(line)) {
line = line
.replace(endifIfVersionRegex, '|\n| $1 |\n| $2 |\n')
.replace('{%-', '{%')
.replace('-%}', '%}')
} else if (endifRegex.test(line)) {
line = line.replace(endifRegex, '|\n| $1 |\n')
} else if (endifAloneRegex.test(line)) {
line = line.replace(endifAloneRegex, '| $1 |\n').replace('{%-', '{%')
}
}
}
newLines.push(line)
}
return newLines.join('')
}