1
0
mirror of synced 2026-01-08 03:01:54 -05:00

Merge branch 'main' into repo-sync

This commit is contained in:
Octomerger Bot
2021-07-23 05:33:08 +10:00
committed by GitHub
50 changed files with 284 additions and 237 deletions

View File

@@ -18,7 +18,8 @@ export const DefaultLayout = (props: Props) => {
<Head>
{error === '404' ? (
<title>{t('oops')}</title>
) : (!isHomepageVersion && page.fullTitle) || (currentPathWithoutLanguage.includes('enterprise-server') && page.fullTitle) ? (
) : (!isHomepageVersion && page.fullTitle) ||
(currentPathWithoutLanguage.includes('enterprise-server') && page.fullTitle) ? (
<title>{page.fullTitle}</title>
) : null}

View File

@@ -54,12 +54,7 @@ export const ArticlePage = () => {
</div>
)}
{intro && (
<div
className="lead-mktg"
dangerouslySetInnerHTML={{ __html: intro }}
/>
)}
{intro && <div className="lead-mktg" dangerouslySetInnerHTML={{ __html: intro }} />}
{permissions && (
<div

View File

@@ -6,9 +6,9 @@ export type TocItem = {
title: string
intro?: string
childTocItems?: Array<{
fullPath: string;
title: string;
}>
fullPath: string
title: string
}>
}
export type FeaturedLink = {
title: string

View File

@@ -13,7 +13,7 @@ export const GuideCard = ({ guide }: Props) => {
className="Box color-shadow-medium height-full d-block hover-shadow-large no-underline color-text-primary p-5"
href={guide.href}
>
<h2 dangerouslySetInnerHTML={{__html: guide.title}} />
<h2 dangerouslySetInnerHTML={{ __html: guide.title }} />
<p className="mt-2 mb-4 color-text-tertiary">{guide.intro}</p>
<footer className="d-flex">

View File

@@ -24,22 +24,26 @@ export const TableOfContents = (props: Props) => {
return variant === 'compact' ? (
<li key={href} className="f4 my-1">
<Link href={href}>{title}</Link>
<ul className={cx(variant === 'compact' ? 'list-style-circle pl-5 my-3' : 'list-style-none')}>
{(childTocItems || []).map((childItem) => {
if (!childItem) {
return null
}
return (
<li key={childItem.fullPath} className="f4 mt-1">
<Link
href={childItem.fullPath}
className="Bump-link--hover no-underline py-1 color-border-primary"
>
{childItem.title}
</Link>
</li>
)
})}
<ul
className={cx(
variant === 'compact' ? 'list-style-circle pl-5 my-3' : 'list-style-none'
)}
>
{(childTocItems || []).map((childItem) => {
if (!childItem) {
return null
}
return (
<li key={childItem.fullPath} className="f4 mt-1">
<Link
href={childItem.fullPath}
className="Bump-link--hover no-underline py-1 color-border-primary"
>
{childItem.title}
</Link>
</li>
)
})}
</ul>
</li>
) : (

View File

@@ -67,4 +67,5 @@ plans.forEach((planObj) => {
})
})
export default allVersions
export const allVersionKeys = Object.keys(allVersions)
export { allVersions }

View File

@@ -2,16 +2,24 @@ import fs from 'fs'
import path from 'path'
import parse from './read-frontmatter.js'
import semver from 'semver'
import xAllVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
const layoutNames = ['default', 'dev-toc', 'graphql-explorer', 'product-landing', 'product-sublanding', 'release-notes', false]
const layoutNames = [
'default',
'dev-toc',
'graphql-explorer',
'product-landing',
'product-sublanding',
'release-notes',
false,
]
const semverValidRange = semver.validRange
const semverRange = {
type: 'string',
conform: semverValidRange,
message: 'Must be a valid SemVer range',
}
const versionObjs = Object.values(xAllVersions)
const versionObjs = Object.values(allVersions)
const guideTypes = ['overview', 'quick_start', 'tutorial', 'how_to', 'reference']
const featureVersions = fs
.readdirSync(path.posix.join(process.cwd(), 'data/features'))

View File

@@ -1,7 +1,7 @@
import { fileURLToPath } from 'url'
import path from 'path'
import { reduce, sortBy } from 'lodash-es'
import allVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
import versionSatisfiesRange from './version-satisfies-range.js'
import checkIfNextVersionOnly from './check-if-next-version-only.js'
import dataDirectory from './data-directory.js'

View File

@@ -1,5 +1,5 @@
import xAllVersions from '../lib/all-versions.js'
const nonEnterpriseDefaultVersion = Object.values(xAllVersions).find(
import { allVersions } from '../lib/all-versions.js'
const nonEnterpriseDefaultVersion = Object.values(allVersions).find(
(version) => version.nonEnterpriseDefault
).version

View File

@@ -2,10 +2,10 @@ import path from 'path'
import { supported, latest } from './enterprise-server-releases.js'
import patterns from './patterns.js'
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
import xAllVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
const latestNewVersion = `enterprise-server@${latest}`
const oldVersions = ['dotcom'].concat(supported)
const newVersions = Object.keys(xAllVersions)
const newVersions = Object.keys(allVersions)
// Utility functions for converting between old version paths and new version paths.
// See lib/path-utils.js for utility functions based on new paths.

View File

@@ -1,13 +1,13 @@
import { fileURLToPath } from 'url'
import path from 'path'
import languages from './languages.js'
import xAllVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
import createTree from './create-tree.js'
import renderContent from './render-content/index.js'
import loadSiteData from './site-data.js'
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const versions = Object.keys(xAllVersions)
const versions = Object.keys(allVersions)
const enterpriseServerVersions = versions.filter((v) => v.startsWith('enterprise-server@'))
const renderOpts = { textOnly: true, encodeEntities: true }

View File

@@ -3,7 +3,7 @@ import path from 'path'
import patterns from './patterns.js'
import { latest } from './enterprise-server-releases.js'
import { productIds } from './all-products.js'
import allVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
const supportedVersions = new Set(Object.keys(allVersions))

View File

@@ -1,7 +1,7 @@
import assert from 'assert'
import path from 'path'
import patterns from './patterns.js'
import allVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
import removeFPTFromPath from './remove-fpt-from-path.js'
class Permalink {

View File

@@ -11,9 +11,9 @@ import {
} from '../path-utils.js'
import patterns from '../patterns.js'
import versionSatisfiesRange from '../version-satisfies-range.js'
import xAllVersions from '../all-versions.js'
import { allVersions } from '../all-versions.js'
import nonEnterpriseDefaultVersion from '../non-enterprise-default-version.js'
const currentlySupportedVersions = Object.keys(xAllVersions)
const currentlySupportedVersions = Object.keys(allVersions)
// This function takes a current path, applies what we know about historically
// supported paths, and returns an array of ALL possible associated old

View File

@@ -1,6 +1,6 @@
import path from 'path'
import patterns from '../patterns.js'
import allVersions from '../all-versions.js'
import { allVersions } from '../all-versions.js'
import getOldPathsFromPermalink from './get-old-paths-from-permalink.js'
import { getVersionStringFromPath } from '../path-utils.js'
import { getNewVersionedPath } from '../old-versions-utils.js'

View File

@@ -1,7 +1,7 @@
import visit from 'unist-util-visit'
import fs from 'fs'
import { legacyAssetVersions } from '../../enterprise-server-releases.js'
import allVersions from '../../all-versions.js'
import { allVersions } from '../../all-versions.js'
const matcher = (node) =>
node.type === 'element' &&

View File

@@ -5,7 +5,7 @@ import { getNewVersionedPath } from '../../old-versions-utils.js'
import patterns from '../../patterns.js'
import { deprecated, latest } from '../../enterprise-server-releases.js'
import nonEnterpriseDefaultVersion from '../../non-enterprise-default-version.js'
import allVersions from '../../all-versions.js'
import { allVersions } from '../../all-versions.js'
import removeFPTFromPath from '../../remove-fpt-from-path.js'
import readJsonFile from '../../read-json-file.js'
const supportedVersions = Object.keys(allVersions)

View File

@@ -2,7 +2,7 @@ import { fileURLToPath } from 'url'
import path from 'path'
import fs from 'fs'
import { chain, get, groupBy } from 'lodash-es'
import allVersions from '../all-versions.js'
import { allVersions, allVersionKeys } from '../all-versions.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const schemasPath = path.join(__dirname, 'static/decorated')
export const operations = {}
@@ -11,7 +11,6 @@ fs.readdirSync(schemasPath).forEach((filename) => {
const value = JSON.parse(fs.readFileSync(path.join(schemasPath, filename)))
operations[key] = value
})
const allVersionKeys = Object.keys(allVersions)
let allCategories = []
allVersionKeys.forEach((currentVersion) => {

View File

@@ -5,7 +5,7 @@ import { getNewVersionedPath } from './old-versions-utils.js'
import patterns from './patterns.js'
import { deprecated, latest } from './enterprise-server-releases.js'
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
import allVersions from './all-versions.js'
import { allVersions } from './all-versions.js'
import removeFPTFromPath from './remove-fpt-from-path.js'
import readJsonFile from './read-json-file.js'
const supportedVersions = Object.keys(allVersions)

View File

@@ -1,4 +1,4 @@
import allVersions from '../all-versions.js'
import { allVersions } from '../all-versions.js'
export default Object.fromEntries(
Object.entries(allVersions).map(([versionStr, versionObject]) => [

View File

@@ -1,6 +1,6 @@
import languages from '../lib/languages.js'
import enterpriseServerReleases from '../lib/enterprise-server-releases.js'
import allVersions from '../lib/all-versions.js'
import { allVersions } from '../lib/all-versions.js'
import { productMap } from '../lib/all-products.js'
import xPathUtils from '../lib/path-utils.js'
import productNames from '../lib/product-names.js'

View File

@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import readJsonFile from '../../lib/read-json-file.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
const previews = readJsonFile('./lib/graphql/static/previews.json')
const upcomingChanges = readJsonFile('./lib/graphql/static/upcoming-changes.json')
const changelog = readJsonFile('./lib/graphql/static/changelog.json')

View File

@@ -1,7 +1,7 @@
import { defaults } from 'lodash-es'
import webhookPayloads from '../../lib/webhooks/index.js'
import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
export default function webhooksContext(req, res, next) {
const currentVersionObj = allVersions[req.context.currentVersion]

View File

@@ -6,9 +6,7 @@ import frontmatter from '../../lib/read-frontmatter.js'
import { loadPages, loadPageMap } from '../../lib/page-data.js'
import patterns from '../../lib/patterns.js'
import loadRedirects from '../../lib/redirects/precompile.js'
import xAllVersions from '../../lib/all-versions.js'
const allVersions = Object.keys(xAllVersions)
import { allVersionKeys } from '../../lib/all-versions.js'
// get all content and data files
const files = ['content', 'data']
@@ -58,7 +56,7 @@ async function main() {
// remove language code segment
.replace(patterns.getLanguageCode, '')
// remove version segment
.replace(new RegExp(`/(${allVersions.join('|')})`), '')
.replace(new RegExp(`/(${allVersionKeys.join('|')})`), '')
// re-add the fragment after removing any fragment added via the redirect
// otherwise /v3/git/refs/#create-a-reference will become /rest/reference/git#refs#create-a-reference

View File

@@ -5,10 +5,10 @@ import path from 'path'
import { escapeRegExp } from 'lodash-es'
import { Tokenizer } from 'liquidjs'
import frontmatter from '../../lib/read-frontmatter.js'
import xAllVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import { deprecated, oldestSupported } from '../../lib/enterprise-server-releases.js'
const allVersions = Object.values(xAllVersions)
const allVersionKeys = Object.values(allVersions)
const dryRun = ['-d', '--dry-run'].includes(process.argv[2])
const walkFiles = (pathToWalk, ext) => {
@@ -62,7 +62,7 @@ async function main() {
.replace(/>=?2\.19/, '*')
// Find the relevant version from the master list so we can access the short name.
const versionObj = allVersions.find(
const versionObj = allVersionKeys.find(
(version) => version.plan === plan || version.shortName === plan
)
if (!versionObj) {
@@ -186,7 +186,7 @@ function getLiquidReplacements(content, file) {
const [plan, release] = opParts[2].slice(1, -1).split('@')
// Find the relevant version from the master list so we can access the short name.
const versionObj = allVersions.find((version) => version.plan === plan)
const versionObj = allVersionKeys.find((version) => version.plan === plan)
if (!versionObj) {
console.error(`Couldn't find a version for ${plan} in "${token}" in ${file}`)

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env node
import fs from 'fs'
import fs from 'fs'
import path from 'path'
import program from 'commander'
import readJsonFile from '../../lib/read-json-file.js'
@@ -19,7 +19,10 @@ program
.description(
'Remove developer redirects for deprecated versions. The redirects for deprecated versions live in the respective directory in the github/help-docs-archived-enterprise-versions repository.'
)
.option('-r, --release <NUMBER>', 'Enterprise Server release number. Example: 2.19. Default: latest deprecated release number.')
.option(
'-r, --release <NUMBER>',
'Enterprise Server release number. Example: 2.19. Default: latest deprecated release number.'
)
.parse(process.argv)
// Default to latest deprecated release
@@ -27,12 +30,15 @@ const release = program.opts().release || deprecated[0]
const supportedRedirects = {}
Object.keys(developerRedirects).forEach(elem => {
const includesVersion = elem.includes(`enterprise/${release}`)
|| elem.includes(`enterprise-server@${release}`)
if ( includesVersion ) return
Object.keys(developerRedirects).forEach((elem) => {
const includesVersion =
elem.includes(`enterprise/${release}`) || elem.includes(`enterprise-server@${release}`)
if (includesVersion) return
supportedRedirects[elem] = developerRedirects[elem]
})
fs.writeFileSync(path.join(process.cwd(), DEVELOPER_REDIRECTS_FILEPATH), JSON.stringify(supportedRedirects, null, 2))
fs.writeFileSync(
path.join(process.cwd(), DEVELOPER_REDIRECTS_FILEPATH),
JSON.stringify(supportedRedirects, null, 2)
)

View File

@@ -2,7 +2,7 @@
import fs from 'fs'
import path from 'path'
import xRimraf from 'rimraf'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
const rimraf = xRimraf.sync

View File

@@ -4,7 +4,7 @@ import program from 'commander'
import frontmatter from '../../lib/read-frontmatter.js'
import removeLiquidStatements from '../../script/helpers/remove-liquid-statements.js'
import removeDeprecatedFrontmatter from '../../script/helpers/remove-deprecated-frontmatter.js'
import { all, getNextReleaseNumber} from '../../lib/enterprise-server-releases.js'
import { all, getNextReleaseNumber } from '../../lib/enterprise-server-releases.js'
import walkFiles from '../helpers/walk-files.js'
// [start-readme]
@@ -34,7 +34,9 @@ if (!release) {
}
if (!all.includes(release)) {
console.log(`You specified ${release}! Please specify a supported or deprecated release number from lib/enterprise-server-releases.js`)
console.log(
`You specified ${release}! Please specify a supported or deprecated release number from lib/enterprise-server-releases.js`
)
process.exit(1)
}
@@ -46,12 +48,12 @@ console.log(`Next oldest version: ${nextOldestRelease}\n`)
// gather content and data files
const contentFiles = walkFiles('content', '.md', { includeEarlyAccess: true })
const reusables = walkFiles('data/reusables', '.md', { includeEarlyAccess: true })
const variables = walkFiles('data/variables', '.yml', { includeEarlyAccess: true })
const variables = walkFiles('data/variables', '.yml', { includeEarlyAccess: true })
const allFiles = contentFiles.concat(reusables, variables)
main()
async function main () {
async function main() {
for (const file of allFiles) {
const oldContents = fs.readFileSync(file, 'utf8')
const { content, data } = frontmatter(oldContents)
@@ -84,7 +86,7 @@ async function main () {
fs.unlinkSync(file)
continue
}
fs.writeFileSync(file, newContents)
}

View File

@@ -3,7 +3,7 @@ import fs from 'fs'
import path from 'path'
import program from 'commander'
import xMkdirp from 'mkdirp'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
const mkdirp = xMkdirp.sync
const graphqlStaticDir = path.join(process.cwd(), 'lib/graphql/static')

View File

@@ -2,7 +2,7 @@
import fs from 'fs'
import path from 'path'
import program from 'commander'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import getOperations from '../rest/utils/get-operations.js'
const dereferencedDir = 'lib/rest/static/dereferenced'

View File

@@ -3,7 +3,7 @@ import fs from 'fs'
import xMkdirp from 'mkdirp'
import path from 'path'
import program from 'commander'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
const mkdirp = xMkdirp.sync
const payloadsDir = 'lib/webhooks/static'

View File

@@ -3,7 +3,7 @@ import fs from 'fs'
import path from 'path'
import program from 'commander'
import yaml from 'js-yaml'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
const releaseCandidateFile = 'data/variables/release_candidate.yml'
const releaseCandidateYaml = path.join(process.cwd(), releaseCandidateFile)

View File

@@ -5,7 +5,7 @@ import xMkdirp from 'mkdirp'
import yaml from 'js-yaml'
import { execSync } from 'child_process'
import { getContents, listMatchingRefs } from '../helpers/git-utils.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import processPreviews from './utils/process-previews.js'
import processUpcomingChanges from './utils/process-upcoming-changes.js'
import processSchemas from './utils/process-schemas.js'

View File

@@ -9,18 +9,18 @@ const tokenize = (str) => {
}
// Return an array of just the conditional strings.
function getLiquidConditionals (str, tagNames) {
function getLiquidConditionals(str, tagNames) {
if (!tagNames) throw new Error(`Must provide a tag name!`)
tagNames = Array.isArray(tagNames) ? tagNames : [tagNames]
return tokenize(str)
.filter(token => tagNames.includes(token.name))
.map(token => token.args)
.filter((token) => tagNames.includes(token.name))
.map((token) => token.args)
}
// Return an array of objects, where the `conditional` prop contains the conditional string,
// and the `text` prop contains the contents between the start tag and the end tag.
function getLiquidConditionalsWithContent (str, tagName) {
function getLiquidConditionalsWithContent(str, tagName) {
if (!tagName) throw new Error(`Must provide a tag name!`)
if (typeof tagName !== 'string') throw new Error(`Must provide a single tag name as a string!`)
@@ -31,33 +31,35 @@ function getLiquidConditionalsWithContent (str, tagName) {
// Get the raw tokens, which includes versions, data tags, etc.,
// Also this captures start tags, content, and end tags as _individual_ tokens, but we want to group them.
const tokens = tokenize(str)
.map(token => {
return {
conditional: token.name,
text: token.getText(),
position: token.getPosition()
}
})
const tokens = tokenize(str).map((token) => {
return {
conditional: token.name,
text: token.getText(),
position: token.getPosition(),
}
})
// Parse the raw tokens and group them, so that start tags, content, and end tags are
// Parse the raw tokens and group them, so that start tags, content, and end tags are
// all considered to be part of the same block, and return that block.
const grouped = groupTokens(tokens, tagName, endTagName)
// Run recursively so we can also capture nested conditionals.
const nestedConditionals = grouped.flatMap(group => {
const nestedConditionals = grouped.flatMap((group) => {
// Remove the start tag and the end tag so we are left with nested tags, if any.
const nested = group.text
.replace(group.conditional, '')
.split('').reverse().join('')
.split('')
.reverse()
.join('')
.replace(new RegExp(`{%-? ${endTagName} -?%}`), '')
.split('').reverse().join('')
.split('')
.reverse()
.join('')
const nestedGroups = getLiquidConditionalsWithContent(nested, tagName)
// Remove the start tag but NOT the end tag, so we are left with elsif tags and their endifs, if any.
const elsifs = group.text
.replace(group.conditional, '')
const elsifs = group.text.replace(group.conditional, '')
const elsifGroups = getLiquidConditionalsWithContent(elsifs, 'elsif')
@@ -67,21 +69,27 @@ function getLiquidConditionalsWithContent (str, tagName) {
return nestedConditionals
}
function groupTokens (tokens, tagName, endTagName, newArray = []) {
const startIndex = tokens.findIndex(token => token.conditional === tagName)
function groupTokens(tokens, tagName, endTagName, newArray = []) {
const startIndex = tokens.findIndex((token) => token.conditional === tagName)
// The end tag name is currently in a separate token, but we want to group it with the start tag and content.
const endIndex = tokens.findIndex(token => token.conditional === endTagName)
// Once all tags are grouped and removed from `tokens`, this findIndex will not find anything,
const endIndex = tokens.findIndex((token) => token.conditional === endTagName)
// Once all tags are grouped and removed from `tokens`, this findIndex will not find anything,
// so we can return the grouped result at this point.
if (startIndex === -1) return newArray
const condBlockArr = tokens.slice(startIndex, endIndex + 1)
if (!condBlockArr.length) return newArray
const [ newBlockArr, newEndIndex ] = handleNestedTags(condBlockArr, endIndex, tagName, endTagName, tokens)
const [newBlockArr, newEndIndex] = handleNestedTags(
condBlockArr,
endIndex,
tagName,
endTagName,
tokens
)
// Combine the text of the groups so it's all together.
const condBlock = newBlockArr.map(t => t.text).join('')
const condBlock = newBlockArr.map((t) => t.text).join('')
const startToken = tokens[startIndex]
const endToken = tokens[endIndex]
@@ -90,7 +98,7 @@ function groupTokens (tokens, tagName, endTagName, newArray = []) {
text: condBlock,
endIfText: endToken.text,
positionStart: startToken.position,
positionEnd: endToken.position
positionEnd: endToken.position,
})
// Remove the already-processed tokens.
@@ -101,16 +109,16 @@ function groupTokens (tokens, tagName, endTagName, newArray = []) {
return groupTokens(tokens, tagName, endTagName, newArray)
}
function handleNestedTags (condBlockArr, endIndex, tagName, endTagName, tokens) {
function handleNestedTags(condBlockArr, endIndex, tagName, endTagName, tokens) {
// Return early if there are no nested tags to be handled.
if (!hasUnhandledNestedTags(condBlockArr, tagName, endTagName)) {
return [ condBlockArr, endIndex ]
return [condBlockArr, endIndex]
}
// If a nested conditional is found, we have to peek forward to the next endif tag after the one we found.
const tempEndIndex = tokens
.slice(endIndex + 1)
.findIndex(token => token.conditional === endTagName)
.findIndex((token) => token.conditional === endTagName)
// Include the content up to the next endif tag.
const additionalTokens = tokens.slice(endIndex + 1, endIndex + tempEndIndex + 2)
@@ -121,25 +129,22 @@ function handleNestedTags (condBlockArr, endIndex, tagName, endTagName, tokens)
return handleNestedTags(newBlockArray, newEndIndex, tagName, endTagName, tokens)
}
function hasUnhandledNestedTags (condBlockArr, tagName, endTagName) {
const startTags = condBlockArr.filter(t => {
function hasUnhandledNestedTags(condBlockArr, tagName, endTagName) {
const startTags = condBlockArr.filter((t) => {
// some blocks that start with ifversion still have if tags nested inside
return tagName === 'ifversion'
? t.conditional === tagName || t.conditional === 'if'
return tagName === 'ifversion'
? t.conditional === tagName || t.conditional === 'if'
: t.conditional === tagName
})
const endTags = condBlockArr.filter(t => t.conditional === endTagName)
const endTags = condBlockArr.filter((t) => t.conditional === endTagName)
const hasMoreStartTagsThanEndTags = startTags.length > endTags.length
// Do not consider multiple elsifs an unhandled nesting. We only care about nested ifs.
const startTagsAreElsifs = startTags.every(t => t.conditional === 'elsif')
const startTagsAreElsifs = startTags.every((t) => t.conditional === 'elsif')
const hasUnhandledNestedTags = hasMoreStartTagsThanEndTags && !startTagsAreElsifs
return hasUnhandledNestedTags
}
export {
getLiquidConditionals,
getLiquidConditionalsWithContent
}
export { getLiquidConditionals, getLiquidConditionalsWithContent }

View File

@@ -2,10 +2,10 @@ import supportedOperators from '../../lib/liquid-tags/ifversion-supported-operat
// Turn an array of Liquid conditional objects that results from ./get-liquid-conditionals.js into a more
// detailed array of objects that includes GHES versioning information.
export default function getVersionBlocks (rawBlocks) {
export default function getVersionBlocks(rawBlocks) {
const versionBlocks = []
rawBlocks.forEach(block => {
rawBlocks.forEach((block) => {
const condKeyword = block.conditional.includes('ifversion') ? 'ifversion' : 'elsif'
const condOnly = block.conditional.replace(/{%-? /, '').replace(/ -?%}/, '')
const condWithLiquid = block.conditional
@@ -14,17 +14,17 @@ export default function getVersionBlocks (rawBlocks) {
const condArgs = condOnly
.replace('ifversion ', '')
.replace('elsif ', '')
// Obfuscate with an arbitrary character we don't want to preserve, so we can split on that character.
// TODO: If preserving `or` and `and` turns out NOT to be important, we can split on those words instead.
// Obfuscate with an arbitrary character we don't want to preserve, so we can split on that character.
// TODO: If preserving `or` and `and` turns out NOT to be important, we can split on those words instead.
.replaceAll(/ (or|and) /g, ' ~$1 ')
.split('~')
.map(arg => arg.trim())
.map((arg) => arg.trim())
// E.g., [ 'ghes', '<', '2.21' ]
const ranges = condArgs
.map(arg => arg.split(' '))
.filter(args => args.some(arg => supportedOperators.includes(arg)))
.map(args => args.filter(arg => !(arg === 'or' || arg === 'and' | arg === '')))
.map((arg) => arg.split(' '))
.filter((args) => args.some((arg) => supportedOperators.includes(arg)))
.map((args) => args.filter((arg) => !(arg === 'or' || (arg === 'and') | (arg === ''))))
// Remove the start tag and the end tag so we are left with the inner text.
// We don't need to do anything with this inner text other than check for nested conds.
@@ -33,8 +33,7 @@ export default function getVersionBlocks (rawBlocks) {
innerText = innerText.slice(0, indexOfLastEndif)
// Remove any nested conditional content so we can check the top-level only.
const topLevelContent = innerText
.replace(/{%-? ifversion[\S\s]+?{%-? endif -?%}/g, '')
const topLevelContent = innerText.replace(/{%-? ifversion[\S\s]+?{%-? endif -?%}/g, '')
versionBlocks.push({
condKeyword,
@@ -47,9 +46,9 @@ export default function getVersionBlocks (rawBlocks) {
hasElse: /{%-? else -?%}/.test(topLevelContent),
endIfText: block.endIfText,
startTagColumn1: block.positionStart[1] === 1,
endTagColumn1: block.positionEnd[1] === 1
endTagColumn1: block.positionEnd[1] === 1,
})
})
return versionBlocks
}

View File

@@ -1,4 +1,9 @@
export default function removeDeprecatedFrontmatter (file, frontmatterVersions, releaseToDeprecate, nextOldestRelease) {
export default function removeDeprecatedFrontmatter(
file,
frontmatterVersions,
releaseToDeprecate,
nextOldestRelease
) {
// skip files with no Enterprise Server versions frontmatter
if (!frontmatterVersions) return
if (!frontmatterVersions.ghes) return
@@ -10,11 +15,10 @@ export default function removeDeprecatedFrontmatter (file, frontmatterVersions,
// 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: '*'
const appliesToAllSupportedGhesReleases = (
const appliesToAllSupportedGhesReleases =
ghesRange === `>=${releaseToDeprecate}` ||
ghesRange === `>${releaseToDeprecate}` ||
ghesRange === `>=${nextOldestRelease}`
)
if (appliesToAllSupportedGhesReleases) {
frontmatterVersions.ghes = '*'
@@ -23,17 +27,18 @@ export default function removeDeprecatedFrontmatter (file, frontmatterVersions,
// if the release to deprecate is 2.13, and the FM is either '=2.13', '<2.13', '<=2.13', or '<2.14',
// delete (aka deprecate) the ghes frontmatter property.
const appliesToNoSupportedGhesReleases = (
const appliesToNoSupportedGhesReleases =
ghesRange === `=${releaseToDeprecate}` ||
ghesRange === `<${releaseToDeprecate}` ||
ghesRange === `<=${releaseToDeprecate}` ||
ghesRange === `<${nextOldestRelease}`
)
if (appliesToNoSupportedGhesReleases) {
if (appliesToNoSupportedGhesReleases) {
// Throw a warning if there are no other frontmatter versions specified.
if (Object.keys(frontmatterVersions).length === 1) {
console.log(`Warning! ${file} has frontmatter versioning that will make it never appear when ${releaseToDeprecate} is deprecated. The article should probably be removed.`)
console.log(
`Warning! ${file} has frontmatter versioning that will make it never appear when ${releaseToDeprecate} is deprecated. The article should probably be removed.`
)
return
}

View File

@@ -1,7 +1,7 @@
import { getLiquidConditionalsWithContent } from './get-liquid-conditionals.js'
import getVersionBlocks from './get-version-blocks.js'
import allVersions from '../../lib/all-versions.js'
const supportedShortVersions = Object.values(allVersions).map(v => v.shortName)
import { allVersions } from '../../lib/all-versions.js'
const supportedShortVersions = Object.values(allVersions).map((v) => v.shortName)
const updateRangeKeepGhes = 'updateRangeKeepGhes'
const updateRangeRemoveGhes = 'updateRangeRemoveGhes'
const removeRangeAndContent = 'removeRangeAndContent'
@@ -9,7 +9,7 @@ const removeRangeAndContent = 'removeRangeAndContent'
// This module is used by script/enterprise-server-deprecations/remove-version-markup.js to remove
// and update Liquid conditionals when a GHES release is being deprecated. It is also used by
// tests/content/remove-liquid-statements.js.
export default function removeLiquidStatements (content, release, nextOldestRelease, file) {
export default function removeLiquidStatements(content, release, nextOldestRelease, file) {
let newContent = content
// Get an array of ifversion blocks with their content included.
@@ -23,10 +23,11 @@ export default function removeLiquidStatements (content, release, nextOldestRele
for (const versionBlock of versionBlocks) {
const actionMap = {}
versionBlock.isGhesOnly = versionBlock.condArgs.every(arg => arg.includes('ghes'))
versionBlock.isGhesOnly = versionBlock.condArgs.every((arg) => arg.includes('ghes'))
versionBlock.hasSingleRange = versionBlock.ranges.length === 1
versionBlock.andGhesRanges = versionBlock.condArgs.filter(arg => arg.includes('and ghes'))
const isSafeToRemoveContent = versionBlock.isGhesOnly && (versionBlock.hasSingleRange || versionBlock.andGhesRanges.length)
versionBlock.andGhesRanges = versionBlock.condArgs.filter((arg) => arg.includes('and ghes'))
const isSafeToRemoveContent =
versionBlock.isGhesOnly && (versionBlock.hasSingleRange || versionBlock.andGhesRanges.length)
for (const rangeArgs of versionBlock.ranges) {
const rangeOperator = rangeArgs[1]
@@ -42,7 +43,8 @@ export default function removeLiquidStatements (content, release, nextOldestRele
// Remove Liquid and content in these scenarios, IF AND ONLY IF it's safe to remove content.
// For example, when there is no other versioning in the conditional.
const lessThanNextOldestVersion = rangeOperator === '<' && (releaseNumber === nextOldestRelease || releaseNumber === release)
const lessThanNextOldestVersion =
rangeOperator === '<' && (releaseNumber === nextOldestRelease || releaseNumber === release)
const equalsVersionToDeprecate = rangeOperator === '=' && releaseNumber === release
let action
@@ -60,18 +62,17 @@ export default function removeLiquidStatements (content, release, nextOldestRele
}
if (action) {
actionMap[action] = versionBlock.condArgs.find(arg => arg.endsWith(rangeArgs.join(' ')))
actionMap[action] = versionBlock.condArgs.find((arg) => arg.endsWith(rangeArgs.join(' ')))
}
}
versionBlock.action = Object.keys(actionMap).length ? actionMap : 'none'
}
// Create the new content and add it to each block.
versionBlocks
.filter(versionBlock => versionBlock.action !== 'none')
.forEach(versionBlock => {
.filter((versionBlock) => versionBlock.action !== 'none')
.forEach((versionBlock) => {
const indexOfLastEndif = lastIndexOfRegex(versionBlock.content, /{%-? endif -?%}/g)
// ----- REMOVE RANGE AND CONTENT -----
@@ -84,25 +85,28 @@ export default function removeLiquidStatements (content, release, nextOldestRele
// doesn't start at the beginning of a new line, the content before
// the ifversion tag will be concatenated to the content after the
// else condition on a single line.
const replaceRegex = versionBlock.startTagColumn1
? new RegExp(`${versionBlock.condWithLiquid}[\\S\\s]+?{%-? else -?%}\n?`)
: new RegExp(`${versionBlock.condWithLiquid}[\\S\\s]+?{%-? else -?%}`)
const replaceRegex = versionBlock.startTagColumn1
? new RegExp(`${versionBlock.condWithLiquid}[\\S\\s]+?{%-? else -?%}\n?`)
: new RegExp(`${versionBlock.condWithLiquid}[\\S\\s]+?{%-? else -?%}`)
versionBlock.newContent = versionBlock.content
.slice(0, indexOfLastEndif)
.replace(replaceRegex, '')
if (versionBlock.endTagColumn1 && versionBlock.newContent.endsWith('\n')) versionBlock.newContent = versionBlock.newContent.slice(0, -1)
if (versionBlock.endTagColumn1 && versionBlock.newContent.endsWith('\n'))
versionBlock.newContent = versionBlock.newContent.slice(0, -1)
}
// If the block has an elsif, remove the content up to the elsif, and change the elsif to an if (or leave it
// an elsif this this block is itself an elsif), leaving the content inside the elsif block as is. The elsif
// If the block has an elsif, remove the content up to the elsif, and change the elsif to an if (or leave it
// an elsif this this block is itself an elsif), leaving the content inside the elsif block as is. The elsif
// condition is evaluated separately so we don't need to worry about evaluating it here.
if (versionBlock.hasElsif) {
const replaceRegex = new RegExp(`${versionBlock.condWithLiquid}[\\S\\s]+?({%-?) elsif`)
versionBlock.newContent = versionBlock.content
.replace(replaceRegex, `$1 ${versionBlock.condKeyword}`)
versionBlock.newContent = versionBlock.content.replace(
replaceRegex,
`$1 ${versionBlock.condKeyword}`
)
}
// For all other scenarios, remove the Liquid and the content.
@@ -110,7 +114,7 @@ export default function removeLiquidStatements (content, release, nextOldestRele
versionBlock.newContent = ''
}
}
// ----- UPDATE RANGE AND REMOVE `GHES` -----
if (versionBlock.action.updateRangeRemoveGhes) {
// Make the replacement and get the new conditional.
@@ -119,8 +123,10 @@ export default function removeLiquidStatements (content, release, nextOldestRele
.replace(/\s\s+/, ' ')
// Update the conditional.
versionBlock.newContent = versionBlock.content
.replace(versionBlock.condWithLiquid, newCondWithLiquid)
versionBlock.newContent = versionBlock.content.replace(
versionBlock.condWithLiquid,
newCondWithLiquid
)
}
// ----- UPDATE RANGE AND KEEP `GHES` -----
@@ -135,11 +141,15 @@ export default function removeLiquidStatements (content, release, nextOldestRele
// If the new conditional contains all the currently supported versions, no conditional
// is actually needed, and it can be removed. Any `else` statements and their content should
// also be removed.
const containsAllSupportedVersions = supportedShortVersions.every(v => newCondWithLiquid.includes(v))
const containsAllSupportedVersions = supportedShortVersions.every((v) =>
newCondWithLiquid.includes(v)
)
if (!containsAllSupportedVersions) {
versionBlock.newContent = versionBlock.content
.replace(versionBlock.condWithLiquid, newCondWithLiquid)
versionBlock.newContent = versionBlock.content.replace(
versionBlock.condWithLiquid,
newCondWithLiquid
)
}
if (containsAllSupportedVersions) {
@@ -150,36 +160,36 @@ export default function removeLiquidStatements (content, release, nextOldestRele
if (!versionBlock.hasElse && !versionBlock.hasElsif) {
const indexOfLastEndif = lastIndexOfRegex(versionBlock.content, /{%-? endif -?%}/g)
versionBlock.newContent = versionBlock.newContent
.slice(0, indexOfLastEndif)
versionBlock.newContent = versionBlock.newContent.slice(0, indexOfLastEndif)
if (versionBlock.endTagColumn1 && versionBlock.newContent.endsWith('\n')) versionBlock.newContent = versionBlock.newContent.slice(0, -1)
if (versionBlock.endTagColumn1 && versionBlock.newContent.endsWith('\n'))
versionBlock.newContent = versionBlock.newContent.slice(0, -1)
}
// If start tag is on it's own line, remove line ending (\\n?)
// and remove white space (//s*) after line ending to
// preserve indentation of next line
const removeStartTagRegex = versionBlock.startTagColumn1
? new RegExp(`${versionBlock.condWithLiquid}\\n?\\s*`)
: new RegExp(`${versionBlock.condWithLiquid}`)
// and remove white space (//s*) after line ending to
// preserve indentation of next line
const removeStartTagRegex = versionBlock.startTagColumn1
? new RegExp(`${versionBlock.condWithLiquid}\\n?\\s*`)
: new RegExp(`${versionBlock.condWithLiquid}`)
// For ALL scenarios, remove the start tag.
versionBlock.newContent = versionBlock.newContent
.replace(removeStartTagRegex, '')
versionBlock.newContent = versionBlock.newContent.replace(removeStartTagRegex, '')
// If the block has an elsif, change the elsif to an if (or leave it an elsif this this block is itself an elsif),
// If the block has an elsif, change the elsif to an if (or leave it an elsif this this block is itself an elsif),
// leaving the content inside the elsif block as is. Also leave the endif in this scenario.
if (versionBlock.hasElsif) {
versionBlock.newContent = versionBlock.newContent
.replace(/({%-) elsif/, `$1 ${versionBlock.condKeyword}`)
versionBlock.newContent = versionBlock.newContent.replace(
/({%-) elsif/,
`$1 ${versionBlock.condKeyword}`
)
}
// If the block has an else, remove the else, its content, and the endif.
if (versionBlock.hasElse) {
const replaceRegex = /{%-? else -?%}[\S\s]+?{%-? endif -?%}\n?/
versionBlock.newContent = versionBlock.newContent
.replace(replaceRegex, '')
versionBlock.newContent = versionBlock.newContent.replace(replaceRegex, '')
}
}
}
@@ -187,30 +197,29 @@ export default function removeLiquidStatements (content, release, nextOldestRele
// Now that we have the old and new content attached to each block, make the replacement
// in the general content and return the updated general content.
versionBlocks
.forEach(versionBlock => {
if (versionBlock.action !== 'none') {
const newBlockContent = versionBlock.newContent.replaceAll(/\n\n\n+?/g, '\n\n')
versionBlocks.forEach((versionBlock) => {
if (versionBlock.action !== 'none') {
const newBlockContent = versionBlock.newContent.replaceAll(/\n\n\n+?/g, '\n\n')
newContent = newContent
.replaceAll(versionBlock.content, newBlockContent)
.replaceAll(/({%-? ifversion |{%-? elsif )(and|or) /g, '$1') // clean up stray and/ors :/
.replaceAll(/\n\n\n+?/g, '\n\n')
if (file && file.includes('/data/')) {
newContent = newContent.trim()
}
newContent = newContent
.replaceAll(versionBlock.content, newBlockContent)
.replaceAll(/({%-? ifversion |{%-? elsif )(and|or) /g, '$1') // clean up stray and/ors :/
.replaceAll(/\n\n\n+?/g, '\n\n')
if (file && file.includes('/data/')) {
newContent = newContent.trim()
}
})
}
})
return newContent
}
// Hack to use a regex with lastIndexOf.
// Inspired by https://stackoverflow.com/a/21420210
function lastIndexOfRegex (str, regex, fromIndex) {
function lastIndexOfRegex(str, regex, fromIndex) {
const myStr = fromIndex ? str.substring(0, fromIndex) : str
const match = myStr.match(regex)
return match ? myStr.lastIndexOf(match[match.length - 1]) : -1
}
}

View File

@@ -8,7 +8,7 @@ import chalk from 'chalk'
import languages from '../../lib/languages.js'
import buildRecords from './build-records.js'
import findIndexablePages from './find-indexable-pages.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import { namePrefix } from '../../lib/search/config.js'
import getRemoteIndexNames from './algolia-get-remote-index-names.js'
import AlgoliaIndex from './algolia-search-index.js'

View File

@@ -9,14 +9,12 @@ import { loadPages, loadPageMap } from '../lib/page-data.js'
import loadSiteData from '../lib/site-data.js'
import loadRedirects from '../lib/redirects/precompile.js'
import { getPathWithoutLanguage, getPathWithoutVersion } from '../lib/path-utils.js'
import xAllVersions from '../lib/all-versions.js'
import { allVersionKeys } from '../lib/all-versions.js'
import frontmatter from '../lib/read-frontmatter.js'
import renderContent from '../lib/render-content/index.js'
import patterns from '../lib/patterns.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const allVersions = Object.keys(xAllVersions)
const walkFiles = (pathToWalk) => {
return walk(path.posix.join(__dirname, '..', pathToWalk), {
includeBasePath: true,
@@ -120,7 +118,7 @@ async function main() {
let foundPage, fragmentMatch, versionMatch
// Run through all supported versions...
for (const version of allVersions) {
for (const version of allVersionKeys) {
context.currentVersion = version
// Render the link for each version using the renderContent pipeline, which includes the rewrite-local-links plugin.
const $ = await renderContent(oldMarkdownLink, context, { cheerioObject: true })

View File

@@ -249,10 +249,13 @@ describe('platform specific content', () => {
})
describe('tool specific content', () => {
const pageWithSingleSwitcher = 'http://localhost:4001/en/actions/managing-workflow-runs/manually-running-a-workflow'
const pageWithoutSwitcher = 'http://localhost:4001/en/billing/managing-billing-for-github-sponsors/about-billing-for-github-sponsors'
const pageWithMultipleSwitcher = 'http://localhost:4001/en/issues/trying-out-the-new-projects-experience/using-the-api-to-manage-projects'
const pageWithSingleSwitcher =
'http://localhost:4001/en/actions/managing-workflow-runs/manually-running-a-workflow'
const pageWithoutSwitcher =
'http://localhost:4001/en/billing/managing-billing-for-github-sponsors/about-billing-for-github-sponsors'
const pageWithMultipleSwitcher =
'http://localhost:4001/en/issues/trying-out-the-new-projects-experience/using-the-api-to-manage-projects'
it('should have a tool switcher if a tool switcher is included', async () => {
await page.goto(pageWithSingleSwitcher)
const nav = await page.$$('nav#tool-switcher')
@@ -287,14 +290,14 @@ describe('tool specific content', () => {
it('should use cli if no defaultTool is specified and if webui is not one of the tools', async () => {
await page.goto(pageWithMultipleSwitcher)
const selectedToolElement = await page.waitForSelector('a.tool-switcher.selected')
const selectedTool = await page.evaluate(el => el.textContent, selectedToolElement)
const selectedTool = await page.evaluate((el) => el.textContent, selectedToolElement)
expect(selectedTool).toBe('GitHub CLI')
})
it('should use webui if no defaultTool is specified and if webui is one of the tools', async () => {
await page.goto(pageWithSingleSwitcher)
const selectedToolElement = await page.waitForSelector('a.tool-switcher.selected')
const selectedTool = await page.evaluate(el => el.textContent, selectedToolElement)
const selectedTool = await page.evaluate((el) => el.textContent, selectedToolElement)
expect(selectedTool).toBe('GitHub.com')
})
@@ -302,7 +305,7 @@ describe('tool specific content', () => {
// With no user data, the selected tool is GitHub.com
await page.goto(pageWithSingleSwitcher)
let selectedToolElement = await page.waitForSelector('a.tool-switcher.selected')
let selectedTool = await page.evaluate(el => el.textContent, selectedToolElement)
let selectedTool = await page.evaluate((el) => el.textContent, selectedToolElement)
expect(selectedTool).toBe('GitHub.com')
await page.click(`.tool-switcher[data-tool="cli"]`)
@@ -310,7 +313,7 @@ describe('tool specific content', () => {
// Revisiting the page after CLI is selected results in CLI as the selected tool
await page.goto(pageWithSingleSwitcher)
selectedToolElement = await page.waitForSelector('a.tool-switcher.selected')
selectedTool = await page.evaluate(el => el.textContent, selectedToolElement)
selectedTool = await page.evaluate((el) => el.textContent, selectedToolElement)
expect(selectedTool).toBe('GitHub CLI')
})
@@ -329,7 +332,7 @@ describe('tool specific content', () => {
expect(selectedSwitch).toHaveLength(1)
// content for NOT selected tools is expected to become hidden
const otherTools = tools.filter(e => e !== tool)
const otherTools = tools.filter((e) => e !== tool)
for (const other of otherTools) {
await page.waitForSelector(`.extended-markdown.${other}`, { hidden: true, timeout: 3000 })
}
@@ -352,7 +355,7 @@ describe('tool specific content', () => {
expect(selectedSwitch).toHaveLength(toolSelector.length)
const selectedToolElement = await page.waitForSelector('a.tool-switcher.selected')
const selectedTool = await page.evaluate(el => el.textContent, selectedToolElement)
const selectedTool = await page.evaluate((el) => el.textContent, selectedToolElement)
expect(selectedTool).toBe(toolName)
}
})

View File

@@ -7,14 +7,14 @@ import {
upcomingChangesValidator,
} from '../../lib/graphql/validator.js'
import revalidator from 'revalidator'
import xAllVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import { jest } from '@jest/globals'
const previewsJson = readJsonFile('./lib/graphql/static/previews.json')
const upcomingChangesJson = readJsonFile('./lib/graphql/static/upcoming-changes.json')
const prerenderedObjectsJson = readJsonFile('./lib/graphql/static/prerendered-objects.json')
const allVersions = Object.values(xAllVersions)
const graphqlVersions = allVersions.map((v) => v.miscVersionName)
const allVersionValues = Object.values(allVersions)
const graphqlVersions = allVersionValues.map((v) => v.miscVersionName)
const graphqlTypes = readJsonFile('./lib/graphql/types.json').map((t) => t.kind)
describe('graphql json files', () => {

View File

@@ -30,7 +30,7 @@ const frontmatter1 = path.join(removeLiquidStatementsFixtures, 'frontmatter1.md'
const frontmatter2 = path.join(removeLiquidStatementsFixtures, 'frontmatter2.md')
// process frontmatter
function processFrontmatter (contents, file) {
function processFrontmatter(contents, file) {
const { content, data } = matter(contents)
removeDeprecatedFrontmatter(file, data.versions, versionToDeprecate, nextOldestVersion)
return matter.stringify(content, data, { lineWidth: 10000 })
@@ -68,8 +68,11 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes > 2.16 %}\n\nCharlie\n
let contents = await readFileAsync(andGreaterThan1, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
expect($('.example1').text().trim()).toBe('{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% endif %}')
expect($('.example2').text().trim()).toBe(`{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% else %}\n
expect($('.example1').text().trim()).toBe(
'{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% endif %}'
)
expect($('.example2').text().trim())
.toBe(`{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% else %}\n
Bravo\n\n{% endif %}`)
expect($('.example3').text().trim()).toBe(`{% ifversion ghes > 2.16 %}\n
Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion not fpt and ghes %}\n\nCharlie\n\n{% endif %}\n{% endif %}`)
@@ -104,7 +107,8 @@ Alpha\n\n{% ifversion not fpt %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCharli
Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes %}\n\nCharlie\n\n{% endif %}\n\n{% endif %}`)
expect($('.example4').text().trim()).toBe(`{% ifversion fpt %}\n
Alpha\n\n{% ifversion ghes %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
expect($('.example5').text().trim()).toBe(`{% ifversion ghes %}\n\nAlpha\n\n{% ifversion fpt %}\n
expect($('.example5').text().trim())
.toBe(`{% ifversion ghes %}\n\nAlpha\n\n{% ifversion fpt %}\n
Bravo\n\n{% endif %}\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
expect($('.example6').text().trim()).toBe(`{% ifversion not fpt and ghes %}\n
Alpha\n\n{% endif %}`)
@@ -123,7 +127,9 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% endif %}`)
expect($('.example4').text().trim()).toBe(`{% ifversion fpt %}\n
Alpha\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
expect($('.example5').text().trim()).toBe('Charlie')
expect($('.example6').text().trim()).toBe('Charlie\n\n{% ifversion fpt or ghes %}\n\nBravo\n\n{% endif %}')
expect($('.example6').text().trim()).toBe(
'Charlie\n\n{% ifversion fpt or ghes %}\n\nBravo\n\n{% endif %}'
)
})
test('removes interior content and liquid statements that specify "less than next oldest than version to deprecate"', async () => {
@@ -131,7 +137,9 @@ Alpha\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
expect($('.example1').text().trim()).toBe('Alpha')
expect($('.example2').text().trim()).toBe('Alpha\n\n{% ifversion fpt %}\n\nBravo\n\n{% endif %}')
expect($('.example2').text().trim()).toBe(
'Alpha\n\n{% ifversion fpt %}\n\nBravo\n\n{% endif %}'
)
expect($('.example3').text().trim()).toBe(`{% ifversion fpt %}\n
Alpha\n\n{% else %}\n\nBravo\n\n{% endif %}`)
expect($('.example4').text().trim()).toBe(`{% ifversion fpt %}\n
@@ -151,16 +159,16 @@ describe('updating frontmatter', () => {
let contents = await readFileAsync(frontmatter1, 'utf8')
contents = processFrontmatter(contents, frontmatter1)
const $ = cheerio.load(contents)
expect($.text().includes('ghes: \'*\'')).toBe(true)
expect($.text().includes('ghes: \'>=2.13\'')).toBe(false)
expect($.text().includes("ghes: '*'")).toBe(true)
expect($.text().includes("ghes: '>=2.13'")).toBe(false)
})
test('updates frontmatter versions Enterprise if set to greater-than-or-equal-to next oldest version', async () => {
let contents = await readFileAsync(frontmatter2, 'utf8')
contents = processFrontmatter(contents, frontmatter2)
const $ = cheerio.load(contents)
expect($.text().includes('ghes: \'*\'')).toBe(true)
expect($.text().includes('ghes: \'>=2.14\'')).toBe(false)
expect($.text().includes("ghes: '*'")).toBe(true)
expect($.text().includes("ghes: '>=2.14'")).toBe(false)
})
})
@@ -180,11 +188,13 @@ describe('whitespace', () => {
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
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')
expect($('.example6').text()).toBe(
'\n Alpha\n{% ifversion fpt or ghes %}\n Bravo\n{% endif %}\n Charlie\n'
)
expect($('.example7').text()).toBe('\nAlpha{% ifversion fpt or ghes %}\nBravo{% endif %}\n')
})
test('only remove newlines when tag starts at beginning of line', async() =>{
test('only remove newlines when tag starts at beginning of line', async () => {
let contents = await readFileAsync(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
@@ -193,4 +203,4 @@ describe('whitespace', () => {
expect($('.example10').text()).toBe('\nPre\nBravo\n')
expect($('.example11').text()).toBe('\nPre\nBravo\n')
})
})
})

View File

@@ -1,23 +1,24 @@
import { difference } from 'lodash-es'
import { getJSON } from '../helpers/supertest.js'
import { latest } from '../../lib/enterprise-server-releases.js'
import xAllVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import webhookPayloads from '../../lib/webhooks'
import { jest } from '@jest/globals'
const allVersions = Object.values(xAllVersions)
const payloadVersions = allVersions.map((v) => v.miscVersionName)
const allVersionValues = Object.values(allVersions)
const payloadVersions = allVersionValues.map((v) => v.miscVersionName)
// grab some values for testing
const nonEnterpriseDefaultPayloadVersion = allVersions.find(
const nonEnterpriseDefaultPayloadVersion = allVersionValues.find(
(version) => version.nonEnterpriseDefault
).miscVersionName
const latestGhesPayloadVersion = allVersions.find(
const latestGhesPayloadVersion = allVersionValues.find(
(version) => version.currentRelease === latest
).miscVersionName
const ghaePayloadVersion = allVersions.find(
const ghaePayloadVersion = allVersionValues.find(
(version) => version.plan === 'github-ae'
).miscVersionName

View File

@@ -18,7 +18,7 @@ import featureVersionsSchema from '../helpers/schemas/feature-versions-schema.js
import renderContent from '../../lib/render-content/index.js'
import getApplicableVersions from '../../lib/get-applicable-versions.js'
import { execSync } from 'child_process'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import { supported, next } from '../../lib/enterprise-server-releases.js'
import { getLiquidConditionals } from '../../script/helpers/get-liquid-conditionals.js'
import allowedVersionOperators from '../../lib/liquid-tags/ifversion-supported-operators.js'

View File

@@ -32,8 +32,12 @@ describe('header', () => {
test('display the native name and the English name for each translated language', async () => {
const $ = await getDOM('/en')
expect($('[data-testid=language-picker] a[href="/en/"]').text().trim()).toBe('English')
expect($('[data-testid=language-picker] a[href="/cn/"]').text().trim()).toBe('简体中文 (Simplified Chinese)')
expect($('[data-testid=language-picker] a[href="/ja/"]').text().trim()).toBe('日本語 (Japanese)')
expect($('[data-testid=language-picker] a[href="/cn/"]').text().trim()).toBe(
'简体中文 (Simplified Chinese)'
)
expect($('[data-testid=language-picker] a[href="/ja/"]').text().trim()).toBe(
'日本語 (Japanese)'
)
})
test('emphasize the current language', async () => {

View File

@@ -1,7 +1,7 @@
import { liquid } from '../../lib/render-content/index.js'
import shortVersionsMiddleware from '../../middleware/contextualizers/short-versions.js'
import featureVersionsMiddleware from '../../middleware/contextualizers/features.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import enterpriseServerReleases from '../../lib/enterprise-server-releases.js'
import loadSiteData from '../../lib/site-data.js'

View File

@@ -2,7 +2,7 @@ import { fileURLToPath } from 'url'
import path from 'path'
import walk from 'walk-sync'
import { get, isPlainObject } from 'lodash-es'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js'
import { operations } from '../../lib/rest/index.js'
import dedent from 'dedent'

View File

@@ -3,7 +3,7 @@ import path from 'path'
import cheerio from 'cheerio'
import Page from '../../lib/page.js'
import readJsonFile from '../../lib/read-json-file.js'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import enterpriseServerReleases, { latest } from '../../lib/enterprise-server-releases.js'
import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js'
// import getLinkData from '../../lib/get-link-data.js'

View File

@@ -1,8 +1,7 @@
import { jest } from '@jest/globals'
import { loadPages } from '../../lib/page-data.js'
import renderContent from '../../lib/render-content/index.js'
import xAllVersions from '../../lib/all-versions.js'
const allVersions = Object.keys(xAllVersions)
import { allVersionKeys } from '../../lib/all-versions.js'
describe('toc links', () => {
jest.setTimeout(3 * 60 * 1000)
@@ -16,7 +15,7 @@ describe('toc links', () => {
const issues = []
for (const pageVersion of allVersions) {
for (const pageVersion of allVersionKeys) {
for (const page of englishIndexPages) {
// skip page if it doesn't have a permalink for the current product version
if (!page.permalinks.some((permalink) => permalink.pageVersion === pageVersion)) continue

View File

@@ -1,6 +1,6 @@
import { jest } from '@jest/globals'
import revalidator from 'revalidator'
import allVersions from '../../lib/all-versions.js'
import { allVersions } from '../../lib/all-versions.js'
import { latest } from '../../lib/enterprise-server-releases.js'
import schema from '../helpers/schemas/versions-schema.js'
import { getJSON } from '../helpers/supertest.js'