@@ -103,68 +103,76 @@ function setCopyState(button: HTMLButtonElement, labels: CopyLabels, copied: boo
103103 button . setAttribute ( "data-tooltip" , labels . copy )
104104}
105105
106- function setupCodeCopy ( root : HTMLDivElement , labels : CopyLabels ) {
107- const timeouts = new Map < HTMLButtonElement , ReturnType < typeof setTimeout > > ( )
108-
109- const updateLabel = ( button : HTMLButtonElement ) => {
110- const copied = button . getAttribute ( "data-copied" ) === "true"
111- setCopyState ( button , labels , copied )
112- }
113-
114- const ensureWrapper = ( block : HTMLPreElement ) => {
115- const parent = block . parentElement
116- if ( ! parent ) return
117- const wrapped = parent . getAttribute ( "data-component" ) === "markdown-code"
118- if ( wrapped ) {
119- const buttons = Array . from ( parent . querySelectorAll ( '[data-slot="markdown-copy-button"]' ) ) . filter (
120- ( el ) : el is HTMLButtonElement => el instanceof HTMLButtonElement ,
121- )
122-
123- if ( buttons . length === 0 ) {
124- parent . appendChild ( createCopyButton ( labels ) )
125- return
126- }
127-
128- for ( const button of buttons . slice ( 1 ) ) {
129- button . remove ( )
130- }
131-
132- return
133- }
106+ function ensureCodeWrapper ( block : HTMLPreElement , labels : CopyLabels ) {
107+ const parent = block . parentElement
108+ if ( ! parent ) return
109+ const wrapped = parent . getAttribute ( "data-component" ) === "markdown-code"
110+ if ( ! wrapped ) {
134111 const wrapper = document . createElement ( "div" )
135112 wrapper . setAttribute ( "data-component" , "markdown-code" )
136113 parent . replaceChild ( wrapper , block )
137114 wrapper . appendChild ( block )
138115 wrapper . appendChild ( createCopyButton ( labels ) )
116+ return
139117 }
140118
141- const markCodeLinks = ( ) => {
142- const codeNodes = Array . from ( root . querySelectorAll ( ":not(pre) > code" ) )
143- for ( const code of codeNodes ) {
144- const href = codeUrl ( code . textContent ?? "" )
145- const parentLink =
146- code . parentElement instanceof HTMLAnchorElement && code . parentElement . classList . contains ( "external-link" )
147- ? code . parentElement
148- : null
149-
150- if ( ! href ) {
151- if ( parentLink ) parentLink . replaceWith ( code )
152- continue
153- }
119+ const buttons = Array . from ( parent . querySelectorAll ( '[data-slot="markdown-copy-button"]' ) ) . filter (
120+ ( el ) : el is HTMLButtonElement => el instanceof HTMLButtonElement ,
121+ )
154122
155- if ( parentLink ) {
156- parentLink . href = href
157- continue
158- }
123+ if ( buttons . length === 0 ) {
124+ parent . appendChild ( createCopyButton ( labels ) )
125+ return
126+ }
127+
128+ for ( const button of buttons . slice ( 1 ) ) {
129+ button . remove ( )
130+ }
131+ }
132+
133+ function markCodeLinks ( root : HTMLDivElement ) {
134+ const codeNodes = Array . from ( root . querySelectorAll ( ":not(pre) > code" ) )
135+ for ( const code of codeNodes ) {
136+ const href = codeUrl ( code . textContent ?? "" )
137+ const parentLink =
138+ code . parentElement instanceof HTMLAnchorElement && code . parentElement . classList . contains ( "external-link" )
139+ ? code . parentElement
140+ : null
141+
142+ if ( ! href ) {
143+ if ( parentLink ) parentLink . replaceWith ( code )
144+ continue
145+ }
159146
160- const link = document . createElement ( "a" )
161- link . href = href
162- link . className = "external-link"
163- link . target = "_blank"
164- link . rel = "noopener noreferrer"
165- code . parentNode ?. replaceChild ( link , code )
166- link . appendChild ( code )
147+ if ( parentLink ) {
148+ parentLink . href = href
149+ continue
167150 }
151+
152+ const link = document . createElement ( "a" )
153+ link . href = href
154+ link . className = "external-link"
155+ link . target = "_blank"
156+ link . rel = "noopener noreferrer"
157+ code . parentNode ?. replaceChild ( link , code )
158+ link . appendChild ( code )
159+ }
160+ }
161+
162+ function decorate ( root : HTMLDivElement , labels : CopyLabels ) {
163+ const blocks = Array . from ( root . querySelectorAll ( "pre" ) )
164+ for ( const block of blocks ) {
165+ ensureCodeWrapper ( block , labels )
166+ }
167+ markCodeLinks ( root )
168+ }
169+
170+ function setupCodeCopy ( root : HTMLDivElement , labels : CopyLabels ) {
171+ const timeouts = new Map < HTMLButtonElement , ReturnType < typeof setTimeout > > ( )
172+
173+ const updateLabel = ( button : HTMLButtonElement ) => {
174+ const copied = button . getAttribute ( "data-copied" ) === "true"
175+ setCopyState ( button , labels , copied )
168176 }
169177
170178 const handleClick = async ( event : MouseEvent ) => {
@@ -186,11 +194,7 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
186194 timeouts . set ( button , timeout )
187195 }
188196
189- const blocks = Array . from ( root . querySelectorAll ( "pre" ) )
190- for ( const block of blocks ) {
191- ensureWrapper ( block )
192- }
193- markCodeLinks ( )
197+ decorate ( root , labels )
194198
195199 const buttons = Array . from ( root . querySelectorAll ( '[data-slot="markdown-copy-button"]' ) )
196200 for ( const button of buttons ) {
@@ -207,20 +211,6 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
207211 }
208212}
209213
210- function wrapCodeBlocks ( root : HTMLDivElement ) {
211- const blocks = Array . from ( root . querySelectorAll ( "pre" ) )
212- for ( const block of blocks ) {
213- const parent = block . parentElement
214- if ( ! parent ) continue
215- const wrapped = parent . getAttribute ( "data-component" ) === "markdown-code"
216- if ( wrapped ) continue
217- const wrapper = document . createElement ( "div" )
218- wrapper . setAttribute ( "data-component" , "markdown-code" )
219- parent . replaceChild ( wrapper , block )
220- wrapper . appendChild ( block )
221- }
222- }
223-
224214function touch ( key : string , value : Entry ) {
225215 cache . delete ( key )
226216 cache . set ( key , value )
@@ -284,23 +274,15 @@ export function Markdown(
284274
285275 const temp = document . createElement ( "div" )
286276 temp . innerHTML = content
287- wrapCodeBlocks ( temp )
277+ decorate ( temp , {
278+ copy : i18n . t ( "ui.message.copy" ) ,
279+ copied : i18n . t ( "ui.message.copied" ) ,
280+ } )
288281
289282 morphdom ( container , temp , {
290283 childrenOnly : true ,
291284 onBeforeElUpdated : ( fromEl , toEl ) => {
292285 if ( fromEl . isEqualNode ( toEl ) ) return false
293-
294- const fromWrapped = fromEl . getAttribute ( "data-component" ) === "markdown-code"
295- const toWrapped = toEl . getAttribute ( "data-component" ) === "markdown-code"
296- if ( fromWrapped && toWrapped ) {
297- const fromPre = fromEl . querySelector ( "pre" )
298- const toPre = toEl . querySelector ( "pre" )
299- if ( fromPre && toPre && ! fromPre . isEqualNode ( toPre ) ) {
300- morphdom ( fromPre , toPre )
301- }
302- return false
303- }
304286 return true
305287 } ,
306288 } )
0 commit comments