mirror of
				https://github.com/Xahau/xahau-web.git
				synced 2025-11-04 04:15:47 +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