1+ import hljs from "highlight.js"
12import yaml from "js-yaml"
2- import { marked } from "marked"
3+ import { Marked } from "marked"
4+ import { markedHighlight } from "marked-highlight"
5+ import "highlight.js/styles/atom-one-dark.css"
36
47export interface Doc {
58 title : string
@@ -9,10 +12,45 @@ export interface Doc {
912 content : string
1013 md : {
1114 html : string
12- tableOfContent : [ ]
15+ tableOfContent : { id : string , content : string } [ ]
1316 }
1417}
1518
19+ const marked = new Marked (
20+ markedHighlight ( {
21+ emptyLangClass : "hljs" ,
22+ langPrefix : "hljs language-" ,
23+ highlight ( code , lang ) {
24+ const language = hljs . getLanguage ( lang ) ? lang : "plaintext"
25+ return hljs . highlight ( code , { language } ) . value
26+ } ,
27+ } ) ,
28+ )
29+
30+ const renderer = new marked . Renderer ( )
31+
32+ renderer . code = function ( { text } ) {
33+ const parts = text . split ( "\n" )
34+ const count = parts . length
35+ const size = 29 + count . toString ( ) . length * 15
36+ const lines = parts . map ( ( _ , i ) => `<span class="text-accent">${ i + 1 } </span>` )
37+
38+ return `
39+ <pre
40+ class="my-6 border rounded d-flex"
41+ style="--v-border-color: 255, 255, 255; --v-border-opacity: 0.12"
42+ >
43+ <code class="py-4 d-inline-block border-e bg-surface text-center" style="width: ${ size } px;">${ lines . join ( "\n" ) } </code>
44+ <code class="hljs bg-surface" style="width: calc(100% - ${ size } px);">${ parts . join ( "\n" ) } </code>
45+ </pre>
46+ `
47+ }
48+
49+ renderer . blockquote = function ( { tokens } ) {
50+ const content = this . parser . parse ( tokens )
51+ return `<blockquote class="my-6 px-6 pa-4 border-s-lg border-primary rounded" style="--v-border-opacity: 1; background: rgba(var(--v-theme-primary), 0.12);">${ content } </blockquote>`
52+ }
53+
1654export const useDocs = createGlobalState ( ( ) => {
1755 // const router = useRouter()
1856
@@ -26,31 +64,45 @@ export const useDocs = createGlobalState(() => {
2664 . then ( res => res . text ( ) ) ) ,
2765 )
2866
29- const renderer = new marked . Renderer ( )
67+ let tableOfContent : Doc [ "md" ] [ "tableOfContent" ] = [ ]
3068
69+ const linkIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M10.59 13.41c.41.39.41 1.03 0 1.42c-.39.39-1.03.39-1.42 0a5.003 5.003 0 0 1 0-7.07l3.54-3.54a5.003 5.003 0 0 1 7.07 0a5.003 5.003 0 0 1 0 7.07l-1.49 1.49c.01-.82-.12-1.64-.4-2.42l.47-.48a2.98 2.98 0 0 0 0-4.24a2.98 2.98 0 0 0-4.24 0l-3.53 3.53a2.98 2.98 0 0 0 0 4.24m2.82-4.24c.39-.39 1.03-.39 1.42 0a5.003 5.003 0 0 1 0 7.07l-3.54 3.54a5.003 5.003 0 0 1-7.07 0a5.003 5.003 0 0 1 0-7.07l1.49-1.49c-.01.82.12 1.64.4 2.43l-.47.47a2.98 2.98 0 0 0 0 4.24a2.98 2.98 0 0 0 4.24 0l3.53-3.53a2.98 2.98 0 0 0 0-4.24a.973.973 0 0 1 0-1.42"/></svg>`
3170 renderer . heading = function ( { depth, tokens } ) {
3271 const content = this . parser . parseInline ( tokens )
72+ let id = ""
73+ let a = ""
74+ if ( depth === 2 ) {
75+ id = content . toLowerCase ( ) . replaceAll ( ":" , "" ) . replaceAll ( " " , "-" )
76+ a = `<a href="#${ id } " class="d-inline-block mr-2 text-primary opacity-50">${ linkIcon } </a>`
77+ tableOfContent . push ( { id, content } )
78+ }
79+
3380 const lv = Math . min ( depth + 3 , 6 )
34- return `<h${ lv } class="text-h${ lv } mb-2">${ content } </h${ lv } >`
81+ return `
82+ <h${ depth } id="${ id } " class="text-h${ lv } mb-4">
83+ ${ a } ${ content }
84+ </h${ depth } >
85+ `
3586 }
3687
3788 renderer . paragraph = function ( { tokens } ) {
3889 const content = this . parser . parseInline ( tokens )
39- return `<p class="text-body-1 text-accent mt-2 mb-4 ">${ content } </p>`
90+ return `<p class="text-body-1 text-accent mt-3 mb-6 ">${ content } </p>`
4091 }
4192
4293 renderer . listitem = function ( x ) {
43- // console.log(x.tokens)
44-
45- // return "item"
4694 const content = this . parser . parse ( x . tokens )
47- return `<li class="text-body-1 text-accent">${ content } </li>`
95+ return `
96+ <li class="mb-2">
97+ <span class="text-body-1 text-accent">${ content } </span>
98+ </li>
99+ `
48100 }
49101
50102 renderer . list = function ( { ordered, items } ) {
51103 const tag = ordered ? "ol" : "ul"
52104 const body = items . map ( item => this . listitem ( item ) ) . join ( "" )
53- return `<${ tag } class="mt-2 mb-4 pl-4" style="list-style-type: square">${ body } </${ tag } >`
105+ return `<${ tag } class="mt-4 mb-6 pl-4" style="list-style-type: square">${ body } </${ tag } >`
54106 }
55107
56108 renderer . link = function ( { href, tokens } ) {
@@ -75,139 +127,27 @@ export const useDocs = createGlobalState(() => {
75127 return `<a class="text-link" href="${ href } " onclick="xonClick(event, this);">${ content } </a>`
76128 }
77129
130+ renderer . strong = function ( { tokens } ) {
131+ const content = this . parser . parseInline ( tokens )
132+ return `<strong class="text-white text-body-1 font-weight-bold">${ content } </strong>`
133+ }
134+
78135 renderer . codespan = function ( { text } ) {
79136 return `<code
80137 class="text-primary text-body-1 border border-primary py-1 px-2 rounded"
81- style="background-color: rgba(var(--v-theme-primary), var(--v-border-opacity))"
138+ style="--v-border-opacity: 0.12; background-color: rgba(var(--v-theme-primary), var(--v-border-opacity))"
82139 >${ text } </code>`
83140 }
84141
85- /* Headings */
86- // renderer.heading = ({ text, depth: level }) => {
87- // return `<h${level} class="md-heading text-h${Math.min(level + 3, 6)}">${text}</h${level}>`
88- // }
89-
90- /* Paragraphs */
91- // renderer.paragraph = (text) => {
92- // return `<p class="md-paragraph">${text}</p>`
93- // }
94-
95- /* Links */
96- // renderer.link = ({ href, title, text }) => {
97- // const t = title ? ` title="${title}"` : ""
98- // return `<a class="md-link" href="${href}"${t} target="_blank" rel="noopener noreferrer">${text}</a>`
99- // }
100-
101- /* Lists */
102- // renderer.list = ({ ordered, items }) => {
103- // const tag = ordered ? "ol" : "ul"
104- // const body = items.map(item => `<li class="md-list-item">${item}</li>`).join("")
105- // return `<${tag} class="md-list">${body}</${tag}>`
106- // }
107-
108- // renderer.listitem = (text) => {
109- // return `<li class="md-list-item">${text}</li>`
110- // }
111-
112- /* Blockquotes */
113- // renderer.blockquote = (quote) => {
114- // return `<blockquote class="md-blockquote">${quote}</blockquote>`
115- // }
116-
117- /* Inline code */
118- // renderer.codespan = (code) => {
119- // return `<code class="md-inline-code">${code}</code>`
120- // }
121-
122- /* Code blocks */
123- // renderer.code = ({ text, lang }) => {
124- // const langClass = lang ? ` lang-${lang}` : ""
125- // return `
126- // <pre class="md-code-block${langClass}">
127- // <code class="md-code">${text}</code>
128- // </pre>
129- // `
130- // }
131-
132- /* Tables */
133- // renderer.table = ({ header, rows }) => {
134- // const body = marked.parseInline(rows)
135- // return `
136- // <table class="md-table">
137- // <thead class="md-table-head">${header}</thead>
138- // <tbody class="md-table-body">${body}</tbody>
139- // </table>
140- // `
141- // }
142-
143- // renderer.tablerow = (content) => {
144- // return `<tr class="md-table-row">${content}</tr>`
145- // }
146-
147- // renderer.tablecell = (content, flags) => {
148- // const tag = flags.header ? "th" : "td"
149- // return `<${tag} class="md-table-cell">${content}</${tag}>`
150- // }
151-
152- /* Images */
153- // renderer.image = ({ href, title, text }) => {
154- // const t = title ? ` title="${title}"` : ""
155- // return `<img class="md-image" src="${href}" alt="${text}"${t} />`
156- // }
157-
158- /* Horizontal rule */
159- // renderer.hr = () => {
160- // return `<hr class="md-hr" />`
161- // }
162-
163- /* Strong / emphasis */
164- // renderer.strong = (text) => {
165- // return `<strong class="md-strong">${text}</strong>`
166- // }
167-
168- // renderer.em = (text) => {
169- // return `<em class="md-em">${text}</em>`
170- // }
171-
172- // function e(name: string, attrs: Record<string, string>) {
173- // const content = attrs.content ?? ""
174- // delete attrs.content
175- // return `<${name} ${Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(" ")}>${content}</${name}>`
176- // }
177-
178- // marked.use({
179- // renderer: {
180- // blockquote({ tokens }) {
181- // const text = this.parser.parse(tokens)
182- // return `
183- // <blockquote
184- // class="pa-4 border-s-lg border-primary bg-surface"
185- // style="--v-border-opacity: 1"
186- // >
187- // ${text}
188- // </blockquote>
189- // `
190- // },
191- // code(code) {
192- // console.log(code)
193-
194- // if (!code.type) {
195- // console.log({ code })
196- // }
197- // return `
198- // <pre class="bg-red overflow-y-auto"><code class="language-${code.lang}">${code.text}</code></pre>
199- // `
200- // },
201- // },
202- // })
203142 return docs . map ( ( doc , index ) => {
143+ tableOfContent = [ ]
204144 const content = contents [ index ] ?? ""
205145 return {
206146 ...doc ,
207147 content,
208148 md : {
209149 html : marked . parse ( content , { renderer } ) ,
210- tableOfContent : [ ] ,
150+ tableOfContent,
211151 } ,
212152 }
213153 } )
0 commit comments