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
13 changes: 8 additions & 5 deletions src/ghes-releases/scripts/remove-deprecated-frontmatter.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// Returns false when no changes were made to the frontmatter,
// true when changes were made.
export default function removeDeprecatedFrontmatter(
file,
frontmatterVersions,
releaseToDeprecate,
nextOldestRelease
) {
// skip files with no Enterprise Server versions frontmatter
if (!frontmatterVersions) return
if (!frontmatterVersions.ghes) return
if (!frontmatterVersions) return false
if (!frontmatterVersions.ghes) return false

const ghesRange = frontmatterVersions.ghes

// skip files with versions frontmatter that already applies to all enterprise-server releases
if (ghesRange === '*') return
if (ghesRange === '*') return false

// if the release to deprecate is 2.13, and the FM is either '>=2.13', '>2.13', or '>=2.14',
// we can safely change the FM to ghes: '*'
Expand All @@ -22,7 +24,7 @@ export default function removeDeprecatedFrontmatter(

if (appliesToAllSupportedGhesReleases) {
frontmatterVersions.ghes = '*'
return
return true
}

// if the release to deprecate is 2.13, and the FM is either '=2.13', '<2.13', '<=2.13', or '<2.14',
Expand All @@ -39,9 +41,10 @@ export default function removeDeprecatedFrontmatter(
console.log(
`Warning! ${file} has frontmatter versioning that will make it never appear when ${releaseToDeprecate} is deprecated. The article should probably be removed.`
)
return
return false
}

delete frontmatterVersions.ghes
return true
}
}
6 changes: 4 additions & 2 deletions src/ghes-releases/scripts/remove-liquid-statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ const tokenize = (str) => {
// src/ghes-releases/tests/remove-liquid-statements.js.
export default function removeLiquidStatements(content, release, nextOldestRelease, file) {
let newContent = content
let contentChanged = false

// Get an array of ifversion blocks with their content included.
const blocks = getLiquidConditionalsWithContent(newContent, 'ifversion')
if (!blocks.length) return newContent
if (!blocks.length) return { newContent, contentChanged }

// Decorate those blocks with more GHES versioning information.
const versionBlocks = getVersionBlocks(blocks)
Expand Down Expand Up @@ -233,6 +234,7 @@ export default function removeLiquidStatements(content, release, nextOldestRelea
// in the general content and return the updated general content.
versionBlocks.forEach((versionBlock) => {
if (versionBlock.action !== 'none') {
contentChanged = true
const newBlockContent = versionBlock.newContent.replaceAll(/\n\n\n+?/g, '\n\n')

newContent = newContent
Expand All @@ -246,7 +248,7 @@ export default function removeLiquidStatements(content, release, nextOldestRelea
}
})

return newContent
return { newContent, contentChanged }
}

// Hack to use a regex with lastIndexOf.
Expand Down
52 changes: 35 additions & 17 deletions src/ghes-releases/scripts/remove-version-markup.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,37 +60,55 @@ async function main() {
for (const file of allFiles) {
const oldContents = fs.readFileSync(file, 'utf8')
const { content, data } = frontmatter(oldContents)

let fileChanged = false
// update frontmatter versions prop
removeDeprecatedFrontmatter(file, data.versions, release, nextOldestRelease)
fileChanged ||= removeDeprecatedFrontmatter(file, data.versions, release, nextOldestRelease)

// update liquid statements in content and data
const newContent = removeLiquidStatements(content, release, nextOldestRelease, file)
const { newContent, contentChanged } = removeLiquidStatements(
content,
release,
nextOldestRelease,
file
)
fileChanged ||= contentChanged

// update liquid statements in content frontmatter (like intro and title)
for (const key in data) {
const value = data[key]
if (typeof value === 'string' && value.includes('{% ifversion')) {
const newValue = removeLiquidStatements(value, release, nextOldestRelease, file)
data[key] = newValue
const { newContent, contentChanged } = removeLiquidStatements(
value,
release,
nextOldestRelease,
file
)
fileChanged ||= contentChanged
data[key] = newContent
}
}

// make sure any intro fields that exist and are empty return an empty string, not null
if (typeof data.intro !== 'undefined' && !data.intro) {
data.intro = ''
}
// When stringifying frontmatter, the frontmatter is also formatted.
// This means that even if there were no Liquid versioning changes,
// the frontmatter may still be modified to modify line breaks or quotes.
// This an already difficult PR noisier to review. This prevents writing
// the file unless there are versioning changes made.
if (fileChanged) {
// make sure any intro fields that exist and are empty return an empty string, not null
if (typeof data.intro !== 'undefined' && !data.intro) {
data.intro = ''
}
// put it all back together
const newContents = frontmatter.stringify(newContent, data, { lineWidth: 10000 })

// put it all back together
const newContents = frontmatter.stringify(newContent, data, { lineWidth: 10000 })
// if the content file is now empty, remove it
if (newContents.replace(/\s/g, '').length === 0) {
fs.unlinkSync(file)
continue
}

// if the content file is now empty, remove it
if (newContents.replace(/\s/g, '').length === 0) {
fs.unlinkSync(file)
continue
fs.writeFileSync(file, newContents)
}

fs.writeFileSync(file, newContents)
}

console.log(`Removed GHES ${release} markup from content and data files! Review and run tests.`)
Expand Down
60 changes: 30 additions & 30 deletions src/ghes-releases/tests/remove-liquid-statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ function processFrontmatter(contents, file) {

describe('removing liquid statements only', () => {
test('removes liquid statements that specify "greater than version to deprecate"', async () => {
let contents = await fs.readFile(greaterThan, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(greaterThan, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(`{% ifversion ghes %}\n
Alpha\n\n{% endif %}`)
expect($('.example2').text().trim()).toBe(`{% ifversion fpt or ghes %}\n
Expand All @@ -65,9 +65,9 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes > 2.16 %}\n\nCharlie\n
{% else %}\n\nBravo\n\n{% endif %}`)
})
test('removes liquid statements that specify all known versions, including some nested conditionals"', async () => {
let contents = await fs.readFile(unnecessary, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(unnecessary, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(`Alpha`)
expect($('.example2').text().trim()).toBe(
`Alpha\n {% ifversion fpt or ghec %}\n Bravo\n {% endif %}`
Expand All @@ -84,9 +84,9 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes > 2.16 %}\n\nCharlie\n
})

test('removes liquid statements that specify "and greater than version to deprecate"', async () => {
let contents = await fs.readFile(andGreaterThan1, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(andGreaterThan1, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(
'{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% endif %}'
)
Expand All @@ -102,9 +102,9 @@ Alpha\n\n{% ifversion ghes > 2.16 %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCh
})

test('removes liquid statements that specify "and greater than version to deprecate" (alternate format)', async () => {
let contents = await fs.readFile(andGreaterThan2, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(andGreaterThan2, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('{% ifversion ghes < 2.16 %}\n\nAlpha\n\n{% endif %}')
expect($('.example2').text().trim()).toBe(`{% ifversion ghes < 2.16 %}\n\nAlpha\n\n{% else %}\n
Bravo\n\n{% endif %}`)
Expand All @@ -117,9 +117,9 @@ Alpha\n\n{% ifversion not fpt %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCharli
})

test('removes liquid statements that specify "not equals version to deprecate"', async () => {
let contents = await fs.readFile(notEquals, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(notEquals, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('{% ifversion ghes %}\n\nAlpha\n\n{% endif %}')
expect($('.example2').text().trim()).toBe('{% ifversion fpt or ghes %}\n\nAlpha\n\n{% endif %}')
expect($('.example3').text().trim()).toBe(`{% ifversion fpt %}\n
Expand All @@ -136,9 +136,9 @@ Alpha\n\n{% endif %}`)

describe('removing liquid statements and content', () => {
test('removes interior content and liquid statements that specify "equals version to deprecate"', async () => {
let contents = await fs.readFile(equals, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(equals, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('')
expect($('.example2').text().trim()).toBe('{% ifversion not fpt %}\n\nAlpha\n\n{% endif %}')
expect($('.example3').text().trim()).toBe(`{% ifversion fpt %}\n
Expand All @@ -152,9 +152,9 @@ Alpha\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
})

test('removes interior content and liquid statements that specify "less than next oldest than version to deprecate"', async () => {
let contents = await fs.readFile(lessThanNextOldest, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(lessThanNextOldest, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('Alpha')
expect($('.example2').text().trim()).toBe(
'Alpha\n\n{% ifversion fpt %}\n\nBravo\n\n{% endif %}'
Expand Down Expand Up @@ -193,19 +193,19 @@ describe('updating frontmatter', () => {

describe('whitespace', () => {
test('does not add newlines when whitespace control is used', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text()).toBe('\n{% ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example2').text()).toBe('\n{%- ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example3').text()).toBe('\n{% ifversion fpt or ghes %}\n Alpha\n{%- endif %}\n')
expect($('.example4').text()).toBe('\n{%- ifversion fpt or ghes %}\n Alpha\n{%- endif %}\n')
})

test('does not add newlines when no newlines are present', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example5').text()).toBe('\n{% ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example6').text()).toBe(
'\n Alpha\n{% ifversion fpt or ghes %}\n Bravo\n{% endif %}\n Charlie\n'
Expand All @@ -214,9 +214,9 @@ describe('whitespace', () => {
})

test('only remove newlines when tag starts at beginning of line', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example8').text()).toBe('\nAlpha\nBravo\n')
expect($('.example9').text()).toBe('\nAlpha\nBravo\n')
expect($('.example10').text()).toBe('\nPre\nBravo\n')
Expand Down