move type-link processing to build stage
This commit is contained in:
		
							parent
							
								
									ab2a9ca7ed
								
							
						
					
					
						commit
						6d353e0c6b
					
				
					 15 changed files with 161 additions and 300 deletions
				
			
		| 
						 | 
				
			
			@ -1,10 +1,9 @@
 | 
			
		|||
import { defineConfig } from "astro/config";
 | 
			
		||||
import solidJs from "@astrojs/solid-js";
 | 
			
		||||
import { remarkAlert } from "remark-github-blockquote-alert";
 | 
			
		||||
import sectionize from "@hbsnow/rehype-sectionize";
 | 
			
		||||
import mdx from "@astrojs/mdx";
 | 
			
		||||
 | 
			
		||||
import pagefind from "./pagefind";
 | 
			
		||||
import { markdownConfig } from "./src/config/io/markdown.ts";
 | 
			
		||||
 | 
			
		||||
// https://astro.build/config
 | 
			
		||||
export default defineConfig({
 | 
			
		||||
| 
						 | 
				
			
			@ -15,27 +14,5 @@ export default defineConfig({
 | 
			
		|||
    mdx(),
 | 
			
		||||
    pagefind(),
 | 
			
		||||
  ],
 | 
			
		||||
  markdown: {
 | 
			
		||||
    syntaxHighlight: "shiki",
 | 
			
		||||
    shikiConfig: {
 | 
			
		||||
      theme: "material-theme-ocean",
 | 
			
		||||
      wrap: true,
 | 
			
		||||
    },
 | 
			
		||||
    remarkPlugins: [
 | 
			
		||||
      [
 | 
			
		||||
        remarkAlert,
 | 
			
		||||
        {
 | 
			
		||||
          legacyTitle: true,
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    ],
 | 
			
		||||
    rehypePlugins: [
 | 
			
		||||
      [
 | 
			
		||||
        sectionize,
 | 
			
		||||
        {
 | 
			
		||||
          idPropertyName: "id",
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  markdown: markdownConfig,
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,28 +12,27 @@
 | 
			
		|||
  "dependencies": {
 | 
			
		||||
    "@ark-ui/solid": "^3.5.0",
 | 
			
		||||
    "@astrojs/check": "^0.9.3",
 | 
			
		||||
    "@astrojs/markdown-remark": "^5.1.0",
 | 
			
		||||
    "@astrojs/mdx": "^3.1.7",
 | 
			
		||||
    "@astrojs/solid-js": "^4.4.2",
 | 
			
		||||
    "@hbsnow/rehype-sectionize": "^1.0.7",
 | 
			
		||||
    "@pagefind/default-ui": "^1.1.1",
 | 
			
		||||
    "@types/node": "^20.14.11",
 | 
			
		||||
    "astro": "^4.15.9",
 | 
			
		||||
    "astro-breadcrumbs": "^2.3.1",
 | 
			
		||||
    "hast-util-from-html": "^2.0.3",
 | 
			
		||||
    "node": "npm:22.7.0",
 | 
			
		||||
    "rehype-stringify": "^10.0.1",
 | 
			
		||||
    "remark-github-blockquote-alert": "^1.2.1",
 | 
			
		||||
    "remark-parse": "^11.0.0",
 | 
			
		||||
    "remark-rehype": "^11.1.1",
 | 
			
		||||
    "solid-devtools": "^0.30.1",
 | 
			
		||||
    "solid-js": "^1.8.18",
 | 
			
		||||
    "typescript": "^5.5.3",
 | 
			
		||||
    "unified": "^11.0.5"
 | 
			
		||||
    "unified": "^11.0.5",
 | 
			
		||||
    "unist-util-visit": "^5.0.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@astrojs/ts-plugin": "^1.10.2",
 | 
			
		||||
    "@biomejs/biome": "^1.8.3",
 | 
			
		||||
    "@hbsnow/rehype-sectionize": "^1.0.7",
 | 
			
		||||
    "pagefind": "^1.1.1",
 | 
			
		||||
    "shiki": "^1.11.0"
 | 
			
		||||
    "pagefind": "^1.1.1"
 | 
			
		||||
  },
 | 
			
		||||
  "packageManager": "yarn@4.5.0"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,107 +0,0 @@
 | 
			
		|||
---
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
<script>
 | 
			
		||||
  const qtRegExp = /QT_(\w+)/g
 | 
			
		||||
  const qsRegExp = /QS_(\w+)/g
 | 
			
		||||
  setTimeout(() =>{
 | 
			
		||||
  const blocks = document.querySelectorAll("pre")
 | 
			
		||||
  if (blocks.length > 0) {
 | 
			
		||||
    blocks.forEach((block) => {
 | 
			
		||||
      const content = block.textContent
 | 
			
		||||
      const elements = block.querySelectorAll("span")
 | 
			
		||||
      const classElements:HTMLSpanElement[] = [];
 | 
			
		||||
      if (elements.length === 0) {
 | 
			
		||||
        console.log("NO SPAN ELEMENTS FOUND")
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      elements.forEach(element => {
 | 
			
		||||
        const isClassColored = element.style.cssText === "color: rgb(255, 203, 107);"
 | 
			
		||||
        const isSignal = element.innerText.trim().startsWith("on")
 | 
			
		||||
        const qualifier = isClassColored && !isSignal
 | 
			
		||||
 | 
			
		||||
        if (qualifier) {
 | 
			
		||||
          const dotSibling = element.nextSibling
 | 
			
		||||
          const isSplit = dotSibling?.textContent === "."
 | 
			
		||||
 | 
			
		||||
          if (isSplit) {
 | 
			
		||||
            let newInnerText = element.innerText + dotSibling.textContent + dotSibling.nextSibling?.textContent
 | 
			
		||||
 | 
			
		||||
            if (dotSibling.nextSibling) {
 | 
			
		||||
              dotSibling.nextSibling.textContent !== " {"
 | 
			
		||||
                ? dotSibling.nextSibling.remove()
 | 
			
		||||
                : null
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            dotSibling.remove()
 | 
			
		||||
            element.innerText = newInnerText
 | 
			
		||||
          }
 | 
			
		||||
          classElements.push(element)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (content) {
 | 
			
		||||
        const qtMatch = [...content.matchAll(qtRegExp)]
 | 
			
		||||
        const qsMatch = [...content.matchAll(qsRegExp)]
 | 
			
		||||
 | 
			
		||||
        if (qtMatch.length > 0) {
 | 
			
		||||
          for (const qtMatching of qtMatch) {
 | 
			
		||||
            const newATag = document.createElement("a")
 | 
			
		||||
            const qtBelongs = qtMatching[0].split("_")[1].replace("11", "-") || null
 | 
			
		||||
            const qtClass = qtMatching[1].split("_")[1]
 | 
			
		||||
            const link = `https://doc.qt.io/qt-6/qml-${qtBelongs ? `${qtBelongs}-${qtClass.toLowerCase()}` : "qtquick-" + qtClass.toLowerCase()}.html`
 | 
			
		||||
            newATag.target = "_blank"
 | 
			
		||||
            newATag.href = link
 | 
			
		||||
            newATag.innerText = qtClass
 | 
			
		||||
            const homeElement = classElements.find(item => {
 | 
			
		||||
              const spacing = item.innerText.replace(qtMatching[0], "")
 | 
			
		||||
              if (item.innerText.trim() === qtMatching[0].trim()){
 | 
			
		||||
                newATag.innerText = spacing + qtClass
 | 
			
		||||
                return true
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
            if (homeElement) {
 | 
			
		||||
              homeElement.innerText = ""
 | 
			
		||||
              homeElement.appendChild(newATag)
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (qsMatch.length > 0) {
 | 
			
		||||
          for (const qsMatching of qsMatch) {
 | 
			
		||||
            const newATag = document.createElement("a")
 | 
			
		||||
 | 
			
		||||
            const qsBelongs = qsMatching[0].split("_")[1].replace("00", ".") || null
 | 
			
		||||
            const qsClass = qsMatching[1].split("_")[1]
 | 
			
		||||
 | 
			
		||||
            const link = `/docs/types/${qsBelongs ? `${qsBelongs}/${qsClass}` : qsClass}`
 | 
			
		||||
            newATag.target = "_blank"
 | 
			
		||||
            newATag.href = link
 | 
			
		||||
 | 
			
		||||
            const homeElement = classElements.find(item => {
 | 
			
		||||
              const existingItem = item.innerText.trim()
 | 
			
		||||
              const matchingItem = qsMatching[0].trim()
 | 
			
		||||
              const spacing = item.innerText.replace(existingItem, "")
 | 
			
		||||
 | 
			
		||||
              if (existingItem === matchingItem) {
 | 
			
		||||
                newATag.innerText = spacing + qsClass
 | 
			
		||||
                return true
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
            if (homeElement) {
 | 
			
		||||
              homeElement.innerText = ""
 | 
			
		||||
 | 
			
		||||
              if (homeElement.nextSibling) {
 | 
			
		||||
                homeElement.nextSibling.textContent !== " {"
 | 
			
		||||
                  ? homeElement.nextSibling.textContent = ""
 | 
			
		||||
                  : null
 | 
			
		||||
              }
 | 
			
		||||
              homeElement.appendChild(newATag)
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  },3000)
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
---
 | 
			
		||||
---
 | 
			
		||||
<script>
 | 
			
		||||
  import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from "@config/io/helpers"
 | 
			
		||||
 | 
			
		||||
  const detailsData = document.getElementsByTagName("p")
 | 
			
		||||
  const innerItems = document.getElementsByClassName("typedata-details")
 | 
			
		||||
  if (detailsData) {
 | 
			
		||||
    for (const details of detailsData) {
 | 
			
		||||
      const linkRegex = /TYPE99(\w+.)99TYPE/g
 | 
			
		||||
      const mtypeExists = details.textContent?.match(linkRegex)
 | 
			
		||||
 | 
			
		||||
      if (!mtypeExists || !details.textContent) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const linkMatch = [...details.textContent.matchAll(linkRegex)]
 | 
			
		||||
      let textWithLinks = details.textContent;
 | 
			
		||||
      for (const matching of linkMatch) {
 | 
			
		||||
        if (details.textContent.indexOf(matching[0]) === -1){
 | 
			
		||||
          continue
 | 
			
		||||
        }
 | 
			
		||||
        const linkObject = getQMLTypeLinkObject(matching[1]);
 | 
			
		||||
        const link = getQMLTypeLink(linkObject);
 | 
			
		||||
        const icon = linkObject.mtype ? getIconForLink(linkObject.mtype, false) : null;
 | 
			
		||||
 | 
			
		||||
        // for signal
 | 
			
		||||
        const bracketString = getIconForLink("func", false)
 | 
			
		||||
 | 
			
		||||
        const newLink = `<span class="type${linkObject.mtype}-link typedata-link">${icon ? icon : ""}<a href=${link}>${linkObject.mname || linkObject.name}</a>${linkObject.mtype === "signal" ? bracketString : ""}</span>`;
 | 
			
		||||
        textWithLinks = textWithLinks.replace(matching[0], newLink)
 | 
			
		||||
      }
 | 
			
		||||
      details.innerHTML = textWithLinks
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (innerItems){
 | 
			
		||||
    for (const innerItem of innerItems){
 | 
			
		||||
      const linkRegex = /TYPE99(\w+.)99TYPE/g
 | 
			
		||||
      const listItems = innerItem.getElementsByTagName("li")
 | 
			
		||||
 | 
			
		||||
      for (const li of listItems){
 | 
			
		||||
        const mtypeExists = li.textContent?.match(linkRegex)
 | 
			
		||||
        if (!mtypeExists || !li.textContent){
 | 
			
		||||
          continue
 | 
			
		||||
        }
 | 
			
		||||
        const linkMatch = [...li.textContent.matchAll(linkRegex)]
 | 
			
		||||
        let textWithLinks = li.textContent;
 | 
			
		||||
        for (const matching of linkMatch) {
 | 
			
		||||
          if (li.textContent.indexOf(matching[0]) === -1){
 | 
			
		||||
            continue
 | 
			
		||||
          }
 | 
			
		||||
          const linkObject = getQMLTypeLinkObject(matching[1]);
 | 
			
		||||
          const link = getQMLTypeLink(linkObject);
 | 
			
		||||
          const icon = linkObject.mtype ? getIconForLink(linkObject.mtype, false) : null;
 | 
			
		||||
 | 
			
		||||
          // for signal
 | 
			
		||||
          const bracketString = getIconForLink("func", false)
 | 
			
		||||
 | 
			
		||||
          const newLink = `<span class="type${linkObject.mtype}-link typedata-link">${icon ? icon : ""}<a href=${link}>${linkObject.mname || linkObject.name}</a>${linkObject.mtype === "signal" ? bracketString : ""}</span>`;
 | 
			
		||||
          textWithLinks = textWithLinks.replace(matching[0], newLink)
 | 
			
		||||
        }
 | 
			
		||||
        li.innerHTML = textWithLinks
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,21 +0,0 @@
 | 
			
		|||
---
 | 
			
		||||
---
 | 
			
		||||
<script>
 | 
			
		||||
  import { codeToHtml } from "shiki";
 | 
			
		||||
  const injectedMd = document.getElementById("injectedMd");
 | 
			
		||||
  if (injectedMd) {
 | 
			
		||||
    const preElements = document.getElementsByTagName("pre");
 | 
			
		||||
    for (const pre of preElements) {
 | 
			
		||||
      if (pre.textContent){
 | 
			
		||||
        const innerText = pre.innerText;
 | 
			
		||||
        pre.outerHTML =
 | 
			
		||||
          await codeToHtml(
 | 
			
		||||
            innerText,
 | 
			
		||||
            {
 | 
			
		||||
              lang: "qml", "theme":"material-theme-ocean"
 | 
			
		||||
            }
 | 
			
		||||
          );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -3,18 +3,15 @@ import type {
 | 
			
		|||
  QMLTypeLinkObject,
 | 
			
		||||
  QuickshellFunction,
 | 
			
		||||
} from "@config/io/types";
 | 
			
		||||
import {
 | 
			
		||||
  parseMarkdown,
 | 
			
		||||
  getQMLTypeLink,
 | 
			
		||||
} from "@config/io/helpers";
 | 
			
		||||
import { getQMLTypeLink } from "@config/io/helpers";
 | 
			
		||||
import { Tag } from "@icons";
 | 
			
		||||
import TypeDetails from "./TypeDetails.astro"
 | 
			
		||||
 | 
			
		||||
export interface Props {
 | 
			
		||||
  funcData: QuickshellFunction[];
 | 
			
		||||
  title: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { funcData, title } = Astro.props;
 | 
			
		||||
const { funcData } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
<ul class="typedata typefuncs">
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -51,9 +48,7 @@ const { funcData, title } = Astro.props;
 | 
			
		|||
            )
 | 
			
		||||
            :null
 | 
			
		||||
          }
 | 
			
		||||
          <section class="typedata-details">
 | 
			
		||||
            <div class="typedata-detailsdata" set:html={parseMarkdown(item.details, title)}/>
 | 
			
		||||
          </section>
 | 
			
		||||
          <TypeDetails markdown={item.details} />
 | 
			
		||||
        </li>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,19 @@
 | 
			
		|||
---
 | 
			
		||||
import {
 | 
			
		||||
  parseMarkdown,
 | 
			
		||||
  getQMLTypeLink,
 | 
			
		||||
} from "@config/io/helpers";
 | 
			
		||||
import { getQMLTypeLink } from "@config/io/helpers";
 | 
			
		||||
import type {
 | 
			
		||||
  QMLTypeLinkObject,
 | 
			
		||||
  QuickshellProps,
 | 
			
		||||
} from "@config/io/types";
 | 
			
		||||
import { Tag, Flag } from "@icons";
 | 
			
		||||
 | 
			
		||||
import TypeDetails from "./TypeDetails.astro"
 | 
			
		||||
 | 
			
		||||
export interface Props {
 | 
			
		||||
  propsKeys: string[];
 | 
			
		||||
  propsData: QuickshellProps;
 | 
			
		||||
  title: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { propsKeys, propsData, title } = Astro.props;
 | 
			
		||||
const { propsKeys, propsData } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
<ul class="typedata typeprops">
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,9 +71,7 @@ const { propsKeys, propsData, title } = Astro.props;
 | 
			
		|||
              </p>
 | 
			
		||||
            ):null
 | 
			
		||||
          }
 | 
			
		||||
          <section class="typedata-details">
 | 
			
		||||
            <div id="injectedMd" class="typedata-detailsdata" set:html={parseMarkdown(propData.details, title)} />
 | 
			
		||||
          </section>
 | 
			
		||||
          <TypeDetails markdown={propData.details} />
 | 
			
		||||
        </li>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,14 @@
 | 
			
		|||
---
 | 
			
		||||
import type { QuickshellSignal } from "@config/io/types";
 | 
			
		||||
import { Tag, PowerCord } from "@icons";
 | 
			
		||||
import { parseMarkdown } from "@config/io/helpers";
 | 
			
		||||
import TypeDetails from "./TypeDetails.astro";
 | 
			
		||||
 | 
			
		||||
export interface Props {
 | 
			
		||||
  signalKeys: string[];
 | 
			
		||||
  signalsData: QuickshellSignal;
 | 
			
		||||
  title: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { signalKeys, signalsData, title } = Astro.props;
 | 
			
		||||
const { signalKeys, signalsData } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
<ul class="typedata typesignals">
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -44,9 +43,7 @@ const { signalKeys, signalsData, title } = Astro.props;
 | 
			
		|||
              </p>
 | 
			
		||||
            ) : null
 | 
			
		||||
          }
 | 
			
		||||
          <section class="typedata-details">
 | 
			
		||||
            <div class="typedata-detailsdata" set:html={parseMarkdown(signalData.details, title)} />
 | 
			
		||||
          </section>
 | 
			
		||||
          <TypeDetails markdown={signalData.details} />
 | 
			
		||||
        </li>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								src/components/type/TypeDetails.astro
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/components/type/TypeDetails.astro
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
---
 | 
			
		||||
import { processQsMarkdown } from "@config/io/helpers"
 | 
			
		||||
 | 
			
		||||
export interface Props {
 | 
			
		||||
  markdown?: string,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { markdown } = Astro.props;
 | 
			
		||||
 | 
			
		||||
const html = markdown ? await processQsMarkdown(markdown) : null;
 | 
			
		||||
---
 | 
			
		||||
<section class="typedata-details">
 | 
			
		||||
  {html ? <div class="typedata-detailsdata" set:html={html} /> : <em>No details provided</em>}
 | 
			
		||||
</section>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,14 @@
 | 
			
		|||
---
 | 
			
		||||
import type { QuickshellVariant } from "@config/io/types";
 | 
			
		||||
import { FourDiamonds } from "../icons";
 | 
			
		||||
import { parseMarkdown } from "@src/config/io/helpers";
 | 
			
		||||
import TypeDetails from "./TypeDetails.astro";
 | 
			
		||||
 | 
			
		||||
export interface Props {
 | 
			
		||||
  variantKeys: string[];
 | 
			
		||||
  variantsData: QuickshellVariant;
 | 
			
		||||
  title: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { variantKeys, variantsData, title } = Astro.props;
 | 
			
		||||
const { variantKeys, variantsData } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
<ul class="typedata typevariants">
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,9 +33,7 @@ const { variantKeys, variantsData, title } = Astro.props;
 | 
			
		|||
            )
 | 
			
		||||
            :null
 | 
			
		||||
          }
 | 
			
		||||
          <section class="typedata-details">
 | 
			
		||||
            <div class="typedata-detailsdata" set:html={parseMarkdown(variantData.details, title)} />
 | 
			
		||||
          </section>
 | 
			
		||||
          <TypeDetails markdown={variantData.details} />
 | 
			
		||||
        </li>
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,4 @@
 | 
			
		|||
import { unified } from "unified";
 | 
			
		||||
import remarkParse from "remark-parse";
 | 
			
		||||
import remarkRehype from "remark-rehype";
 | 
			
		||||
import rehypeStringify from "rehype-stringify";
 | 
			
		||||
import { remarkAlert } from "remark-github-blockquote-alert";
 | 
			
		||||
import * as markdownUtils from "./markdown.ts";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  //  Flag,
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +6,8 @@ import {
 | 
			
		|||
  Tag,
 | 
			
		||||
  FourDiamonds,
 | 
			
		||||
  RoundBrackets,
 | 
			
		||||
} from "@icons";
 | 
			
		||||
  // @icons breaks when imported indirectly from astro.config.mjs
 | 
			
		||||
} from "../../components/icons.tsx";
 | 
			
		||||
import type {
 | 
			
		||||
  ConfigHeading,
 | 
			
		||||
  ConfigTOC,
 | 
			
		||||
| 
						 | 
				
			
			@ -78,21 +75,8 @@ export function groupRoutes(routes: RouteData[]): GroupedRoutes {
 | 
			
		|||
  }, defaultValue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function parseMarkdown(text?: string, title?: string) {
 | 
			
		||||
  if (!text) {
 | 
			
		||||
		return unified()
 | 
			
		||||
			.use(remarkParse)
 | 
			
		||||
			.use(remarkRehype)
 | 
			
		||||
			.use(rehypeStringify)
 | 
			
		||||
			.process(title);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
	return unified()
 | 
			
		||||
		.use(remarkParse)
 | 
			
		||||
		.use(remarkAlert)
 | 
			
		||||
		.use(remarkRehype)
 | 
			
		||||
		.use(rehypeStringify)
 | 
			
		||||
		.process(text);
 | 
			
		||||
export async function processQsMarkdown(markdown: string): Promise<string> {
 | 
			
		||||
  return await markdownUtils.processMarkdown(markdown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getQMLTypeLinkObject(unparsed: string) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										108
									
								
								src/config/io/markdown.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/config/io/markdown.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
import type { Transformer } from "unified";
 | 
			
		||||
import type { Node, Parent } from "unist";
 | 
			
		||||
import { visit, CONTINUE, SKIP } from "unist-util-visit";
 | 
			
		||||
import { fromHtml } from "hast-util-from-html";
 | 
			
		||||
 | 
			
		||||
import type { AstroMarkdownOptions, MarkdownProcessor } from "@astrojs/markdown-remark";
 | 
			
		||||
import { createMarkdownProcessor } from "@astrojs/markdown-remark";
 | 
			
		||||
 | 
			
		||||
import { remarkAlert } from "remark-github-blockquote-alert";
 | 
			
		||||
import sectionize from "@hbsnow/rehype-sectionize";
 | 
			
		||||
 | 
			
		||||
import { getQMLTypeLinkObject, getQMLTypeLink, getIconForLink } from "./helpers.ts"
 | 
			
		||||
 | 
			
		||||
// couldn't find the actual type to use
 | 
			
		||||
type HtmlNode = Node & {
 | 
			
		||||
  value: string,
 | 
			
		||||
  type: string,
 | 
			
		||||
  tagName: string,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function rehypeRewriteTypelinks(): Transformer {
 | 
			
		||||
  return function (root: Node): Node {
 | 
			
		||||
    // @ts-ignore: does not appear to be a way to give this a correct type, it works for the one with a test below
 | 
			
		||||
    visit(root, (node: HtmlNode, index: number, parent: Parent) => {
 | 
			
		||||
      if (node.type == "element" && node.tagName == "pre") return SKIP;
 | 
			
		||||
 | 
			
		||||
      if (node.type == "text") {
 | 
			
		||||
        let changed = false;
 | 
			
		||||
 | 
			
		||||
        node.value = node.value.replace(/TYPE99(\w+.)99TYPE/g, (_full: string, match: string) => {
 | 
			
		||||
          changed = true;
 | 
			
		||||
 | 
			
		||||
          const linkObject = getQMLTypeLinkObject(match);
 | 
			
		||||
          const link = getQMLTypeLink(linkObject);
 | 
			
		||||
          const icon = (linkObject.mtype && linkObject.mtype != "func") ? getIconForLink(linkObject.mtype, false) : null;
 | 
			
		||||
          const hasParens = linkObject.mtype == "func" || linkObject.mtype == "signal";
 | 
			
		||||
          const hasDot = linkObject.name && linkObject.mname;
 | 
			
		||||
 | 
			
		||||
          return `<a class="type${linkObject.mtype}-link typedata-link" href=${link}>${icon ?? ""}${linkObject.name ?? ""}${hasDot ? "." : ""}${linkObject.mname ?? ""}${hasParens ? "()" : ""}</a>`;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (changed) {
 | 
			
		||||
          const fragment = fromHtml(node.value, { fragment: true });
 | 
			
		||||
          parent.children.splice(index, 1, ...fragment.children);
 | 
			
		||||
          return SKIP;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return CONTINUE;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return root;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const shikiRewriteTypelinks = {
 | 
			
		||||
  code: (root: Node) => {
 | 
			
		||||
    visit(root, "text", (node: HtmlNode, index: number, parent: Parent) => {
 | 
			
		||||
      let changed = false;
 | 
			
		||||
 | 
			
		||||
      node.value = node.value.replace(/TYPE99(\w+.)99TYPE/g, (_full: string, match: string) => {
 | 
			
		||||
        changed = true;
 | 
			
		||||
 | 
			
		||||
        const linkObject = getQMLTypeLinkObject(match);
 | 
			
		||||
        const link = getQMLTypeLink(linkObject);
 | 
			
		||||
 | 
			
		||||
        return `<a href=${link}>${linkObject.name ?? ""}</a>`;
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (changed) {
 | 
			
		||||
        const fragment = fromHtml(node.value, { fragment: true });
 | 
			
		||||
        parent.children.splice(index, 1, ...fragment.children);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const markdownConfig: AstroMarkdownOptions = {
 | 
			
		||||
  syntaxHighlight: "shiki",
 | 
			
		||||
  shikiConfig: {
 | 
			
		||||
    theme: "material-theme-ocean",
 | 
			
		||||
    wrap: true,
 | 
			
		||||
    transformers: [ shikiRewriteTypelinks ],
 | 
			
		||||
  },
 | 
			
		||||
  remarkPlugins: [[
 | 
			
		||||
    remarkAlert,
 | 
			
		||||
    { legacyTitle: true },
 | 
			
		||||
  ]],
 | 
			
		||||
  rehypePlugins: [
 | 
			
		||||
    [ sectionize, { idPropertyName: "id" } ],
 | 
			
		||||
    // @ts-ignore: can't tell what this wants
 | 
			
		||||
    [ rehypeRewriteTypelinks, {} ],
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let globalMarkdownProcessor: Promise<MarkdownProcessor>;
 | 
			
		||||
 | 
			
		||||
async function getMarkdownProcessor(): Promise<MarkdownProcessor> {
 | 
			
		||||
  if (!globalMarkdownProcessor) {
 | 
			
		||||
    globalMarkdownProcessor = createMarkdownProcessor(markdownConfig);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return globalMarkdownProcessor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function processMarkdown(markdown: string): Promise<string> {
 | 
			
		||||
  return (await (await getMarkdownProcessor()).render(markdown)).code;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ import PreTheme from "@config/PreTheme.astro";
 | 
			
		|||
import Header from "@components/Header.astro";
 | 
			
		||||
import Head from "@config/Head.astro";
 | 
			
		||||
import Nav from "@components/navigation/sidebars/Nav.astro";
 | 
			
		||||
import CreateQMLCodeButtons from "@components/hooks/CreateQMLCodeButtons.astro";
 | 
			
		||||
import "@styles/global.css";
 | 
			
		||||
import type { ConfigHeading } from "@src/components/navigation/sidebars/types";
 | 
			
		||||
import Footer from "@src/components/Footer.astro";
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +62,6 @@ if (url[2]) {
 | 
			
		|||
    <link rel="canonical" href={Astro.url} />
 | 
			
		||||
    <PreTheme />
 | 
			
		||||
    <CreateCopyButtons />
 | 
			
		||||
    <CreateQMLCodeButtons/>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body class="docslayout">
 | 
			
		||||
    <Header headings={headings}/>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
---
 | 
			
		||||
import {
 | 
			
		||||
  parseMarkdown,
 | 
			
		||||
  processQsMarkdown,
 | 
			
		||||
  getQMLTypeLink,
 | 
			
		||||
} from "@config/io/helpers";
 | 
			
		||||
import { generateTypeData } from "@config/io/generateTypeData";
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +11,6 @@ import Properties from "@components/type/Properties.astro";
 | 
			
		|||
import Functions from "@components/type/Functions.astro";
 | 
			
		||||
import Signals from "@components/type/Signals.astro";
 | 
			
		||||
import Variants from "@components/type/Variants.astro";
 | 
			
		||||
import TransformMDCodeblocks from "@components/hooks/TransformMDCodeblocks.astro";
 | 
			
		||||
import TransformLinks from "@components/hooks/TransformLinks.astro";
 | 
			
		||||
 | 
			
		||||
export async function getStaticPaths() {
 | 
			
		||||
  const routes = await generateTypeData();
 | 
			
		||||
| 
						 | 
				
			
			@ -51,11 +49,8 @@ const sidebarData = {
 | 
			
		|||
 | 
			
		||||
const superLink = data.super ? getQMLTypeLink(data.super) : null;
 | 
			
		||||
 | 
			
		||||
const details = parseMarkdown(data.details, route.name);
 | 
			
		||||
const details = data.details ? await processQsMarkdown(data.details) : null;
 | 
			
		||||
---
 | 
			
		||||
<TransformLinks/>
 | 
			
		||||
<TransformMDCodeblocks/>
 | 
			
		||||
 | 
			
		||||
<DocsLayout title={`${route.name} - ${route.type}`} description={data?.description ?? ""}>
 | 
			
		||||
  <div class="docs">
 | 
			
		||||
    <div class="typedocs-content">
 | 
			
		||||
| 
						 | 
				
			
			@ -87,34 +82,30 @@ const details = parseMarkdown(data.details, route.name);
 | 
			
		|||
                  </span>
 | 
			
		||||
                ))}</div>
 | 
			
		||||
              ):null}
 | 
			
		||||
              <span id="injectedMd" set:html={details}/>
 | 
			
		||||
              {details ? <span set:html={details}/> : null}
 | 
			
		||||
              {!details ? (<span class="toparse">{data.description}</span>):null}
 | 
			
		||||
            </subheading>
 | 
			
		||||
            { data.properties && propsKeys ? (
 | 
			
		||||
              <Properties
 | 
			
		||||
                propsData={data.properties}
 | 
			
		||||
                propsKeys={propsKeys!}
 | 
			
		||||
                title={route.name}
 | 
			
		||||
              />
 | 
			
		||||
            ): null}
 | 
			
		||||
            { data.functions && data.functions.length > 0 ? (
 | 
			
		||||
              <Functions
 | 
			
		||||
                funcData={data.functions}
 | 
			
		||||
                title={route.name}
 | 
			
		||||
              />
 | 
			
		||||
            ): null}
 | 
			
		||||
            { data.signals && signalKeys ? (
 | 
			
		||||
              <Signals
 | 
			
		||||
                signalsData={data.signals}
 | 
			
		||||
                signalKeys={signalKeys}
 | 
			
		||||
                title={route.name}
 | 
			
		||||
              />
 | 
			
		||||
            ):null}
 | 
			
		||||
            { data.variants && variantKeys ? (
 | 
			
		||||
              <Variants
 | 
			
		||||
                variantsData={data.variants}
 | 
			
		||||
                variantKeys={variantKeys}
 | 
			
		||||
                title={route.name}
 | 
			
		||||
              />
 | 
			
		||||
            ):null}
 | 
			
		||||
          </section>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								yarn.lock
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								yarn.lock
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -138,7 +138,7 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"@astrojs/markdown-remark@npm:5.2.0":
 | 
			
		||||
"@astrojs/markdown-remark@npm:5.2.0, @astrojs/markdown-remark@npm:^5.1.0":
 | 
			
		||||
  version: 5.2.0
 | 
			
		||||
  resolution: "@astrojs/markdown-remark@npm:5.2.0"
 | 
			
		||||
  dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -4081,7 +4081,7 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"hast-util-from-html@npm:^2.0.0, hast-util-from-html@npm:^2.0.1":
 | 
			
		||||
"hast-util-from-html@npm:^2.0.0, hast-util-from-html@npm:^2.0.1, hast-util-from-html@npm:^2.0.3":
 | 
			
		||||
  version: 2.0.3
 | 
			
		||||
  resolution: "hast-util-from-html@npm:2.0.3"
 | 
			
		||||
  dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -6302,6 +6302,7 @@ __metadata:
 | 
			
		|||
  dependencies:
 | 
			
		||||
    "@ark-ui/solid": "npm:^3.5.0"
 | 
			
		||||
    "@astrojs/check": "npm:^0.9.3"
 | 
			
		||||
    "@astrojs/markdown-remark": "npm:^5.1.0"
 | 
			
		||||
    "@astrojs/mdx": "npm:^3.1.7"
 | 
			
		||||
    "@astrojs/solid-js": "npm:^4.4.2"
 | 
			
		||||
    "@astrojs/ts-plugin": "npm:^1.10.2"
 | 
			
		||||
| 
						 | 
				
			
			@ -6311,17 +6312,15 @@ __metadata:
 | 
			
		|||
    "@types/node": "npm:^20.14.11"
 | 
			
		||||
    astro: "npm:^4.15.9"
 | 
			
		||||
    astro-breadcrumbs: "npm:^2.3.1"
 | 
			
		||||
    hast-util-from-html: "npm:^2.0.3"
 | 
			
		||||
    node: "npm:22.7.0"
 | 
			
		||||
    pagefind: "npm:^1.1.1"
 | 
			
		||||
    rehype-stringify: "npm:^10.0.1"
 | 
			
		||||
    remark-github-blockquote-alert: "npm:^1.2.1"
 | 
			
		||||
    remark-parse: "npm:^11.0.0"
 | 
			
		||||
    remark-rehype: "npm:^11.1.1"
 | 
			
		||||
    shiki: "npm:^1.11.0"
 | 
			
		||||
    solid-devtools: "npm:^0.30.1"
 | 
			
		||||
    solid-js: "npm:^1.8.18"
 | 
			
		||||
    typescript: "npm:^5.5.3"
 | 
			
		||||
    unified: "npm:^11.0.5"
 | 
			
		||||
    unist-util-visit: "npm:^5.0.0"
 | 
			
		||||
  languageName: unknown
 | 
			
		||||
  linkType: soft
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6382,7 +6381,7 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"rehype-stringify@npm:^10.0.0, rehype-stringify@npm:^10.0.1":
 | 
			
		||||
"rehype-stringify@npm:^10.0.0":
 | 
			
		||||
  version: 10.0.1
 | 
			
		||||
  resolution: "rehype-stringify@npm:10.0.1"
 | 
			
		||||
  dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -6473,7 +6472,7 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"remark-rehype@npm:^11.0.0, remark-rehype@npm:^11.1.0, remark-rehype@npm:^11.1.1":
 | 
			
		||||
"remark-rehype@npm:^11.0.0, remark-rehype@npm:^11.1.0":
 | 
			
		||||
  version: 11.1.1
 | 
			
		||||
  resolution: "remark-rehype@npm:11.1.1"
 | 
			
		||||
  dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -6830,7 +6829,7 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"shiki@npm:^1.10.3, shiki@npm:^1.11.0, shiki@npm:^1.16.2":
 | 
			
		||||
"shiki@npm:^1.10.3, shiki@npm:^1.16.2":
 | 
			
		||||
  version: 1.20.0
 | 
			
		||||
  resolution: "shiki@npm:1.20.0"
 | 
			
		||||
  dependencies:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue