diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2c9d59e3..0e8861e0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -121,20 +121,20 @@ jobs: - name: Clean cache on stage if: needs.set-state.outputs.clean_cache == 'true' && needs.set-state.outputs.deploy_stage == 'true' run: | - bash .github/scripts/process-mds.sh cache stage ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" + bash .github/scripts/process-mds.sh cache stage ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" - name: Clean cache on prod if: needs.set-state.outputs.clean_cache == 'true' && needs.set-state.outputs.deploy_prod == 'true' run: | - bash .github/scripts/process-mds.sh cache prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" + bash .github/scripts/process-mds.sh cache prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" - name: Deploy to stage if: needs.set-state.outputs.deploy_stage == 'true' run: | - bash .github/scripts/process-mds.sh preview stage ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" + bash .github/scripts/process-mds.sh preview stage ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" - name: Deploy to prod if: needs.set-state.outputs.deploy_prod == 'true' - run: | - bash .github/scripts/process-mds.sh preview prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" - bash .github/scripts/process-mds.sh live prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" + run: | + bash .github/scripts/process-mds.sh preview prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" + bash .github/scripts/process-mds.sh live prod ${{ needs.set-state.outputs.branch_short_ref }} "${{ needs.set-state.outputs.path_prefix }}" \ No newline at end of file diff --git a/buildRedirections.js b/buildRedirections.js index 3fec0d03..f7815409 100644 --- a/buildRedirections.js +++ b/buildRedirections.js @@ -1,7 +1,7 @@ const path = require('path'); -const fs = require('node:fs'); const { pathPrefix } = require('./gatsby-config.js'); const { globSync }= require('glob'); +const { writeRedirectionsFile } = require('./scriptUtils.js'); try { if(!pathPrefix) { @@ -39,17 +39,7 @@ try { } }); - let redirectionsData = - { - "total" : data.length, - "offset": 0, - "limit": data.length, - "data" : data, - ":type": "sheet" - }; - - let redirectionsFilePath = path.resolve(__dirname + '/src/pages/redirects.json'); - fs.writeFileSync(redirectionsFilePath, JSON.stringify(redirectionsData)); + writeRedirectionsFile(data); } catch (err) { console.error(err); diff --git a/normalizeLinks.js b/normalizeLinks.js new file mode 100644 index 00000000..5209dfc5 --- /dev/null +++ b/normalizeLinks.js @@ -0,0 +1,66 @@ +const path = require('path'); +const fs = require('node:fs'); +const matchAll = require('string.prototype.matchall'); +const { + getMarkdownFiles, + replaceLinksInFile, + getFindPatternForMarkdownFiles: getFindPattern, + getReplacePatternForMarkdownFiles: getReplacePattern, +} = require('./scriptUtils.js'); + +function normalizeLinksInMarkdownFile(file, files) { + const relativeToDir = path.dirname(file); + const relativeFiles = files.map(file => path.relative(relativeToDir, file)); + const linkMap = new Map(); + + const linkPattern = getFindPattern('[^)#]*'); + let data = fs.readFileSync(file, 'utf8'); + const links = matchAll(data, new RegExp(linkPattern, "gm")); + [...links].forEach(link => { + const optionalPrefix = link[2] ?? ''; + const from = link[3] ?? ''; + let to = from; + + // ensure link includes file name and extension + if(to.endsWith('/') || optionalPrefix.endsWith('/') && !to) { + to = `${to}index.md` + } + if(!to.endsWith('.md') && to) { + to = `${to}.md`; + } + + to = to.replaceAll('/', path.sep); + + // ensure simplest relative path + // this removes trailing slash, so need to do this after the file name and extension checks above + const absolute = path.resolve(relativeToDir, to); + const relative = path.relative(relativeToDir, absolute); + to = relative; + + // ensure the link we constructed above exists + const toExists = relativeFiles.find(file => to === file); + + to = to.replaceAll(path.sep, '/'); + + if(to !== from && toExists) { + linkMap.set(from, to); + } + }) + + replaceLinksInFile({ + file, + linkMap, + getFindPattern, + getReplacePattern, + }); +} + +try { + const files = getMarkdownFiles(); + files.forEach(file => { + normalizeLinksInMarkdownFile(file, files); + }); + +} catch (err) { + console.error(err); +} \ No newline at end of file diff --git a/package.json b/package.json index 127ad901..79902c52 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "private": true, - "name": "adobe-dev-console", + "name": "dev-site-documentation-template", "version": "1.0.0", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/AdobeDocs/adobe-dev-console" + "url": "https://github.com/AdobeDocs/dev-site-documentation-template" }, "author": { "name": "Stephan Ringel", "url": "https://github.com/icaraps" }, "dependencies": { - "@adobe/gatsby-theme-aio": "^4.14.18", + "@adobe/gatsby-theme-aio": "^4.14.6", "gatsby": "4.22.0", "react": "^17.0.2", "react-dom": "^17.0.2" @@ -27,20 +27,21 @@ "dev": "gatsby develop", "dev:https": "gatsby develop --https --host localhost.corp.adobe.com --port 9000", "build": "gatsby build", - "build:incremental": "GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build --log-pages", "serve": "gatsby serve", "clean": "gatsby clean", "test:links": "remark src/pages --quiet --frail", "lint": "docker run --rm -e RUN_LOCAL=true --env-file '.github/super-linter.env' -v \"$PWD\":/tmp/lint github/super-linter:slim-v4.10.1", "buildNavigation": "node buildNavigation.js", - "buildRedirections": "node buildRedirections.js" + "buildRedirections": "node buildRedirections.js", + "renameFiles": "node renameFiles.js", + "normalizeLinks": "node normalizeLinks.js" }, "remarkConfig": { "plugins": [ "remark-validate-links" ] }, - "packageManager": "yarn@3.2.2", + "packageManager": "yarn@3.2.1", "devDependencies": { "glob": "11.0.0", "remark-cli": "^11.0.0", diff --git a/renameFiles.js b/renameFiles.js new file mode 100644 index 00000000..7a18a5bd --- /dev/null +++ b/renameFiles.js @@ -0,0 +1,142 @@ +const path = require('path'); +const fs = require('node:fs'); +const { pathPrefix } = require('./gatsby-config.js'); +const { + readRedirectionsFile, + writeRedirectionsFile, + getRedirectionsFilePath, + getMarkdownFiles, + getFindPatternForMarkdownFiles, + getReplacePatternForMarkdownFiles, + replaceLinksInFile +} = require('./scriptUtils.js'); + +function toKebabCase(str) { + const isScreamingSnakeCase = new RegExp(/^[A-Z0-9_]*$/gm).test(str); + str = isScreamingSnakeCase ? str.toLowerCase() : str; + return str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.toLowerCase()) + .join('-'); +} + +function toEdsCase(str) { + const isValid = Boolean((/^([a-z0-9-]*)$/.test(str))); + return isValid ? str : toKebabCase(str); +} + +function toUrl(file, renameBaseWithoutExt = name => name) { + const base = path.basename(file); + const ext = path.extname(file); + const end = file.length - base.length; + const baseWithoutExt = base.substring(0, base.length - ext.length); + const newBaseWithoutExt = renameBaseWithoutExt(baseWithoutExt); + return `${file.substring(0, end)}${newBaseWithoutExt}` +} + +function renameFile(file, renameBaseWithoutExt) { + const url = toUrl(file, renameBaseWithoutExt); + const ext = path.extname(file); + return `${url}${ext}` +} + +function getFileMap(files) { + const map = new Map(); + files.forEach(from => { + const to = renameFile(from, toEdsCase) + if(to !== from) { + map.set(from, to) + } + }); + return map; +} + +function getLinkMap(fileMap, relativeToDir) { + const linkMap = new Map(); + fileMap.forEach((toFile, fromFile) => { + let fromRelFile = path.relative(relativeToDir, fromFile); + fromRelFile = fromRelFile.replaceAll(path.sep, '/'); + + let toRelFile = path.relative(relativeToDir, toFile); + toRelFile = toRelFile.replaceAll(path.sep, '/'); + + linkMap.set(fromRelFile, toRelFile); + }); + return linkMap; +} + +function renameLinksInMarkdownFile(fileMap, file) { + const dir = path.dirname(file); + replaceLinksInFile({ + file, + linkMap: getLinkMap(fileMap, dir), + getFindPattern: getFindPatternForMarkdownFiles, + getReplacePattern: getReplacePatternForMarkdownFiles, + }); +} + +function renameLinksInRedirectsFile(fileMap) { + const file = getRedirectionsFilePath(); + const dir = path.dirname(file); + replaceLinksInFile({ + file, + linkMap: getLinkMap(fileMap, dir), + getFindPattern: (from) => `(['"]?)(Source|Destination)(['"]?\\s*:\\s*['"])(${pathPrefix}${toUrl(from)})(/?)(#[^'"]*)?(['"])`, + getReplacePattern: (to) => `$1$2$3${pathPrefix}${toUrl(to)}$5$6$7`, + }); +} + +function renameLinksInGatsbyConfigFile(fileMap, file) { + const dir = path.join('src', 'pages'); + replaceLinksInFile({ + file, + linkMap: getLinkMap(fileMap, dir), + getFindPattern: (from) => `(['"]?path['"]?\\s*:\\s*['"])(/|./)?(${from})(#[^'"]*)?(['"])`, + getReplacePattern: (to) => `$1$2${to}$4$5`, + }); +} + +function appendRedirects(fileMap) { + const file = getRedirectionsFilePath(); + const dir = path.dirname(file); + const linkMap = getLinkMap(fileMap, dir); + const newData = []; + linkMap.forEach((to, from) => { + newData.push({ + Source: `${pathPrefix}${toUrl(from)}`, + Destination: `${pathPrefix}${toUrl(to)}`, + }) + }); + const currData = readRedirectionsFile(); + const data = [...currData, ...newData]; + writeRedirectionsFile(data); +} + +function renameFiles(map) { + map.forEach((to, from) => { + fs.renameSync(from, to); + }); +} + +try { + const markdownFiles = getMarkdownFiles(); + const fileMap = getFileMap(markdownFiles); + markdownFiles.forEach(file => { + renameLinksInMarkdownFile(fileMap, file); + }); + renameFiles(fileMap); + + const redirectsFile = getRedirectionsFilePath(); + if(fs.existsSync(redirectsFile)) { + renameLinksInRedirectsFile(fileMap); + appendRedirects(fileMap); + } + + const gatsbyConfigFile = 'gatsby-config.js'; + if(fs.existsSync(gatsbyConfigFile)) { + renameLinksInGatsbyConfigFile(fileMap, gatsbyConfigFile); + } + +} catch (err) { + console.error(err); +} \ No newline at end of file diff --git a/scriptUtils.js b/scriptUtils.js new file mode 100644 index 00000000..1eb2b7c4 --- /dev/null +++ b/scriptUtils.js @@ -0,0 +1,55 @@ +const path = require('path'); +const fs = require('node:fs'); +const { globSync }= require('glob'); + +function getRedirectionsFilePath() { + const redirectionsFilePath = path.join(__dirname, 'src', 'pages', 'redirects.json'); + return path.resolve(redirectionsFilePath); +} + +function readRedirectionsFile() { + const redirectionsFilePath = getRedirectionsFilePath(); + return JSON.parse(fs.readFileSync(redirectionsFilePath)).data; +} + +function writeRedirectionsFile(data) { + let redirectionsData = + { + "total" : data.length, + "offset": 0, + "limit": data.length, + "data" : data, + ":type": "sheet" + }; + + let redirectionsFilePath = getRedirectionsFilePath(); + fs.writeFileSync(redirectionsFilePath, JSON.stringify(redirectionsData)); +} + +function getMarkdownFiles() { + return globSync(__dirname + '/src/pages/**/*.md') + .map(f => path.resolve(f)); +} + +const getFindPatternForMarkdownFiles = (from) => `(\\[[^\\]]*]\\()(/|./)?(${from})(#[^\\()]*)?(\\))`; +const getReplacePatternForMarkdownFiles = (to) => `$1$2${to}$4$5`; + +function replaceLinksInFile({ file, linkMap, getFindPattern, getReplacePattern }) { + let data = fs.readFileSync(file, 'utf8'); + linkMap.forEach((to, from) => { + const find = getFindPattern(from); + const replace = getReplacePattern(to); + data = data.replaceAll(new RegExp(find, "gm"), replace); + }); + fs.writeFileSync(file, data, 'utf-8'); +} + +module.exports = { + getRedirectionsFilePath, + readRedirectionsFile, + writeRedirectionsFile, + getMarkdownFiles, + getFindPatternForMarkdownFiles, + getReplacePatternForMarkdownFiles, + replaceLinksInFile +}; \ No newline at end of file diff --git a/src/pages/guides/authentication/ServerToServerAuthentication/index.md b/src/pages/guides/authentication/ServerToServerAuthentication/index.md index 368866dd..84fc1330 100644 --- a/src/pages/guides/authentication/ServerToServerAuthentication/index.md +++ b/src/pages/guides/authentication/ServerToServerAuthentication/index.md @@ -48,7 +48,7 @@ Read our OAuth Server-to-server credential implementation guide - -The Service Account (JWT) credentials have been deprecated in favor of the OAuth Server-to-Server credentials. Your applications using the Service Account (JWT) credentials will stop working after Jun 30, 2025. You must migrate to the new credential by **Jun 30, 2025**, to ensure your application continues functioning. [Learn more](../ServerToServerAuthentication/migration.md). +The Service Account (JWT) credentials have been deprecated in favor of the OAuth Server-to-Server credentials. Your applications using the Service Account (JWT) credentials will stop working after Jun 30, 2025. You must migrate to the new credential by **Jun 30, 2025**, to ensure your application continues functioning. [Learn more](migration.md). Service Account (JWT) credentials rely on the JWT token exchange mechanism to generate access tokens. This credential's details include two secrets a `client_secret` and a `private.key` (part of a public certificate private key pair). diff --git a/src/pages/guides/authentication/UserAuthentication/implementation.md b/src/pages/guides/authentication/UserAuthentication/implementation.md index ba94bc4a..d3709272 100644 --- a/src/pages/guides/authentication/UserAuthentication/implementation.md +++ b/src/pages/guides/authentication/UserAuthentication/implementation.md @@ -1,6 +1,6 @@ # User Authentication Implementation Guide -The following guide goes over finer implementation details for user authentication credentials. At the end of this guide is a list of recommended industry-standard OAuth2 libraries. Before proceeding, we recommend you familiarize yourself with the 3-legged OAuth flow in our [user authentication guide](../UserAuthentication/index.md). +The following guide goes over finer implementation details for user authentication credentials. At the end of this guide is a list of recommended industry-standard OAuth2 libraries. Before proceeding, we recommend you familiarize yourself with the 3-legged OAuth flow in our [user authentication guide](index.md). ## User authentication credential types diff --git a/src/pages/guides/plugins/plugin-distribution.md b/src/pages/guides/plugins/plugin-distribution.md index e2d8f86d..49cfd542 100644 --- a/src/pages/guides/plugins/plugin-distribution.md +++ b/src/pages/guides/plugins/plugin-distribution.md @@ -2,7 +2,7 @@ This guide provides instructions for distributing a Plugin created in Adobe Developer Console. -For information on how to build a plugin, please being by reading the [plugin overview](../plugins/index.md). +For information on how to build a plugin, please being by reading the [plugin overview](index.md). ## Select plugin project diff --git a/src/pages/guides/services/services-add-api-jwt.md b/src/pages/guides/services/services-add-api-jwt.md index 33be8fd6..de8c4d40 100644 --- a/src/pages/guides/services/services-add-api-jwt.md +++ b/src/pages/guides/services/services-add-api-jwt.md @@ -2,4 +2,4 @@ -Service Account (JWT) credentials have been deprecated in favor of the OAuth Server-to-Server credentials. View our [migration guide](../authentication/ServerToServerAuthentication/migration.md) to know more. The new version of this guide that uses OAuth Server-to-Server credentials is now available here - [**Add API to project using OAuth Server-to-Server credentials**](../services/services-add-api-oauth-s2s.md). +Service Account (JWT) credentials have been deprecated in favor of the OAuth Server-to-Server credentials. View our [migration guide](../authentication/ServerToServerAuthentication/migration.md) to know more. The new version of this guide that uses OAuth Server-to-Server credentials is now available here - [**Add API to project using OAuth Server-to-Server credentials**](services-add-api-oauth-s2s.md). diff --git a/src/pages/guides/services/services-add-api-key.md b/src/pages/guides/services/services-add-api-key.md index 22cb570a..9b443725 100644 --- a/src/pages/guides/services/services-add-api-key.md +++ b/src/pages/guides/services/services-add-api-key.md @@ -60,7 +60,7 @@ To learn more about insights, begin by reading the [insights overview](../insigh ## Next steps -With an API successfully added, you can follow the same workflow steps to add additional APIs, or return to the [services overview](../services/index.md) to select another type of service to add to your project. +With an API successfully added, you can follow the same workflow steps to add additional APIs, or return to the [services overview](index.md) to select another type of service to add to your project. If you have completed development on your project and are ready to submit your application for approval, please read the [project approval guide](../projects/approval.md) to get started. diff --git a/src/pages/guides/services/services-add-api-oauth-s2-s.md b/src/pages/guides/services/services-add-api-oauth-s2s.md similarity index 98% rename from src/pages/guides/services/services-add-api-oauth-s2-s.md rename to src/pages/guides/services/services-add-api-oauth-s2s.md index 065c85fb..69159012 100644 --- a/src/pages/guides/services/services-add-api-oauth-s2-s.md +++ b/src/pages/guides/services/services-add-api-oauth-s2s.md @@ -99,6 +99,6 @@ To learn more about insights, begin by reading the [insights overview](../insigh ## Next steps -With an API successfully added, you can follow the same workflow steps to add additional APIs, or return to the [services overview](../services/index.md) to select another type of service to add to your project. +With an API successfully added, you can follow the same workflow steps to add additional APIs, or return to the [services overview](index.md) to select another type of service to add to your project. If you have completed development on your project and are ready to submit your application for approval, please read the [project approval guide](../projects/approval.md) to get started. \ No newline at end of file diff --git a/src/pages/guides/services/services-add-api-oauth-user-authentication.md b/src/pages/guides/services/services-add-api-oauth-user-authentication.md index 90ef91b5..ed5470f9 100644 --- a/src/pages/guides/services/services-add-api-oauth-user-authentication.md +++ b/src/pages/guides/services/services-add-api-oauth-user-authentication.md @@ -129,7 +129,7 @@ To learn more about insights, begin by reading the [insights overview](../insigh ## Next steps -With an API successfully added, you can follow the same workflow steps to add additional APIs or return to the [services overview](../services/index.md) to select another type of service to add to your project. +With an API successfully added, you can follow the same workflow steps to add additional APIs or return to the [services overview](index.md) to select another type of service to add to your project. If you have completed development on your project and are ready to submit your application for approval, please read the [project approval guide](../projects/approval.md) to get started. diff --git a/src/pages/guides/services/services-add-api-oauth.md b/src/pages/guides/services/services-add-api-oauth.md index e80cf8a0..fbb3fad1 100644 --- a/src/pages/guides/services/services-add-api-oauth.md +++ b/src/pages/guides/services/services-add-api-oauth.md @@ -2,4 +2,4 @@ -The new version of this guide is now available here - [Add API to project using OAuth User Authentication credentials](../services/services-add-api-oauth-user-authentication.md). \ No newline at end of file +The new version of this guide is now available here - [Add API to project using OAuth User Authentication credentials](services-add-api-oauth-user-authentication.md). \ No newline at end of file diff --git a/src/pages/guides/services/services-add-event.md b/src/pages/guides/services/services-add-event.md index 67cf0bba..4c2d546b 100644 --- a/src/pages/guides/services/services-add-event.md +++ b/src/pages/guides/services/services-add-event.md @@ -78,6 +78,6 @@ The *Debug Tracing* tab shows details related to recent requests and responses r ## Next steps -Now that you have successfully added events to your project or workspace, you can follow this workflow again to add additional event registrations, or return to the [services overview](../services/index.md) to select another type of service to add to your project. +Now that you have successfully added events to your project or workspace, you can follow this workflow again to add additional event registrations, or return to the [services overview](index.md) to select another type of service to add to your project. If you have completed development on your project and are ready to submit your application for approval, please read the [project approval guide](../projects/approval.md) to get started. \ No newline at end of file diff --git a/src/pages/guides/services/services-enable-runtime.md b/src/pages/guides/services/services-enable-runtime.md index e2300c31..82e683e0 100644 --- a/src/pages/guides/services/services-enable-runtime.md +++ b/src/pages/guides/services/services-enable-runtime.md @@ -66,6 +66,6 @@ To learn more about insights, begin by reading the [insights overview](../insigh ## Next steps -With Runtime successfully added to your project or workspace, you can now return to the [services overview](../services/index.md) to select another type of service to add to your project. +With Runtime successfully added to your project or workspace, you can now return to the [services overview](index.md) to select another type of service to add to your project. If you have completed development on your project and are ready to submit your application for approval, please read the [project approval guide](../projects/approval.md) to get started. \ No newline at end of file diff --git a/src/pages/support/faq.md b/src/pages/support/faq.md index 062979f7..4812fb1a 100644 --- a/src/pages/support/faq.md +++ b/src/pages/support/faq.md @@ -1,6 +1,6 @@ # Frequently Asked Questions -This document provides answers to frequently asked questions about Adobe Developer Console. This is a great place to start when troubleshooting a problem with Console. If you are unable to find the answer you're looking for, please refer to the [Support overview](../support/index.md) for additional resources. +This document provides answers to frequently asked questions about Adobe Developer Console. This is a great place to start when troubleshooting a problem with Console. If you are unable to find the answer you're looking for, please refer to the [Support overview](index.md) for additional resources. ## Questions