|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +// [start-readme] |
| 4 | +// |
| 5 | +// Run this script to add versions frontmatter and Liquid conditionals for |
| 6 | +// GitHub Enterprise Cloud, based on anything currently versioned for the specified release |
| 7 | +// of free-pro-team. |
| 8 | +// |
| 9 | +// [end-readme] |
| 10 | + |
| 11 | +const fs = require('fs') |
| 12 | +const path = require('path') |
| 13 | +const walk = require('walk-sync') |
| 14 | +const program = require('commander') |
| 15 | +const frontmatter = require('../../lib/read-frontmatter') |
| 16 | +const contentPath = path.join(process.cwd(), 'content') |
| 17 | +const dataPath = path.join(process.cwd(), 'data') |
| 18 | + |
| 19 | +program |
| 20 | + .description('Add versions frontmatter and Liquid conditionals for GitHub EC based on FPT. Runs on all content by default.') |
| 21 | + .option('-p, --products [OPTIONAL PRODUCT_IDS...]', 'Optional list of space-separated product IDs. Example: admin github developers') |
| 22 | + .parse(process.argv) |
| 23 | + |
| 24 | +const { products } = program.opts() |
| 25 | + |
| 26 | +console.log('✅ Adding EC versioning based on FPT latest versioning') |
| 27 | + |
| 28 | +if (products) { |
| 29 | + console.log(`✅ Running on the following products: ${products}`) |
| 30 | +} else { |
| 31 | + console.log('✅ Running on all products') |
| 32 | +} |
| 33 | + |
| 34 | +console.log('✅ Running on English content and data\n') |
| 35 | + |
| 36 | +// The new conditional to add |
| 37 | +const githubECConditional = 'currentVersion == "enterprise-cloud@latest"' |
| 38 | + |
| 39 | +// Match: currentVersion == "free-pro-team@latest" |
| 40 | +const fptConditionalRegex = /currentVersion == "free-pro-team@latest"/ |
| 41 | + |
| 42 | +console.log('Working...\n') |
| 43 | + |
| 44 | +const englishContentFiles = walkContent(contentPath) |
| 45 | +const englishDataFiles = walkData(dataPath) |
| 46 | + |
| 47 | +function walkContent (dirPath) { |
| 48 | + const productArray = products || [''] |
| 49 | + return productArray.map(product => { |
| 50 | + dirPath = path.join(contentPath, product) |
| 51 | + return walk(dirPath, { includeBasePath: true, directories: false }) |
| 52 | + .filter(file => file.includes('/content/')) |
| 53 | + .filter(file => file.endsWith('.md')) |
| 54 | + .filter(file => !file.endsWith('README.md')) |
| 55 | + }).flat() |
| 56 | +} |
| 57 | + |
| 58 | +function walkData (dirPath) { |
| 59 | + return walk(dirPath, { includeBasePath: true, directories: false }) |
| 60 | + .filter(file => file.includes('/data/reusables') || file.includes('/data/variables')) |
| 61 | + .filter(file => !file.endsWith('README.md')) |
| 62 | +} |
| 63 | + |
| 64 | +const allContentFiles = englishContentFiles |
| 65 | +const allDataFiles = englishDataFiles |
| 66 | + |
| 67 | +// Update the data files |
| 68 | +allDataFiles |
| 69 | + .forEach(file => { |
| 70 | + const dataContent = fs.readFileSync(file, 'utf8') |
| 71 | + |
| 72 | + const conditionalsToUpdate = getConditionalsToUpdate(dataContent) |
| 73 | + if (!conditionalsToUpdate.length) return |
| 74 | + |
| 75 | + // Update Liquid in data files |
| 76 | + const newDataContent = updateLiquid(conditionalsToUpdate, dataContent) |
| 77 | + |
| 78 | + fs.writeFileSync(file, newDataContent) |
| 79 | + }) |
| 80 | + |
| 81 | +// Update the content files |
| 82 | +allContentFiles |
| 83 | + .forEach(file => { |
| 84 | + const { data, content } = frontmatter(fs.readFileSync(file, 'utf8')) |
| 85 | + |
| 86 | + // Return early if the current page frontmatter does not apply to either GHEC or the given fpt release |
| 87 | + if (!(data.versions['free-pro-team'])) return |
| 88 | + |
| 89 | + const conditionalsToUpdate = getConditionalsToUpdate(content) |
| 90 | + if (!conditionalsToUpdate.length) return |
| 91 | + |
| 92 | + // Update Liquid in content files |
| 93 | + const newContent = updateLiquid(conditionalsToUpdate, content) |
| 94 | + |
| 95 | + // Add frontmatter version |
| 96 | + data.versions['enterprise-cloud'] = '*' |
| 97 | + |
| 98 | + // Update Liquid in frontmatter props |
| 99 | + Object.keys(data) |
| 100 | + .filter(key => typeof data[key] === 'string') |
| 101 | + .forEach(key => { |
| 102 | + const conditionalsToUpdate = getConditionalsToUpdate(data[key]) |
| 103 | + if (!conditionalsToUpdate.length) return |
| 104 | + data[key] = updateLiquid(conditionalsToUpdate, data[key]) |
| 105 | + }) |
| 106 | + |
| 107 | + fs.writeFileSync(file, frontmatter.stringify(newContent, data, { lineWidth: 10000 })) |
| 108 | + }) |
| 109 | + |
| 110 | +function getConditionalsToUpdate (content) { |
| 111 | + const allConditionals = content.match(/{% if .+?%}/g) |
| 112 | + |
| 113 | + return (allConditionals || []) |
| 114 | + .filter(conditional => !conditional.includes('enterprise-cloud')) |
| 115 | + .filter(conditional => conditional.includes('free-pro-team')) |
| 116 | +} |
| 117 | + |
| 118 | +function updateLiquid (conditionalsToUpdate, content) { |
| 119 | + let newContent = content |
| 120 | + |
| 121 | + conditionalsToUpdate.forEach(conditional => { |
| 122 | + let newConditional = conditional |
| 123 | + |
| 124 | + const fptMatch = conditional.match(fptConditionalRegex) |
| 125 | + |
| 126 | + if (!fptMatch) { |
| 127 | + console.error(conditional) |
| 128 | + return |
| 129 | + } |
| 130 | + |
| 131 | + // First do the replacement within the conditional |
| 132 | + // Old: {% if currentVersion == "free-pro-team@latest" or currentVersion ver_gt "[email protected]" %} |
| 133 | + // New: {% if currentVersion == "free-pro-team@latest" or currentVersion ver_gt "[email protected]" or currentVersion == "enterprise-cloud@latest" %} |
| 134 | + newConditional = newConditional.replace(fptMatch[0], `${fptMatch[0]} or ${githubECConditional}`) |
| 135 | + |
| 136 | + // Then replace all instances of the conditional in the content |
| 137 | + newContent = newContent.replace(conditional, newConditional) |
| 138 | + }) |
| 139 | + |
| 140 | + return newContent |
| 141 | +} |
| 142 | + |
| 143 | +console.log('Done!') |
0 commit comments