microsoft/TypeAgent

Public

mirrored fromhttps://github.com/microsoft/TypeAgentAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
f46fff4e5103217703b51e27ba3f6405ac000e21

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

docs/scripts/update-links.js

153lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4// Normalizes file paths to use forward slashes consistently
5function normalizePath(filePath) {
6 return filePath ? filePath.replace(/\\/g, "/") : "";
7}
8
9/**
10 * Updates links in content to point to GitHub repository
11 * This relies on Eleventy's inputPath property to get the original Markdown path
12 *
13 * @param {string} content - The HTML content
14 * @param {string} outputPath - The output HTML file path
15 * @param {string} inputPath - The original Markdown file path
16 * @param {string} repoUrl - The GitHub repository URL
17 * @param {string} defaultBranch - The default branch name
18 * @return {string} Updated content
19 */
20function updateLinks(
21 content,
22 outputPath,
23 inputPath,
24 repoUrl,
25 defaultBranch = "main"
26) {
27 if (!repoUrl) {
28 repoUrl = "https://github.com/microsoft/TypeAgent";
29 }
30
31 // Normalize paths
32 const normalizedInputPath = normalizePath(inputPath);
33 const normalizedOutputPath = normalizePath(outputPath);
34
35 console.log(`Processing file: ${normalizedOutputPath}`);
36 console.log(`Original source: ${normalizedInputPath}`);
37
38 // Process HTML links
39 const externalLinkPattern =
40 /<a\s+(?:[^>]*?\s+)?href=["']([^"']+)["']([^>]*)>([^<]*)<\/a>/g;
41
42 return content.replace(
43 externalLinkPattern,
44 (match, linkPath, attributes, linkText) => {
45 // Normalize link path
46 const normalizedLinkPath = normalizePath(linkPath);
47
48 // Skip if the link is internal (starts with #), a web URL, or a site-relative path
49 if (
50 normalizedLinkPath.startsWith("#") ||
51 normalizedLinkPath.startsWith("http") ||
52 normalizedLinkPath.startsWith("/docs/") ||
53 normalizedLinkPath.startsWith("/content/")
54 ) {
55 return match;
56 }
57
58 // Skip image files
59 if (/\.(jpeg|jpg|gif|png|svg)$/.test(normalizedLinkPath)) {
60 return match;
61 }
62
63 // Only process links that likely point outside the docs directory
64 // This typically means they start with ../ or are a path without a leading /
65 if (
66 normalizedLinkPath.startsWith("../") ||
67 (!normalizedLinkPath.startsWith("/") &&
68 !normalizedLinkPath.startsWith("."))
69 ) {
70 try {
71 // Use the original Markdown file path for resolution
72 const repoPath = resolvePathFromMarkdown(
73 normalizedLinkPath,
74 normalizedInputPath
75 );
76
77 // Determine if this is a file or directory (assume directory if no extension)
78 const isDirectory = !repoPath.includes(".");
79
80 // Create the appropriate GitHub URL
81 const githubPath = isDirectory
82 ? `${repoUrl}/tree/${defaultBranch}/${repoPath}`
83 : `${repoUrl}/blob/${defaultBranch}/${repoPath}`;
84
85 console.log(
86 `Replacing link: ${normalizedLinkPath} with ${githubPath}`
87 );
88
89 // Return the updated link
90 return `<a href="${githubPath}"${attributes}>${linkText}</a>`;
91 } catch (err) {
92 console.error(
93 `Error processing link ${normalizedLinkPath}: ${err.message}`
94 );
95 return match;
96 }
97 }
98
99 return match;
100 }
101 );
102}
103
104/**
105 * Resolves a relative path from a Markdown file to its repository path
106 *
107 * @param {string} relativePath - The relative path in the link
108 * @param {string} markdownFilePath - The original Markdown file path
109 * @returns {string} The resolved path relative to the repository root
110 */
111function resolvePathFromMarkdown(relativePath, markdownFilePath) {
112 try {
113 const lastSlashIndex = markdownFilePath.lastIndexOf("/");
114 const markdownDir =
115 lastSlashIndex !== -1
116 ? markdownFilePath.substring(0, lastSlashIndex)
117 : "";
118
119 const markdownDirParts = markdownDir ? markdownDir.split("/") : [];
120 const relativePathParts = relativePath.split("/");
121
122 const resultParts = [...markdownDirParts];
123
124 // Process each part of the relative path
125 for (const part of relativePathParts) {
126 if (part === "..") {
127 // Go up one directory
128 if (resultParts.length > 0) {
129 resultParts.pop();
130 }
131 } else if (part !== ".") {
132 resultParts.push(part);
133 }
134 }
135
136 // Join the path
137 const resolvedPath = resultParts.join("/");
138
139 const docsIndex = resolvedPath.indexOf("/docs/");
140 if (docsIndex !== -1) {
141 // If the path contains /docs/, everything before that is the repo root
142 const repoRoot = resolvedPath.substring(0, docsIndex);
143 return resolvedPath.substring(repoRoot.length + 1); // +1 for the leading slash
144 }
145
146 return resolvedPath;
147 } catch (err) {
148 console.error(`Error resolving path: ${err.message}`);
149 return relativePath;
150 }
151}
152
153module.exports = { updateLinks, normalizePath, resolvePathFromMarkdown };
154