mirror of
https://github.com/Xahau/xahau-web.git
synced 2025-12-06 17:27:53 +00:00
Add global link references
This commit is contained in:
@@ -6,6 +6,7 @@ import starlight from '@astrojs/starlight'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'astro/config'
|
||||
import starlightOpenAPI, { openAPISidebarGroups } from 'starlight-openapi'
|
||||
import { remarkGlobalReferences } from './src/plugins/remarkGlobalReferences'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
@@ -311,6 +312,9 @@ export default defineConfig({
|
||||
}),
|
||||
mdx(),
|
||||
],
|
||||
markdown: {
|
||||
remarkPlugins: [remarkGlobalReferences],
|
||||
},
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
|
||||
15
package-lock.json
generated
15
package-lock.json
generated
@@ -18,6 +18,7 @@
|
||||
"astro": "^5.10.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"remark-reference-links": "^7.0.0",
|
||||
"starlight-openapi": "^0.19.1",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"vanilla-cookieconsent": "^3.1.0"
|
||||
@@ -6421,6 +6422,20 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-reference-links": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/remark-reference-links/-/remark-reference-links-7.0.0.tgz",
|
||||
"integrity": "sha512-OMACEps7CkpBio5nutUToCcXFJr9QkkoHdku41iIholMdFZ0jdRxgFmPm2B7R+DSvW83ZShdA3ubWTH+C3M6Eg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-rehype": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"astro": "^5.10.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"remark-reference-links": "^7.0.0",
|
||||
"starlight-openapi": "^0.19.1",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"vanilla-cookieconsent": "^3.1.0"
|
||||
|
||||
2
src/content/references/global.md
Normal file
2
src/content/references/global.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<!-- Currently, remarkPlugins does not support HMR, so you will need to restart the dev server if you change this file. -->
|
||||
[Internal Type]: /docs/protocol-reference/binary-format
|
||||
129
src/plugins/remarkGlobalReferences.ts
Normal file
129
src/plugins/remarkGlobalReferences.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { visit } from 'unist-util-visit'
|
||||
|
||||
/**
|
||||
* Remark plugin to resolve reference-style links from global.md
|
||||
*/
|
||||
export function remarkGlobalReferences() {
|
||||
let globalRefs: Record<string, string> | null = null
|
||||
|
||||
function loadGlobalReferences() {
|
||||
if (globalRefs !== null) return globalRefs
|
||||
|
||||
try {
|
||||
const globalMdPath = join(
|
||||
process.cwd(),
|
||||
'src/content/references/global.md',
|
||||
)
|
||||
const content = readFileSync(globalMdPath, 'utf-8')
|
||||
|
||||
globalRefs = {}
|
||||
|
||||
// Parse reference-style link definitions: [label]: url
|
||||
const lines = content.split('\n')
|
||||
for (const line of lines) {
|
||||
const match = line.match(/^\[([^\]]+)\]:\s*(.+)$/)
|
||||
if (match) {
|
||||
const [, label, url] = match
|
||||
globalRefs[label] = url.trim()
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Loaded global references:', globalRefs)
|
||||
return globalRefs
|
||||
} catch (error: any) {
|
||||
console.warn('Could not load global.md references:', error.message)
|
||||
globalRefs = {}
|
||||
return globalRefs
|
||||
}
|
||||
}
|
||||
|
||||
return function transformer(tree: any) {
|
||||
const refs = loadGlobalReferences()
|
||||
|
||||
// Find all reference-style links in the format [text][]
|
||||
visit(tree, 'linkReference', (node) => {
|
||||
if (
|
||||
node.referenceType === 'shortcut' ||
|
||||
node.referenceType === 'collapsed'
|
||||
) {
|
||||
const label = node.label || node.children?.[0]?.value
|
||||
|
||||
if (label && refs[label]) {
|
||||
// Convert linkReference to a regular link
|
||||
node.type = 'link'
|
||||
node.url = refs[label]
|
||||
delete node.referenceType
|
||||
delete node.identifier
|
||||
delete node.label
|
||||
|
||||
console.log(`Resolved reference [${label}][] to ${refs[label]}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Also look for escaped reference-style links in text nodes: \[label]\[]
|
||||
visit(tree, 'text', (node, index, parent) => {
|
||||
if (!node.value) return
|
||||
|
||||
// Find escaped reference-style links: \[label]\[]
|
||||
const pattern = /\\?\[([^\]]+)\\?\]\\?\[\]/g
|
||||
const replacements = []
|
||||
let match: RegExpExecArray | null = null
|
||||
|
||||
match = pattern.exec(node.value)
|
||||
while (match !== null) {
|
||||
const [fullMatch, label] = match
|
||||
if (refs[label]) {
|
||||
replacements.push({
|
||||
start: match.index,
|
||||
end: match.index + fullMatch.length,
|
||||
label,
|
||||
url: refs[label],
|
||||
})
|
||||
console.log(`Found escaped reference ${fullMatch} -> ${refs[label]}`)
|
||||
}
|
||||
match = pattern.exec(node.value)
|
||||
}
|
||||
|
||||
// Apply replacements from right to left to maintain indices
|
||||
if (replacements.length > 0) {
|
||||
const newNodes = []
|
||||
let lastIndex = 0
|
||||
|
||||
for (const replacement of replacements) {
|
||||
// Add text before the replacement
|
||||
if (replacement.start > lastIndex) {
|
||||
newNodes.push({
|
||||
type: 'text',
|
||||
value: node.value.slice(lastIndex, replacement.start),
|
||||
})
|
||||
}
|
||||
|
||||
// Add the link
|
||||
newNodes.push({
|
||||
type: 'link',
|
||||
url: replacement.url,
|
||||
children: [{ type: 'text', value: replacement.label }],
|
||||
})
|
||||
|
||||
lastIndex = replacement.end
|
||||
}
|
||||
|
||||
// Add remaining text
|
||||
if (lastIndex < node.value.length) {
|
||||
newNodes.push({
|
||||
type: 'text',
|
||||
value: node.value.slice(lastIndex),
|
||||
})
|
||||
}
|
||||
|
||||
// Replace the current node with the new nodes
|
||||
if (parent && typeof index === 'number') {
|
||||
parent.children.splice(index, 1, ...newNodes)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user