Skip to content

Commit

Permalink
Merge pull request github#30746 from github/repo-sync
Browse files Browse the repository at this point in the history
Repo sync
  • Loading branch information
docs-bot authored Dec 18, 2023
2 parents 83929a3 + 5c6a733 commit efc2a9c
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/content-linter/lib/linting-rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { frontmatterSchema } from './frontmatter-schema.js'
import { codeAnnotations } from './code-annotations.js'
import { frontmatterLiquidSyntax, liquidSyntax } from './liquid-syntax.js'
import { liquidIfTags, liquidIfVersionTags } from './liquid-versioning.js'
import { raiReusableUsage } from './rai-reusable-usage.js'

const noDefaultAltText = markdownlintGitHub.find((elem) =>
elem.names.includes('no-default-alt-text'),
Expand Down Expand Up @@ -65,5 +66,6 @@ export const gitHubDocsMarkdownlint = {
liquidSyntax,
liquidIfTags,
liquidIfVersionTags,
raiReusableUsage,
],
}
58 changes: 58 additions & 0 deletions src/content-linter/lib/linting-rules/rai-reusable-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { addError } from 'markdownlint-rule-helpers'
import { TokenKind } from 'liquidjs'
import path from 'path'

import { getFrontmatter } from '../helpers/utils.js'
import { getLiquidTokens, getPositionData } from '../helpers/liquid-utils.js'

export const raiReusableUsage = {
names: ['GHD035', 'rai-reusable-usage'],
description:
'RAI articles and reusables can only reference reusable content in the data/reusables/rai directory',
tags: ['feature', 'rai'],
function: (params, onError) => {
if (!isFileRai(params)) return

const content = params.lines.join('\n')
const tokens = getLiquidTokens(content)
.filter((token) => token.kind === TokenKind.Tag)
.filter((token) => token.name === 'data' || token.name === 'indented_data_reference')
// It's ok to reference variables from rai content
.filter((token) => !token.args.startsWith('variables'))

for (const token of tokens) {
// if token is 'data foo.bar` or `indented_data_reference foo.bar depth=3`
// we only want the `foo.bar` part.
const dataDirectoryReference = token.args.split(/\s+/)[0]
if (dataDirectoryReference.startsWith('reusables.rai')) continue

const lines = params.lines
const { lineNumber, column, length } = getPositionData(token, lines)
addError(
onError,
lineNumber,
`RAI reusables and content articles can only reference reusables in the data/reusables/rai directory to ensure that changes to RAI content are reviewed by the legal-product team. The Liquid data reference {% ${token.content} %} needs to be moved to the data/reusables/rai directory.`,
token.content,
[column, length],
null, // No fix available
)
}
},
}

// Rai file content can be in either the data/reusables/rai directory
// or anywhere in the content directory
function isFileRai(params) {
// ROOT is set in the test environment to src/fixtures/fixtures otherwise
// it is set to the root of the project.
const ROOT = process.env.ROOT || '.'
const dataPath = path.join(ROOT, 'data/reusables')
const dataRai = path.join(dataPath, 'rai')

if (params.name.startsWith(dataPath)) {
return params.name.startsWith(dataRai)
}

const fm = getFrontmatter(params.frontMatterLines) || {}
return fm.type === 'rai'
}
5 changes: 5 additions & 0 deletions src/content-linter/style/github-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ const githubDocsConfig = {
severity: 'warning',
'partial-markdown-files': true,
},
'rai-reusable-usage': {
// GHD035
severity: 'error',
'partial-markdown-files': true,
},
}

export const githubDocsFrontmatterConfig = {
Expand Down
2 changes: 1 addition & 1 deletion src/content-linter/tests/unit/liquid-versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe(liquidIfVersionTags.names.join(' - '), () => {
const envVarValueBefore = process.env.ROOT

beforeAll(() => {
process.env.ROOT = path.join('src', 'fixtures', 'fixtures')
process.env.ROOT = 'src/fixtures/fixtures'
})

afterAll(() => {
Expand Down
101 changes: 101 additions & 0 deletions src/content-linter/tests/unit/rai-resuable-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { runRule } from '../../lib/init-test.js'
import { raiReusableUsage } from '../../lib/linting-rules/rai-reusable-usage.js'

describe(raiReusableUsage.names.join(' - '), () => {
const envVarValueBefore = process.env.ROOT

beforeAll(() => {
process.env.ROOT = 'src/fixtures/fixtures'
})

afterAll(() => {
process.env.ROOT = envVarValueBefore
})

test('a non-RAI content article referencing non-RAI data succeeds', async () => {
const markdown = [
'---',
'title: article',
'---',
'',
'{% data reusables.injectables.multiple_numbers %}',
].join('\n')
const result = await runRule(raiReusableUsage, {
strings: { markdown },
})
const errors = result.markdown
expect(errors.length).toBe(0)
})

test('an RAI content article referencing non-RAI data fails', async () => {
const markdown = [
'---',
'title: article',
'type: rai',
'---',
'',
'{% data reusables.injectables.multiple_numbers %}',
].join('\n')
const result = await runRule(raiReusableUsage, {
strings: { markdown },
})
const errors = result.markdown
expect(errors.length).toBe(1)
expect(errors[0].lineNumber).toBe(6)
expect(errors[0].errorRange).toEqual([1, 49])
})

test('an RAI content article referencing RAI data succeeds', async () => {
const markdown = [
'---',
'title: article',
'type: rai',
'---',
'',
'{% data reusables.rai.note %}',
].join('\n')
const result = await runRule(raiReusableUsage, {
strings: { markdown },
})
const errors = result.markdown
expect(errors.length).toBe(0)
})

test('a non-RAI data file referencing non-RAI data succeeds', async () => {
const TEST_FILE = 'src/fixtures/fixtures/data/reusables/nested_reusables/nested.md'
const result = await runRule(raiReusableUsage, {
files: [TEST_FILE],
})
const errors = result[TEST_FILE]
expect(errors.length).toBe(0)
})

test('an RAI data file referencing RAI data succeeds', async () => {
const TEST_FILE = 'src/fixtures/fixtures/data/reusables/rai/referencing_rai_data.md'
const result = await runRule(raiReusableUsage, {
files: [TEST_FILE],
})
const errors = result[TEST_FILE]
expect(errors.length).toBe(0)
})

test('an RAI data file referencing non-RAI data fails', async () => {
const TEST_FILE = 'src/fixtures/fixtures/data/reusables/rai/not_referencing_this_directory.md'
const result = await runRule(raiReusableUsage, {
files: [TEST_FILE],
})
const errors = result[TEST_FILE]
expect(errors.length).toBe(1)
expect(errors[0].lineNumber).toBe(3)
expect(errors[0].errorRange).toEqual([1, 41])
})

test('an RAI data file referencing data variables succeeds', async () => {
const TEST_FILE = 'src/fixtures/fixtures/data/reusables/rai/referencing_variable.md'
const result = await runRule(raiReusableUsage, {
files: [TEST_FILE],
})
const errors = result[TEST_FILE]
expect(errors.length).toBe(0)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This file contains reusable text and also references reusable text.

{% data reusables.policies.translation %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This is responsible AI content that is incorrectly referencing data in the non-rai directory.

{% data reusables.policies.translation %}
1 change: 1 addition & 0 deletions src/fixtures/fixtures/data/reusables/rai/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is responsible AI content.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This is an RAI data reusable referencing other RAI data reusables.

{% data reusables.rai.note %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Referencing data variables is ok.

{% data variables.product.name %}

0 comments on commit efc2a9c

Please sign in to comment.