diff --git a/website/scripts/build-static-content.js b/website/scripts/build-static-content.js
index ba6f82b2823..6f61634855f 100644
--- a/website/scripts/build-static-content.js
+++ b/website/scripts/build-static-content.js
@@ -166,7 +166,14 @@ module.exports = {
fallbackPageTitle = sails.helpers.strings.toSentenceCase(path.basename(pageSourcePath, path.extname(pageSourcePath)));
}
- // Determine URL for this page
+ // Determine URL for this page.
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Note: If this is an article page, then the rootRelativeUrlPath will be further modified below to
+ // also include the article's category: https://github.com/fleetdm/fleet/blob/9d2acb5751f4cebfb211ae1f15c9289143b5b79c/website/scripts/build-static-content.js#L441-L447
+ // > TODO: Try eliminating this exception by moving the processing of all page metadata upwards, so
+ // > that it occurs before this spot in the file, so that all URL-determining logic can happen here,
+ // > all in one place. (For more context, see https://github.com/fleetdm/confidential/issues/1537 )
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
let rootRelativeUrlPath = (
(
SECTION_INFOS_BY_SECTION_REPO_PATHS[sectionRepoPath].urlPrefix +
@@ -177,12 +184,6 @@ module.exports = {
).replace(RX_README_FILENAME, '')// « Interpret README files as special and map it to the URL representing its containing folder.
);
- // Assert uniqueness of URL paths.
- if (rootRelativeUrlPathsSeen.includes(rootRelativeUrlPath)) {
- throw new Error('Failed compiling markdown content: Files as currently named would result in colliding (duplicate) URLs for the website. To resolve, rename the pages whose names are too similar. Duplicate detected: ' + rootRelativeUrlPath);
- }//•
- rootRelativeUrlPathsSeen.push(rootRelativeUrlPath);
-
if (path.extname(pageSourcePath) !== '.md') {// If this file doesn't end in `.md`: skip it (we won't create a page for it)
// > Inspired by https://github.com/uncletammy/doc-templater/blob/2969726b598b39aa78648c5379e4d9503b65685e/lib/compile-markdown-tree-from-remote-git-repo.js#L275-L276
sails.log.verbose(`Skipping ${pageSourcePath}`);
@@ -197,7 +198,7 @@ module.exports = {
// >
// > For more info about how these additional features work, see: https://github.com/fleetdm/fleet/issues/706#issuecomment-884622252
// >
- // > • What about images referenced in markdown files? :: They need to be referenced using an absolute URL src-- e.g.  See also https://github.com/fleetdm/fleet/issues/706#issuecomment-884641081 for reasoning.
+ // > • What about images referenced in markdown files? :: For documentation and handbook files, they need to be referenced using an absolute URL of the src-- e.g. . For articles, you can use the absolute URL of the src - e.g.  OR the relative repo path e.g. . See also https://github.com/fleetdm/fleet/issues/706#issuecomment-884641081 for reasoning.
// > • What about GitHub-style emojis like `:white_check_mark:`? :: Use actual unicode emojis instead. Need to revisit this? Visit https://github.com/fleetdm/fleet/pull/1380/commits/19a6e5ffc70bf41569293db44100e976f3e2bda7 for more info.
let mdString = await sails.helpers.fs.read(pageSourcePath);
mdString = mdString.replace(/(```)([a-zA-Z0-9\-]*)(\s*\n)/g, '$1\n' + '' + '$3'); // « Based on the github-flavored markdown's language annotation, (e.g. ```js```) add a temporary marker to code blocks that can be parsed post-md-compilation when this is HTML. Note: This is an HTML comment because it is easy to over-match and "accidentally" add it underneath each code block as well (being an HTML comment ensures it doesn't show up or break anything). For more information, see https://github.com/uncletammy/doc-templater/blob/2969726b598b39aa78648c5379e4d9503b65685e/lib/compile-markdown-tree-from-remote-git-repo.js#L198-L202
@@ -359,7 +360,6 @@ module.exports = {
// If the page has a pageOrderInSection meta tag, we'll use that to sort pages in their bottom level sections.
let pageOrderInSection;
- // Add handbook pages to pageOrderInSection check, add pageOrderInSection meta tags to each handbook page.
if(sectionRepoPath === 'docs/') {
// Set a flag to determine if the page is a readme (e.g. /docs/Using-Fleet/configuration-files/readme.md) or a FAQ page.
// READMEs in subfolders and FAQ pages don't have pageOrderInSection values, they are always sorted at the end of sections.
@@ -404,16 +404,15 @@ module.exports = {
// Throwing an error if the article is missing a 'publishedOn' meta tag
throw new Error(`Failed compiling markdown content: An article page is missing a publishedOn meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, add a meta tag with the ISO formatted date the article was published on`);
}
- if(embeddedMetadata.category) {
+ if(!embeddedMetadata.category) {
+ // Throwing an error if the article is missing a category meta tag
+ throw new Error(`Failed compiling markdown content: An article page is missing a category meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, add a meta tag with the category of the article`);
+ } else {
// Throwing an error if the article has an invalid category.
- embeddedMetadata.category = embeddedMetadata.category.toLowerCase();
let validArticleCategories = ['deploy', 'security', 'engineering', 'success stories', 'announcements', 'guides', 'releases', 'podcasts', 'report' ];
if(!validArticleCategories.includes(embeddedMetadata.category)) {
throw new Error(`Failed compiling markdown content: An article page has an invalid category meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, change the meta tag to a valid category, one of: ${validArticleCategories}`);
}
- } else {
- // throwing an error if the article is missing a category meta tag
- throw new Error(`Failed compiling markdown content: An article page is missing a category meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, add a meta tag with the category of the article`);
}
if(embeddedMetadata.articleImageUrl) {
// Checking the value of `articleImageUrl` meta tags, and throwing an error if it is not a link to an image.
@@ -428,9 +427,8 @@ module.exports = {
if (isURL) {
if (!isExternal) { // If the image is hosted on fleetdm.com, we'll modify the meta value to reference the file directly in the `website/assets/` folder
embeddedMetadata.articleImageUrl = embeddedMetadata.articleImageUrl.replace(/https?:\/\//, '').replace(/^fleetdm\.com/, '');
- } else { // If the value is a link to an image that is not hosted on fleetdm.com, we won't modify it.
- // TODO: Enable this error once our Medium articles and their assets have been fully migrated.
- // throw new Error(`Failed compiling markdown content: An article page has an invalid a articleImageUrl meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, change the value of the meta tag to be an image that will be hosted on fleetdm.com`);
+ } else { // If the value is a link to an image that will not be hosted on fleetdm.com, we'll throw an error.
+ throw new Error(`Failed compiling markdown content: An article page has an invalid a articleImageUrl meta tag () at "${path.join(topLvlRepoPath, pageSourcePath)}". To resolve, change the value of the meta tag to be an image that will be hosted on fleetdm.com`);
}
} else if(inWebsiteAssetFolder) { // If the `articleImageUrl` value is a relative link to the `website/assets/` folder, we'll modify the value to link directly to that folder.
embeddedMetadata.articleImageUrl = embeddedMetadata.articleImageUrl.replace(/^\.\.\/website\/assets/g, '');
@@ -442,11 +440,17 @@ module.exports = {
// If the article is categorized as 'product' we'll replace the category with 'use-cases', or if it is categorized as 'success story' we'll replace it with 'device-management'
rootRelativeUrlPath = (
'/' +
- (embeddedMetadata.category === 'success stories' ? 'device-management' : embeddedMetadata.category === 'security' ? 'securing' : embeddedMetadata.category) + '/' +
+ (encodeURIComponent(embeddedMetadata.category === 'success stories' ? 'device-management' : embeddedMetadata.category === 'security' ? 'securing' : embeddedMetadata.category)) + '/' +
(pageUnextensionedLowercasedRelPath.split(/\//).map((fileOrFolderName) => encodeURIComponent(fileOrFolderName.replace(/^[0-9]+[\-]+/,''))).join('/'))
);
}
+ // Assert uniqueness of URL paths.
+ if (rootRelativeUrlPathsSeen.includes(rootRelativeUrlPath)) {
+ throw new Error('Failed compiling markdown content: Files as currently named would result in colliding (duplicate) URLs for the website. To resolve, rename the pages whose names are too similar. Duplicate detected: ' + rootRelativeUrlPath);
+ }//•
+ rootRelativeUrlPathsSeen.push(rootRelativeUrlPath);
+
// Determine unique HTML id
// > • This will become the filename of the resulting HTML.
let htmlId = (