| 324 | } |
| 325 | |
| 326 | function wrapCodeBlock(pre: Element): Element { |
| 327 | const code = pre.children.find((c) => c.type === 'element' && c.tagName === 'code') as |
| 328 | | Element |
| 329 | | undefined |
| 330 | const lang = |
| 331 | (typeof code?.properties?.['data-language'] === 'string' && code.properties['data-language']) || |
| 332 | (typeof pre.properties?.['data-language'] === 'string' && pre.properties['data-language']) || |
| 333 | 'text' |
| 334 | const raw = code ? hastToString(code) : '' |
| 335 | |
| 336 | const bar: Element = { |
| 337 | type: 'element', |
| 338 | tagName: 'div', |
| 339 | properties: { className: ['code-bar'] }, |
| 340 | children: [ |
| 341 | { type: 'element', tagName: 'span', properties: { className: ['lang'] }, children: [{ type: 'text', value: lang }] }, |
| 342 | { |
| 343 | type: 'element', |
| 344 | tagName: 'button', |
| 345 | properties: { className: ['copy-btn'], type: 'button', 'data-copy': raw, 'aria-label': 'Copy code' }, |
| 346 | children: [ |
| 347 | { |
| 348 | type: 'element', |
| 349 | tagName: 'svg', |
| 350 | properties: { |
| 351 | viewBox: '0 0 24 24', |
| 352 | fill: 'none', |
| 353 | stroke: 'currentColor', |
| 354 | strokeWidth: 2, |
| 355 | strokeLinecap: 'round', |
| 356 | strokeLinejoin: 'round' |
| 357 | }, |
| 358 | children: [ |
| 359 | { type: 'element', tagName: 'rect', properties: { x: 9, y: 9, width: 13, height: 13, rx: 2, ry: 2 }, children: [] }, |
| 360 | { type: 'element', tagName: 'path', properties: { d: 'M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1' }, children: [] } |
| 361 | ] |
| 362 | }, |
| 363 | { type: 'element', tagName: 'span', properties: { className: ['label'] }, children: [{ type: 'text', value: 'Copy' }] } |
| 364 | ] |
| 365 | } |
| 366 | ] |
| 367 | } |
| 368 | |
| 369 | return { |
| 370 | type: 'element', |
| 371 | tagName: 'div', |
| 372 | properties: { className: ['code'] }, |
| 373 | children: [bar, pre] |
| 374 | } |
| 375 | } |