11import { Primitives } from "@repo/common-data" ;
2+ import { escapeHTML } from "@repo/utils/std/string" ;
23
3- type Primitive = ReturnType < typeof Primitives . prototype . getPrimByName > | null ;
4+ type ParsedMarkdown = Awaited < ReturnType < typeof parseMarkdown > > ;
5+ type Primitive = ReturnType < typeof Primitives . prototype . getPrimByName > | null | undefined ;
6+ type ParsedPrimitive =
7+ | ( Omit < NonNullable < Primitive > , "description" | "examples" > & {
8+ description : ParsedMarkdown | null ;
9+ examples : ParsedMarkdown | null ;
10+ } )
11+ | undefined
12+ | null ;
413let primitives : Primitives | undefined = undefined ;
514
6- function convertRelativeMarkdownLinksToAbsolute ( markdown : string , baseUrl : string ) : string {
7- const markdownLinkRegex = / \[ ( [ ^ \] ] + ) \] \( ( [ ^ ) ] + ) \) / g;
8- const convertedMarkdown = markdown . replace ( markdownLinkRegex , ( match , text , url ) => {
9- if ( ! url . startsWith ( "http://" ) && ! url . startsWith ( "https://" ) ) {
10- const absoluteUrl = new URL ( url , baseUrl ) . href ;
11- return `[${ text } ](${ absoluteUrl } )` ;
12- }
13- return match ;
14- } ) ;
15-
16- return convertedMarkdown ;
17- }
18-
19- function parsePrimitive ( prim : Primitive ) : Primitive {
20- if ( ! prim ) return null ;
21- if ( prim . description ) {
22- prim . description = convertRelativeMarkdownLinksToAbsolute (
23- prim . description ,
24- "https://docs.netlogo.org/" ,
25- ) ;
26- }
27-
28- return prim ;
29- }
30-
31- export const usePrimitive = async ( { name } : { name : string } ) => {
15+ const usePrimitive = async ( { name } : { name : string } ) => {
3216 if ( import . meta. dev ) {
33- const { data } = await useAsyncData ( "primitives" , ( ) => queryCollection ( "primitives" ) . all ( ) , {
34- deep : false ,
35- server : true ,
36- dedupe : "defer" ,
37- } ) ;
38-
39- if ( data . value ) {
40- primitives = Primitives . getInstance ( data . value [ 0 ] ?. primitives ?? [ ] ) ;
41- }
42-
43- const prim = parsePrimitive ( primitives ?. getPrimByName ( name ) ) ;
44-
45- return {
46- primitive : computed ( ( ) => prim ) ,
47- pending : computed ( ( ) => typeof primitives === "undefined" && ! primitives ) ,
48- error : computed ( ( ) => null ) ,
49- } ;
17+ return usePrimitiveDev ( { name } ) ;
5018 }
5119
5220 const { data, pending, error } = await useAsyncData (
@@ -58,7 +26,7 @@ export const usePrimitive = async ({ name }: { name: string }) => {
5826 dedupe : "defer" ,
5927 transform : async ( allPrimitivesData ) => {
6028 const primitives = Primitives . getInstance ( allPrimitivesData [ 0 ] ?. primitives ?? [ ] ) ;
61- const prim = parsePrimitive ( primitives . getPrimByName ( name ) ) ;
29+ const prim = await parsePrimitive ( primitives . getPrimByName ( name ) ) ;
6230
6331 return prim ?? null ;
6432 } ,
@@ -77,10 +45,83 @@ export const usePrimitive = async ({ name }: { name: string }) => {
7745 } ;
7846} ;
7947
80- export const useNoPrimitive = ( ) => {
48+ const usePrimitiveDev = async ( { name } : { name : string } ) => {
49+ const { data } = await useAsyncData ( "primitives" , ( ) => queryCollection ( "primitives" ) . all ( ) , {
50+ deep : false ,
51+ server : true ,
52+ dedupe : "defer" ,
53+ } ) ;
54+
55+ if ( data . value ) {
56+ primitives = Primitives . getInstance ( data . value [ 0 ] ?. primitives ?? [ ] ) ;
57+ }
58+
59+ const prim = await parsePrimitive ( primitives ?. getPrimByName ( name ) ) ;
60+
61+ return {
62+ primitive : computed ( ( ) => prim ) ,
63+ pending : computed ( ( ) => typeof primitives === "undefined" && ! primitives ) ,
64+ error : computed ( ( ) => null ) ,
65+ } ;
66+ } ;
67+
68+ const useNoPrimitive = ( ) => {
8169 return {
8270 primitive : computed ( ( ) => null ) ,
8371 pending : computed ( ( ) => false ) ,
8472 error : computed ( ( ) => null ) ,
8573 } ;
8674} ;
75+
76+ // Utilities
77+ function convertRelativeMarkdownLinksToAbsolute ( markdown : string , baseUrl : string ) : string {
78+ const markdownLinkRegex = / \[ ( [ ^ \] ] + ) \] \( ( [ ^ ) ] + ) \) / g;
79+ const convertedMarkdown = markdown . replace ( markdownLinkRegex , ( match , text , url ) => {
80+ if ( ! url . startsWith ( "http://" ) && ! url . startsWith ( "https://" ) ) {
81+ const absoluteUrl = new URL ( url , baseUrl ) . href ;
82+ return `[${ text } ](${ absoluteUrl } )` ;
83+ }
84+ return match ;
85+ } ) ;
86+
87+ return convertedMarkdown ;
88+ }
89+
90+ async function parsePrimitive ( prim : Primitive ) : Promise < ParsedPrimitive | null > {
91+ if ( ! prim ) return null ;
92+ if ( prim . description ) {
93+ prim . description = convertRelativeMarkdownLinksToAbsolute (
94+ prim . description ,
95+ "https://docs.netlogo.org/" ,
96+ ) ;
97+ }
98+
99+ const [ parsedDescription , parsedExamples ] = await Promise . all ( [
100+ prim . description ? await parseMarkdown ( prim . description ) : null ,
101+ prim . examples ? await parseMarkdown ( buildExamples ( prim ) ) : null ,
102+ ] ) ;
103+
104+ return {
105+ ...prim ,
106+ description : parsedDescription ,
107+ examples : parsedExamples ,
108+ } ;
109+ }
110+
111+ function buildExamples ( primitive : Primitive | null ) : string {
112+ return `<h5 class="m-0">${
113+ primitive ?. examples
114+ ?. map (
115+ ( ex : string ) => `
116+ <span class="prim-example font-mono m-0 block [&_p]:m-0! [&_p]:font-bold">
117+
118+ ${ escapeHTML ( ex ) }
119+
120+ </span>
121+ ` ,
122+ )
123+ . join ( "" ) ?? ""
124+ } </h5>`;
125+ }
126+
127+ export { useNoPrimitive , usePrimitive } ;
0 commit comments