@mhmo91/schmancy 0.9.19 → 0.9.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/{flow-CaPi2G8y.js.map → flow-CvG1fLW5.js.map} +1 -1
- package/dist/agent/{rolldown-runtime-DsMetpgY.js → rolldown-runtime-BIIoCavz.js} +9 -2
- package/dist/agent/schmancy.agent.js +3348 -3332
- package/dist/agent/schmancy.agent.js.map +1 -1
- package/dist/agent/{vendor-highlight-CHJZQQB7.js → vendor-highlight-Dow87ZL_.js} +90 -85
- package/dist/agent/{vendor-highlight-CHJZQQB7.js.map → vendor-highlight-Dow87ZL_.js.map} +1 -1
- package/dist/agent/{vendor-jsqr-r7GNh4P3.js → vendor-jsqr-Bl4iAtKC.js} +1 -1
- package/dist/agent/{vendor-jsqr-r7GNh4P3.js.map → vendor-jsqr-Bl4iAtKC.js.map} +1 -1
- package/dist/agent/{vendor-material-color-Be96dpGE.js.map → vendor-material-color-DcL7ZPxx.js.map} +1 -1
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/{code-highlight-zSYcSfCz.cjs → code-highlight-B_l8vDzn.cjs} +11 -11
- package/dist/code-highlight-B_l8vDzn.cjs.map +1 -0
- package/dist/{code-highlight-BgExKEto.js → code-highlight-CI_gqXYX.js} +30 -22
- package/dist/code-highlight-CI_gqXYX.js.map +1 -0
- package/dist/code-highlight.cjs +1 -1
- package/dist/code-highlight.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/handover/agent-runtime-followups.md +1 -1
- package/dist/handover/agent-runtime-v1.md +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/nav-drawer.cjs +1 -1
- package/dist/nav-drawer.js +1 -1
- package/dist/navigation-bar.cjs +1 -1
- package/dist/navigation-bar.js +1 -1
- package/dist/qr-scanner.cjs +5 -5
- package/dist/qr-scanner.cjs.map +1 -1
- package/dist/qr-scanner.js +10 -6
- package/dist/qr-scanner.js.map +1 -1
- package/dist/{src-BGj6ufWS.js → src-Dw-PjtMH.js} +1 -1
- package/dist/{src-BGj6ufWS.js.map → src-Dw-PjtMH.js.map} +1 -1
- package/dist/{src-BPKGdQdp.cjs → src-sG7Ihf0e.cjs} +1 -1
- package/dist/{src-BPKGdQdp.cjs.map → src-sG7Ihf0e.cjs.map} +1 -1
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/package.json +1 -1
- package/src/code-highlight/code-highlight.ts +56 -24
- package/src/qr-scanner/qr-scanner.ts +27 -2
- package/types/src/code-highlight/code-highlight.d.ts +8 -1
- package/dist/code-highlight-BgExKEto.js.map +0 -1
- package/dist/code-highlight-zSYcSfCz.cjs.map +0 -1
- /package/dist/agent/{flow-CaPi2G8y.js → flow-CvG1fLW5.js} +0 -0
- /package/dist/agent/{vendor-material-color-Be96dpGE.js → vendor-material-color-DcL7ZPxx.js} +0 -0
package/dist/teleport.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./src-sG7Ihf0e.cjs`);exports.HereMorty=e.r,Object.defineProperty(exports,`SchmancyTeleportation`,{enumerable:!0,get:function(){return e.n}}),exports.WhereAreYouRicky=e.i,exports.teleport=e.a;
|
package/dist/teleport.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, r } from "./src-
|
|
1
|
+
import { a as e, i as t, n, r } from "./src-Dw-PjtMH.js";
|
|
2
2
|
export { r as HereMorty, n as SchmancyTeleportation, t as WhereAreYouRicky, e as teleport };
|
package/package.json
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
import { TailwindElement } from '@mixins/index'
|
|
2
|
-
import hljs from 'highlight.js/lib/core'
|
|
3
|
-
import bash from 'highlight.js/lib/languages/bash'
|
|
4
|
-
import javascript from 'highlight.js/lib/languages/javascript'
|
|
5
|
-
import markdown from 'highlight.js/lib/languages/markdown'
|
|
6
|
-
import typescript from 'highlight.js/lib/languages/typescript'
|
|
7
|
-
import xml from 'highlight.js/lib/languages/xml'
|
|
8
2
|
import { css, html } from 'lit'
|
|
9
3
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
10
4
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
|
11
5
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
// highlight.js + all 6 language grammars are loaded lazily on first render.
|
|
7
|
+
// Static imports were previously responsible for ~15 KB gzipped (vendor-
|
|
8
|
+
// highlight chunk) being eagerly fetched on every agent-bundle first paint,
|
|
9
|
+
// even for pages that never rendered <schmancy-code>. See ADR 0014 in the
|
|
10
|
+
// parent monorepo.
|
|
11
|
+
type Hljs = typeof import('highlight.js/lib/core').default
|
|
12
|
+
|
|
13
|
+
let hljsPromise: Promise<Hljs> | null = null
|
|
14
|
+
function loadHljs(): Promise<Hljs> {
|
|
15
|
+
if (hljsPromise) return hljsPromise
|
|
16
|
+
hljsPromise = Promise.all([
|
|
17
|
+
import('highlight.js/lib/core'),
|
|
18
|
+
import('highlight.js/lib/languages/bash'),
|
|
19
|
+
import('highlight.js/lib/languages/javascript'),
|
|
20
|
+
import('highlight.js/lib/languages/markdown'),
|
|
21
|
+
import('highlight.js/lib/languages/typescript'),
|
|
22
|
+
import('highlight.js/lib/languages/xml'),
|
|
23
|
+
]).then(([core, bash, javascript, markdown, typescript, xml]) => {
|
|
24
|
+
const hljs = core.default
|
|
25
|
+
hljs.registerLanguage('javascript', javascript.default)
|
|
26
|
+
hljs.registerLanguage('typescript', typescript.default)
|
|
27
|
+
hljs.registerLanguage('html', xml.default)
|
|
28
|
+
hljs.registerLanguage('xml', xml.default)
|
|
29
|
+
hljs.registerLanguage('markdown', markdown.default)
|
|
30
|
+
hljs.registerLanguage('bash', bash.default)
|
|
31
|
+
return hljs
|
|
32
|
+
})
|
|
33
|
+
return hljsPromise
|
|
34
|
+
}
|
|
19
35
|
|
|
20
36
|
/**
|
|
21
37
|
* @element schmancy-code
|
|
@@ -188,32 +204,48 @@ export class SchmancyCode extends TailwindElement(css`
|
|
|
188
204
|
@state()
|
|
189
205
|
private copied: boolean = false
|
|
190
206
|
|
|
191
|
-
|
|
192
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Fully-rendered highlighted HTML — populated asynchronously after
|
|
209
|
+
* `loadHljs()` resolves. Empty on first render (one microtask) for a
|
|
210
|
+
* cold component; non-empty from then on.
|
|
211
|
+
*/
|
|
212
|
+
@state()
|
|
213
|
+
private _highlightedCode: string = ''
|
|
193
214
|
|
|
194
|
-
|
|
215
|
+
protected override updated(changed: Map<string, unknown>): void {
|
|
216
|
+
super.updated?.(changed)
|
|
217
|
+
if (changed.has('code') || changed.has('language') || changed.has('lineNumbers') || changed.has('highlightLines')) {
|
|
218
|
+
void this._rehighlight()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private async _rehighlight(): Promise<void> {
|
|
223
|
+
if (!this.code) {
|
|
224
|
+
this._highlightedCode = ''
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
const hljs = await loadHljs()
|
|
228
|
+
// Guard against unmount + racing property changes.
|
|
229
|
+
if (!this.isConnected) return
|
|
195
230
|
|
|
231
|
+
let highlightedHtml = ''
|
|
196
232
|
try {
|
|
197
|
-
// Use highlight.js to get highlighted code
|
|
198
233
|
const result = hljs.highlight(this.code.trim(), { language: this.language })
|
|
199
234
|
highlightedHtml = result.value
|
|
200
235
|
} catch {
|
|
201
|
-
// Fallback to auto-detection if language is not supported
|
|
202
236
|
try {
|
|
203
237
|
const result = hljs.highlightAuto(this.code.trim())
|
|
204
238
|
highlightedHtml = result.value
|
|
205
239
|
} catch {
|
|
206
|
-
// Final fallback to escaped plain text
|
|
207
240
|
highlightedHtml = this.escapeHtml(this.code.trim())
|
|
208
241
|
}
|
|
209
242
|
}
|
|
210
243
|
|
|
211
|
-
// Process for line numbers and highlighting if needed
|
|
212
244
|
if (this.lineNumbers || this.highlightLines) {
|
|
213
|
-
|
|
245
|
+
this._highlightedCode = this.addLineFeatures(highlightedHtml)
|
|
246
|
+
} else {
|
|
247
|
+
this._highlightedCode = highlightedHtml
|
|
214
248
|
}
|
|
215
|
-
|
|
216
|
-
return highlightedHtml
|
|
217
249
|
}
|
|
218
250
|
|
|
219
251
|
private escapeHtml(text: string): string {
|
|
@@ -330,7 +362,7 @@ export class SchmancyCode extends TailwindElement(css`
|
|
|
330
362
|
</section>
|
|
331
363
|
<!-- Code -->
|
|
332
364
|
<div class="overflow-auto" style="${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}">
|
|
333
|
-
<pre class="m-0"><code class="${codeClass}">${unsafeHTML(this.
|
|
365
|
+
<pre class="m-0"><code class="${codeClass}">${unsafeHTML(this._highlightedCode)}</code></pre>
|
|
334
366
|
</div>
|
|
335
367
|
</schmancy-details>
|
|
336
368
|
`
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import { $LitElement } from '@mixins/litElement.mixin'
|
|
2
|
-
import jsQR from 'jsqr'
|
|
3
2
|
import { css, html } from 'lit'
|
|
4
3
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
5
4
|
import { when } from 'lit/directives/when.js'
|
|
6
5
|
import { animationFrames, Subject, timer } from 'rxjs'
|
|
7
6
|
import { distinctUntilChanged, filter, map, takeUntil, throttleTime } from 'rxjs/operators'
|
|
8
7
|
|
|
8
|
+
// jsQR (~53 KB gzipped) is loaded lazily the first time a camera stream
|
|
9
|
+
// is attached — see ADR 0014. Until this resolves, scanFrame() returns
|
|
10
|
+
// null and no decode happens, so the animationFrames loop spins harmlessly.
|
|
11
|
+
type JsQR = typeof import('jsqr').default
|
|
12
|
+
let jsQRFn: JsQR | null = null
|
|
13
|
+
let jsQRPromise: Promise<JsQR> | null = null
|
|
14
|
+
function loadJsQR(): Promise<JsQR> {
|
|
15
|
+
if (jsQRPromise) return jsQRPromise
|
|
16
|
+
jsQRPromise = import('jsqr').then(m => {
|
|
17
|
+
jsQRFn = m.default
|
|
18
|
+
return m.default
|
|
19
|
+
})
|
|
20
|
+
return jsQRPromise
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
interface QRScanResult {
|
|
10
24
|
data: string
|
|
11
25
|
timestamp: number
|
|
@@ -55,6 +69,12 @@ export class SchmancyQRScanner extends $LitElement(css`
|
|
|
55
69
|
if (this.videoElement) {
|
|
56
70
|
this.videoElement.srcObject = this.stream
|
|
57
71
|
await this.videoElement.play()
|
|
72
|
+
// Preload jsQR before starting the animationFrames loop so the
|
|
73
|
+
// first few frames have the decoder available. If the fetch
|
|
74
|
+
// hasn't finished by the time a frame fires, scanFrame() just
|
|
75
|
+
// returns null for that tick — no decode, no error.
|
|
76
|
+
await loadJsQR()
|
|
77
|
+
if (!this.isConnected) return
|
|
58
78
|
this.startScanning()
|
|
59
79
|
}
|
|
60
80
|
} catch (error) {
|
|
@@ -122,7 +142,12 @@ export class SchmancyQRScanner extends $LitElement(css`
|
|
|
122
142
|
ctx.drawImage(this.videoElement, 0, 0)
|
|
123
143
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
124
144
|
|
|
125
|
-
|
|
145
|
+
// Skip this frame if jsQR hasn't resolved yet — startCamera awaits
|
|
146
|
+
// loadJsQR() before this path runs, so in practice jsQRFn is
|
|
147
|
+
// always set here. Keeping the guard for safety during racy
|
|
148
|
+
// disconnects.
|
|
149
|
+
if (!jsQRFn) return null
|
|
150
|
+
const code = jsQRFn(imageData.data, imageData.width, imageData.height)
|
|
126
151
|
|
|
127
152
|
if (code && code.data) {
|
|
128
153
|
return {
|
|
@@ -33,7 +33,14 @@ export declare class SchmancyCode extends SchmancyCode_base {
|
|
|
33
33
|
*/
|
|
34
34
|
maxHeight?: string;
|
|
35
35
|
private copied;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Fully-rendered highlighted HTML — populated asynchronously after
|
|
38
|
+
* `loadHljs()` resolves. Empty on first render (one microtask) for a
|
|
39
|
+
* cold component; non-empty from then on.
|
|
40
|
+
*/
|
|
41
|
+
private _highlightedCode;
|
|
42
|
+
protected updated(changed: Map<string, unknown>): void;
|
|
43
|
+
private _rehighlight;
|
|
37
44
|
private escapeHtml;
|
|
38
45
|
private getHighlightedLines;
|
|
39
46
|
private addLineFeatures;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"code-highlight-BgExKEto.js","names":[],"sources":["../src/code-highlight/code-highlight.ts","../src/code-highlight/code-preview.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport hljs from 'highlight.js/lib/core'\nimport bash from 'highlight.js/lib/languages/bash'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport xml from 'highlight.js/lib/languages/xml'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\n// Register only the languages we need\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('typescript', typescript)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('xml', xml)\nhljs.registerLanguage('markdown', markdown)\nhljs.registerLanguage('bash', bash)\n\n/**\n * @element schmancy-code\n * Code highlighting component using highlight.js with schmancy theming support\n */\n@customElement('schmancy-code')\nexport class SchmancyCode extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\toverflow: hidden;\n\t}\n\n\t/* Code block styling using schmancy color system */\n\t.hljs {\n\t\tdisplay: block;\n\t\toverflow-x: auto;\n\t\tpadding: 0.5em;\n\t\tcolor: var(--md-sys-color-on-surface-variant);\n\t\tbackground: var(--md-sys-color-surface-container-lowest);\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n\t}\n\n\t/* Comments and documentation */\n\t.hljs-comment,\n\t.hljs-quote {\n\t\tcolor: var(--md-sys-color-outline);\n\t\tfont-style: italic;\n\t}\n\n\t/* Keywords, doctags, formulas */\n\t.hljs-doctag,\n\t.hljs-keyword,\n\t.hljs-formula {\n\t\tcolor: var(--md-sys-color-primary);\n\t}\n\n\t/* Tags, sections, names, deletions */\n\t.hljs-section,\n\t.hljs-name,\n\t.hljs-selector-tag,\n\t.hljs-deletion,\n\t.hljs-subst {\n\t\tcolor: var(--md-sys-color-error);\n\t}\n\n\t/* Literals */\n\t.hljs-literal {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Strings, regex, additions */\n\t.hljs-string,\n\t.hljs-regexp,\n\t.hljs-addition,\n\t.hljs-attribute,\n\t.hljs-meta-string {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t/* Built-ins and class titles */\n\t.hljs-built_in,\n\t.hljs-class .hljs-title {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Variables, attributes, types */\n\t.hljs-attr,\n\t.hljs-variable,\n\t.hljs-template-variable,\n\t.hljs-type,\n\t.hljs-selector-class,\n\t.hljs-selector-attr,\n\t.hljs-selector-pseudo,\n\t.hljs-number {\n\t\tcolor: var(--md-sys-color-on-surface);\n\t}\n\n\t/* Symbols, bullets, links, meta */\n\t.hljs-symbol,\n\t.hljs-bullet,\n\t.hljs-link,\n\t.hljs-meta,\n\t.hljs-selector-id,\n\t.hljs-title {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t.hljs-emphasis {\n\t\tfont-style: italic;\n\t}\n\n\t.hljs-strong {\n\t\tfont-weight: bold;\n\t}\n\n\t.hljs-link {\n\t\ttext-decoration: underline;\n\t}\n\n\t/* Line features styling */\n\t.code-with-lines {\n\t\tbackground: transparent;\n\t\tpadding: 0;\n\t}\n\n\t.code-line {\n\t\tdisplay: block;\n\t\tpadding-left: 0;\n\t\ttransition: background-color 0.2s ease;\n\t}\n\n\t.code-line.highlighted {\n\t\tbackground-color: var(--md-sys-color-primary-container);\n\t\topacity: 0.2;\n\t}\n\n\t.line-number {\n\t\tdisplay: inline-block;\n\t\twidth: 3rem;\n\t\tpadding-right: 1rem;\n\t\ttext-align: right;\n\t\tcolor: var(--md-sys-color-outline);\n\t\tuser-select: none;\n\t\tfont-size: inherit;\n\t}\n`) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'javascript'\n\n\t/**\n\t * Code content to highlight\n\t */\n\t@property({ type: String })\n\tcode: string = ''\n\n\t/**\n\t * Optional filename or title to display in header\n\t */\n\t@property({ type: String })\n\tfilename?: string\n\n\t/**\n\t * Show line numbers\n\t */\n\t@property({ type: Boolean })\n\tlineNumbers: boolean = false\n\n\t/**\n\t * Show copy button\n\t */\n\t@property({ type: Boolean })\n\tcopyButton: boolean = true\n\n\t/**\n\t * Highlighted line numbers (comma-separated or ranges like \"1-3,5,7-9\")\n\t */\n\t@property({ type: String })\n\thighlightLines?: string\n\n\t/**\n\t * Maximum height before scrolling\n\t */\n\t@property({ type: String })\n\tmaxHeight?: string\n\n\t@state()\n\tprivate copied: boolean = false\n\n\tprivate get highlightedCode(): string {\n\t\tif (!this.code) return ''\n\n\t\tlet highlightedHtml = ''\n\n\t\ttry {\n\t\t\t// Use highlight.js to get highlighted code\n\t\t\tconst result = hljs.highlight(this.code.trim(), { language: this.language })\n\t\t\thighlightedHtml = result.value\n\t\t} catch {\n\t\t\t// Fallback to auto-detection if language is not supported\n\t\t\ttry {\n\t\t\t\tconst result = hljs.highlightAuto(this.code.trim())\n\t\t\t\thighlightedHtml = result.value\n\t\t\t} catch {\n\t\t\t\t// Final fallback to escaped plain text\n\t\t\t\thighlightedHtml = this.escapeHtml(this.code.trim())\n\t\t\t}\n\t\t}\n\n\t\t// Process for line numbers and highlighting if needed\n\t\tif (this.lineNumbers || this.highlightLines) {\n\t\t\treturn this.addLineFeatures(highlightedHtml)\n\t\t}\n\n\t\treturn highlightedHtml\n\t}\n\n\tprivate escapeHtml(text: string): string {\n\t\tconst div = document.createElement('div')\n\t\tdiv.textContent = text\n\t\treturn div.innerHTML\n\t}\n\n\tprivate getHighlightedLines(): Set<number> {\n\t\tconst lines = new Set<number>()\n\t\tif (!this.highlightLines) return lines\n\n\t\tconst parts = this.highlightLines.split(',')\n\t\tfor (const part of parts) {\n\t\t\tconst trimmed = part.trim()\n\t\t\tif (trimmed.includes('-')) {\n\t\t\t\tconst [start, end] = trimmed.split('-').map(n => parseInt(n.trim()))\n\t\t\t\tif (!isNaN(start) && !isNaN(end)) {\n\t\t\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\t\t\tlines.add(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lineNum = parseInt(trimmed)\n\t\t\t\tif (!isNaN(lineNum)) {\n\t\t\t\t\tlines.add(lineNum)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn lines\n\t}\n\n\tprivate addLineFeatures(highlightedHtml: string): string {\n\t\tconst lines = highlightedHtml.split('\\n')\n\t\tconst highlightedLines = this.getHighlightedLines()\n\n\t\treturn lines\n\t\t\t.map((line, index) => {\n\t\t\t\tconst lineNumber = index + 1\n\t\t\t\tconst isHighlighted = highlightedLines.has(lineNumber)\n\t\t\t\tconst lineClass = isHighlighted ? 'code-line highlighted' : 'code-line'\n\n\t\t\t\tlet content = ''\n\t\t\t\tif (this.lineNumbers) {\n\t\t\t\t\tcontent += `<span class=\"line-number\">${lineNumber}</span>`\n\t\t\t\t}\n\t\t\t\tcontent += line\n\n\t\t\t\treturn `<div class=\"${lineClass}\">${content}</div>`\n\t\t\t})\n\t\t\t.join('')\n\t}\n\n\tprivate async copyCode() {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(this.code)\n\t\t\tthis.copied = true\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.copied = false\n\t\t\t}, 2000)\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to copy code:', err)\n\t\t}\n\t}\n\n\tprivate getLanguageLabel(): string {\n\t\tconst languageMap: Record<string, string> = {\n\t\t\tjavascript: 'JavaScript',\n\t\t\ttypescript: 'TypeScript',\n\t\t\thtml: 'HTML',\n\t\t\tmarkdown: 'Markdown',\n\t\t\tbash: 'Bash',\n\t\t}\n\n\t\tif (this.filename) {\n\t\t\treturn this.filename\n\t\t}\n\n\t\treturn languageMap[this.language.toLowerCase()] || this.language.toUpperCase()\n\t}\n\n\trender() {\n\t\tconst codeClass = this.lineNumbers || this.highlightLines ? 'code-with-lines' : 'hljs'\n\n\t\treturn html`\n\t\t\t<schmancy-details class=\"bg-surface-default\">\n\t\t\t\t<section slot=\"summary\">\n\t\t\t\t\t<!-- Header -->\n\t\t\t\t\t<div class=\"flex items-center justify-between\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div class=\"flex gap-1.5\">\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-error);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-tertiary);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-secondary);\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span class=\"text-xs font-medium opacity-70 ml-2\" style=\"color: var(--md-sys-color-on-surface-variant);\">\n\t\t\t\t\t\t\t\t${this.getLanguageLabel()}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t${this.copyButton\n\t\t\t\t\t\t\t? html`\n\t\t\t\t\t\t\t\t\t<schmancy-button\n\t\t\t\t\t\t\t\t\t\t.variant=\"${this.copied ? 'filled tonal' : 'text'}\"\n\t\t\t\t\t\t\t\t\t\t@click=${this.copyCode}\n\t\t\t\t\t\t\t\t\t\tclass=\"transition-all\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<schmancy-icon > ${this.copied ? 'check' : 'content_copy'} </schmancy-icon>\n\t\t\t\t\t\t\t\t\t\t<span class=\"ml-1\">${this.copied ? 'Copied!' : 'Copy'}</span>\n\t\t\t\t\t\t\t\t\t</schmancy-button>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t\t<!-- Code -->\n\t\t\t\t<div class=\"overflow-auto\" style=\"${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}\">\n\t\t\t\t\t<pre class=\"m-0\"><code class=\"${codeClass}\">${unsafeHTML(this.highlightedCode)}</code></pre>\n\t\t\t\t</div>\n\t\t\t</schmancy-details>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code': SchmancyCode\n\t}\n}\n","import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { timer } from 'rxjs'\nimport { take } from 'rxjs/operators'\n\n/**\n * @element schmancy-code-preview\n * A component that shows code and its rendered preview side by side\n * Takes the content as a slot and displays both the source and rendered result\n */\n@customElement('schmancy-code-preview')\nexport class SchmancyCodePreview extends TailwindElement(\n\tcss`:host{\n\t\tdisplay:block;\n\t\toverflow:hidden;\n\t\tposition:relative;\n\t\tinset:0;\n\t}`\n) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'html'\n\n\t/**\n\t * Show code on top or side-by-side\n\t */\n\t@property({ type: String })\n\tlayout: 'vertical' | 'horizontal' = 'vertical'\n\n\t/**\n\t * Whether to render/execute the code in preview section\n\t * When false, only shows the code without rendering\n\t */\n\t@property({ type: Boolean })\n\tpreview: boolean = true\n\n\t@state()\n\tprivate slotContent: string = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Capture the slot content as HTML string\n\t\ttimer(0).pipe(take(1)).subscribe(() => {\n\t\t\tconst slot = this.shadowRoot?.querySelector('slot')\n\t\t\tif (slot) {\n\t\t\t\tconst nodes = slot.assignedNodes({ flatten: true })\n\t\t\t\tconst htmlStrings = nodes.map(node => {\n\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\treturn (node as HTMLElement).outerHTML\n\t\t\t\t\t} else if (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\treturn node.textContent || ''\n\t\t\t\t\t}\n\t\t\t\t\treturn ''\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Clean up the HTML string\n\t\t\t\tconst rawContent = htmlStrings.join('')\n\t\t\t\t\n\t\t\t\t// Find the minimum indentation (excluding empty lines)\n\t\t\t\tconst lines = rawContent.split('\\n')\n\t\t\t\tconst minIndent = lines\n\t\t\t\t\t.filter(line => line.trim().length > 0)\n\t\t\t\t\t.reduce((min, line) => {\n\t\t\t\t\t\tconst indent = line.match(/^(\\s*)/)?.[1].length || 0\n\t\t\t\t\t\treturn Math.min(min, indent)\n\t\t\t\t\t}, Infinity)\n\t\t\t\t\n\t\t\t\t// Remove the minimum indentation from all lines\n\t\t\t\tthis.slotContent = lines\n\t\t\t\t\t.map(line => line.slice(minIndent))\n\t\t\t\t\t.join('\\n')\n\t\t\t\t\t.trim()\n\t\t\t}\n\t\t})\n\t}\n\n\trender() {\n\t\tconst containerClass = this.layout === 'horizontal' \n\t\t\t? 'grid grid-cols-1 lg:grid-cols-2 gap-0' \n\t\t\t: 'flex flex-col'\n\n\t\tconst showPreview = this.preview && this.language.toLowerCase() === 'html'\n\t\t\n\t\treturn html`\n\t\t\t<schmancy-surface class=\"rounded-lg overflow-hidden\">\n\t\t\t\t<div class=\"${showPreview ? containerClass : ''}\">\n\t\t\t\t\t<!-- Code section with proper overflow handling -->\n\t\t\t\t\t<div class=\"min-w-0 overflow-hidden\">\n\t\t\t\t\t\t<schmancy-code\n\t\t\t\t\t\t\tlanguage=\"${this.language}\"\n\t\t\t\t\t\t\t.code=\"${this.slotContent}\"\n\t\t\t\t\t\t\t?copyButton=\"${true}\"\n\t\t\t\t\t\t\tclass=\"block w-full\"\n\t\t\t\t\t\t></schmancy-code>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<!-- Preview section (only visible for HTML and when preview is enabled) -->\n\t\t\t\t\t${showPreview ? html`\n\t\t\t\t\t\t<div class=\"min-w-0 overflow-auto\">\n\t\t\t\t\t\t\t<schmancy-surface type=\"solid\" class=\"p-2 h-full\">\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t\t</schmancy-surface>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t` : html`\n\t\t\t\t\t\t<!-- Hidden slot to capture content -->\n\t\t\t\t\t\t<div class=\"hidden\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`}\n\t\t\t\t</div>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code-preview': SchmancyCodePreview\n\t}\n}"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"code-highlight-zSYcSfCz.cjs","names":[],"sources":["../src/code-highlight/code-highlight.ts","../src/code-highlight/code-preview.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport hljs from 'highlight.js/lib/core'\nimport bash from 'highlight.js/lib/languages/bash'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport markdown from 'highlight.js/lib/languages/markdown'\nimport typescript from 'highlight.js/lib/languages/typescript'\nimport xml from 'highlight.js/lib/languages/xml'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\n// Register only the languages we need\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('typescript', typescript)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('xml', xml)\nhljs.registerLanguage('markdown', markdown)\nhljs.registerLanguage('bash', bash)\n\n/**\n * @element schmancy-code\n * Code highlighting component using highlight.js with schmancy theming support\n */\n@customElement('schmancy-code')\nexport class SchmancyCode extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\toverflow: hidden;\n\t}\n\n\t/* Code block styling using schmancy color system */\n\t.hljs {\n\t\tdisplay: block;\n\t\toverflow-x: auto;\n\t\tpadding: 0.5em;\n\t\tcolor: var(--md-sys-color-on-surface-variant);\n\t\tbackground: var(--md-sys-color-surface-container-lowest);\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n\t}\n\n\t/* Comments and documentation */\n\t.hljs-comment,\n\t.hljs-quote {\n\t\tcolor: var(--md-sys-color-outline);\n\t\tfont-style: italic;\n\t}\n\n\t/* Keywords, doctags, formulas */\n\t.hljs-doctag,\n\t.hljs-keyword,\n\t.hljs-formula {\n\t\tcolor: var(--md-sys-color-primary);\n\t}\n\n\t/* Tags, sections, names, deletions */\n\t.hljs-section,\n\t.hljs-name,\n\t.hljs-selector-tag,\n\t.hljs-deletion,\n\t.hljs-subst {\n\t\tcolor: var(--md-sys-color-error);\n\t}\n\n\t/* Literals */\n\t.hljs-literal {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Strings, regex, additions */\n\t.hljs-string,\n\t.hljs-regexp,\n\t.hljs-addition,\n\t.hljs-attribute,\n\t.hljs-meta-string {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t/* Built-ins and class titles */\n\t.hljs-built_in,\n\t.hljs-class .hljs-title {\n\t\tcolor: var(--md-sys-color-tertiary);\n\t}\n\n\t/* Variables, attributes, types */\n\t.hljs-attr,\n\t.hljs-variable,\n\t.hljs-template-variable,\n\t.hljs-type,\n\t.hljs-selector-class,\n\t.hljs-selector-attr,\n\t.hljs-selector-pseudo,\n\t.hljs-number {\n\t\tcolor: var(--md-sys-color-on-surface);\n\t}\n\n\t/* Symbols, bullets, links, meta */\n\t.hljs-symbol,\n\t.hljs-bullet,\n\t.hljs-link,\n\t.hljs-meta,\n\t.hljs-selector-id,\n\t.hljs-title {\n\t\tcolor: var(--md-sys-color-secondary);\n\t}\n\n\t.hljs-emphasis {\n\t\tfont-style: italic;\n\t}\n\n\t.hljs-strong {\n\t\tfont-weight: bold;\n\t}\n\n\t.hljs-link {\n\t\ttext-decoration: underline;\n\t}\n\n\t/* Line features styling */\n\t.code-with-lines {\n\t\tbackground: transparent;\n\t\tpadding: 0;\n\t}\n\n\t.code-line {\n\t\tdisplay: block;\n\t\tpadding-left: 0;\n\t\ttransition: background-color 0.2s ease;\n\t}\n\n\t.code-line.highlighted {\n\t\tbackground-color: var(--md-sys-color-primary-container);\n\t\topacity: 0.2;\n\t}\n\n\t.line-number {\n\t\tdisplay: inline-block;\n\t\twidth: 3rem;\n\t\tpadding-right: 1rem;\n\t\ttext-align: right;\n\t\tcolor: var(--md-sys-color-outline);\n\t\tuser-select: none;\n\t\tfont-size: inherit;\n\t}\n`) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'javascript'\n\n\t/**\n\t * Code content to highlight\n\t */\n\t@property({ type: String })\n\tcode: string = ''\n\n\t/**\n\t * Optional filename or title to display in header\n\t */\n\t@property({ type: String })\n\tfilename?: string\n\n\t/**\n\t * Show line numbers\n\t */\n\t@property({ type: Boolean })\n\tlineNumbers: boolean = false\n\n\t/**\n\t * Show copy button\n\t */\n\t@property({ type: Boolean })\n\tcopyButton: boolean = true\n\n\t/**\n\t * Highlighted line numbers (comma-separated or ranges like \"1-3,5,7-9\")\n\t */\n\t@property({ type: String })\n\thighlightLines?: string\n\n\t/**\n\t * Maximum height before scrolling\n\t */\n\t@property({ type: String })\n\tmaxHeight?: string\n\n\t@state()\n\tprivate copied: boolean = false\n\n\tprivate get highlightedCode(): string {\n\t\tif (!this.code) return ''\n\n\t\tlet highlightedHtml = ''\n\n\t\ttry {\n\t\t\t// Use highlight.js to get highlighted code\n\t\t\tconst result = hljs.highlight(this.code.trim(), { language: this.language })\n\t\t\thighlightedHtml = result.value\n\t\t} catch {\n\t\t\t// Fallback to auto-detection if language is not supported\n\t\t\ttry {\n\t\t\t\tconst result = hljs.highlightAuto(this.code.trim())\n\t\t\t\thighlightedHtml = result.value\n\t\t\t} catch {\n\t\t\t\t// Final fallback to escaped plain text\n\t\t\t\thighlightedHtml = this.escapeHtml(this.code.trim())\n\t\t\t}\n\t\t}\n\n\t\t// Process for line numbers and highlighting if needed\n\t\tif (this.lineNumbers || this.highlightLines) {\n\t\t\treturn this.addLineFeatures(highlightedHtml)\n\t\t}\n\n\t\treturn highlightedHtml\n\t}\n\n\tprivate escapeHtml(text: string): string {\n\t\tconst div = document.createElement('div')\n\t\tdiv.textContent = text\n\t\treturn div.innerHTML\n\t}\n\n\tprivate getHighlightedLines(): Set<number> {\n\t\tconst lines = new Set<number>()\n\t\tif (!this.highlightLines) return lines\n\n\t\tconst parts = this.highlightLines.split(',')\n\t\tfor (const part of parts) {\n\t\t\tconst trimmed = part.trim()\n\t\t\tif (trimmed.includes('-')) {\n\t\t\t\tconst [start, end] = trimmed.split('-').map(n => parseInt(n.trim()))\n\t\t\t\tif (!isNaN(start) && !isNaN(end)) {\n\t\t\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\t\t\tlines.add(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lineNum = parseInt(trimmed)\n\t\t\t\tif (!isNaN(lineNum)) {\n\t\t\t\t\tlines.add(lineNum)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn lines\n\t}\n\n\tprivate addLineFeatures(highlightedHtml: string): string {\n\t\tconst lines = highlightedHtml.split('\\n')\n\t\tconst highlightedLines = this.getHighlightedLines()\n\n\t\treturn lines\n\t\t\t.map((line, index) => {\n\t\t\t\tconst lineNumber = index + 1\n\t\t\t\tconst isHighlighted = highlightedLines.has(lineNumber)\n\t\t\t\tconst lineClass = isHighlighted ? 'code-line highlighted' : 'code-line'\n\n\t\t\t\tlet content = ''\n\t\t\t\tif (this.lineNumbers) {\n\t\t\t\t\tcontent += `<span class=\"line-number\">${lineNumber}</span>`\n\t\t\t\t}\n\t\t\t\tcontent += line\n\n\t\t\t\treturn `<div class=\"${lineClass}\">${content}</div>`\n\t\t\t})\n\t\t\t.join('')\n\t}\n\n\tprivate async copyCode() {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(this.code)\n\t\t\tthis.copied = true\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.copied = false\n\t\t\t}, 2000)\n\t\t} catch (err) {\n\t\t\tconsole.error('Failed to copy code:', err)\n\t\t}\n\t}\n\n\tprivate getLanguageLabel(): string {\n\t\tconst languageMap: Record<string, string> = {\n\t\t\tjavascript: 'JavaScript',\n\t\t\ttypescript: 'TypeScript',\n\t\t\thtml: 'HTML',\n\t\t\tmarkdown: 'Markdown',\n\t\t\tbash: 'Bash',\n\t\t}\n\n\t\tif (this.filename) {\n\t\t\treturn this.filename\n\t\t}\n\n\t\treturn languageMap[this.language.toLowerCase()] || this.language.toUpperCase()\n\t}\n\n\trender() {\n\t\tconst codeClass = this.lineNumbers || this.highlightLines ? 'code-with-lines' : 'hljs'\n\n\t\treturn html`\n\t\t\t<schmancy-details class=\"bg-surface-default\">\n\t\t\t\t<section slot=\"summary\">\n\t\t\t\t\t<!-- Header -->\n\t\t\t\t\t<div class=\"flex items-center justify-between\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<div class=\"flex gap-1.5\">\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-error);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-tertiary);\"></div>\n\t\t\t\t\t\t\t\t<div class=\"w-3 h-3 rounded-full opacity-60\" style=\"background-color: var(--md-sys-color-secondary);\"></div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<span class=\"text-xs font-medium opacity-70 ml-2\" style=\"color: var(--md-sys-color-on-surface-variant);\">\n\t\t\t\t\t\t\t\t${this.getLanguageLabel()}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t${this.copyButton\n\t\t\t\t\t\t\t? html`\n\t\t\t\t\t\t\t\t\t<schmancy-button\n\t\t\t\t\t\t\t\t\t\t.variant=\"${this.copied ? 'filled tonal' : 'text'}\"\n\t\t\t\t\t\t\t\t\t\t@click=${this.copyCode}\n\t\t\t\t\t\t\t\t\t\tclass=\"transition-all\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<schmancy-icon > ${this.copied ? 'check' : 'content_copy'} </schmancy-icon>\n\t\t\t\t\t\t\t\t\t\t<span class=\"ml-1\">${this.copied ? 'Copied!' : 'Copy'}</span>\n\t\t\t\t\t\t\t\t\t</schmancy-button>\n\t\t\t\t\t\t\t\t`\n\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t\t<!-- Code -->\n\t\t\t\t<div class=\"overflow-auto\" style=\"${this.maxHeight ? `max-height: ${this.maxHeight}` : ''}\">\n\t\t\t\t\t<pre class=\"m-0\"><code class=\"${codeClass}\">${unsafeHTML(this.highlightedCode)}</code></pre>\n\t\t\t\t</div>\n\t\t\t</schmancy-details>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code': SchmancyCode\n\t}\n}\n","import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { timer } from 'rxjs'\nimport { take } from 'rxjs/operators'\n\n/**\n * @element schmancy-code-preview\n * A component that shows code and its rendered preview side by side\n * Takes the content as a slot and displays both the source and rendered result\n */\n@customElement('schmancy-code-preview')\nexport class SchmancyCodePreview extends TailwindElement(\n\tcss`:host{\n\t\tdisplay:block;\n\t\toverflow:hidden;\n\t\tposition:relative;\n\t\tinset:0;\n\t}`\n) {\n\t/**\n\t * Programming language for syntax highlighting\n\t */\n\t@property({ type: String })\n\tlanguage: string = 'html'\n\n\t/**\n\t * Show code on top or side-by-side\n\t */\n\t@property({ type: String })\n\tlayout: 'vertical' | 'horizontal' = 'vertical'\n\n\t/**\n\t * Whether to render/execute the code in preview section\n\t * When false, only shows the code without rendering\n\t */\n\t@property({ type: Boolean })\n\tpreview: boolean = true\n\n\t@state()\n\tprivate slotContent: string = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Capture the slot content as HTML string\n\t\ttimer(0).pipe(take(1)).subscribe(() => {\n\t\t\tconst slot = this.shadowRoot?.querySelector('slot')\n\t\t\tif (slot) {\n\t\t\t\tconst nodes = slot.assignedNodes({ flatten: true })\n\t\t\t\tconst htmlStrings = nodes.map(node => {\n\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\treturn (node as HTMLElement).outerHTML\n\t\t\t\t\t} else if (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\treturn node.textContent || ''\n\t\t\t\t\t}\n\t\t\t\t\treturn ''\n\t\t\t\t})\n\t\t\t\t\n\t\t\t\t// Clean up the HTML string\n\t\t\t\tconst rawContent = htmlStrings.join('')\n\t\t\t\t\n\t\t\t\t// Find the minimum indentation (excluding empty lines)\n\t\t\t\tconst lines = rawContent.split('\\n')\n\t\t\t\tconst minIndent = lines\n\t\t\t\t\t.filter(line => line.trim().length > 0)\n\t\t\t\t\t.reduce((min, line) => {\n\t\t\t\t\t\tconst indent = line.match(/^(\\s*)/)?.[1].length || 0\n\t\t\t\t\t\treturn Math.min(min, indent)\n\t\t\t\t\t}, Infinity)\n\t\t\t\t\n\t\t\t\t// Remove the minimum indentation from all lines\n\t\t\t\tthis.slotContent = lines\n\t\t\t\t\t.map(line => line.slice(minIndent))\n\t\t\t\t\t.join('\\n')\n\t\t\t\t\t.trim()\n\t\t\t}\n\t\t})\n\t}\n\n\trender() {\n\t\tconst containerClass = this.layout === 'horizontal' \n\t\t\t? 'grid grid-cols-1 lg:grid-cols-2 gap-0' \n\t\t\t: 'flex flex-col'\n\n\t\tconst showPreview = this.preview && this.language.toLowerCase() === 'html'\n\t\t\n\t\treturn html`\n\t\t\t<schmancy-surface class=\"rounded-lg overflow-hidden\">\n\t\t\t\t<div class=\"${showPreview ? containerClass : ''}\">\n\t\t\t\t\t<!-- Code section with proper overflow handling -->\n\t\t\t\t\t<div class=\"min-w-0 overflow-hidden\">\n\t\t\t\t\t\t<schmancy-code\n\t\t\t\t\t\t\tlanguage=\"${this.language}\"\n\t\t\t\t\t\t\t.code=\"${this.slotContent}\"\n\t\t\t\t\t\t\t?copyButton=\"${true}\"\n\t\t\t\t\t\t\tclass=\"block w-full\"\n\t\t\t\t\t\t></schmancy-code>\n\t\t\t\t\t</div>\n\t\t\t\t\t\n\t\t\t\t\t<!-- Preview section (only visible for HTML and when preview is enabled) -->\n\t\t\t\t\t${showPreview ? html`\n\t\t\t\t\t\t<div class=\"min-w-0 overflow-auto\">\n\t\t\t\t\t\t\t<schmancy-surface type=\"solid\" class=\"p-2 h-full\">\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t\t</schmancy-surface>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t` : html`\n\t\t\t\t\t\t<!-- Hidden slot to capture content -->\n\t\t\t\t\t\t<div class=\"hidden\">\n\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`}\n\t\t\t\t</div>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-code-preview': SchmancyCodePreview\n\t}\n}"],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|