import { html, LitElement, css, nothing, PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { tailwind } from "./tailwind"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; import { query } from "lit/decorators/query.js"; import SDUIUtils from "../core/components/functional/sdui/sdui-utils"; import "./prism/prism"; import { prismCSS } from "./prism"; import * as Prism from "prismjs"; import "prismjs/plugins/normalize-whitespace/prism-normalize-whitespace"; import "prismjs/components/prism-json"; // Language import "prismjs/components/prism-typescript"; // Language import "prismjs/components/prism-javascript"; // Language import "prismjs/components/prism-bash"; // Language // import "prismjs/components/prism-css"; // Language import "prismjs/components/prism-markup"; // Language const tagName = "sonic-code"; @customElement(tagName) export class DocsCode extends LitElement { static styles = [ tailwind, prismCSS, css` :host(:not([inline])) { display: block; margin: 1rem 0; } :host([inline]) { display: inline-block; } pre { font-size: 13px !important; padding-right: 5rem !important; } .custom-scroll { overflow: auto !important; } .custom-scroll:hover::-webkit-scrollbar-thumb { box-shadow: inset 0 0 2rem 2rem var(--sc-scrollbar-bg); } .custom-scroll::-webkit-scrollbar { opacity: 0; width: 0.5rem; height: 0.5rem; border: solid 0.15rem transparent; border-radius: var(--sc-rounded); background: transparent; } .custom-scroll::-webkit-scrollbar-thumb { box-shadow: none; transition: box-shadow 0.2s; border-radius: var(--sc-rounded); border: solid 0.15rem transparent; } `, ]; //SETTINGS @property({ type: Boolean, reflect: true }) inline = false; @property({ type: Boolean, reflect: true }) showCode = false; @property({ type: Boolean, reflect: true }) toggleCode = false; @property({ type: Boolean, reflect: true }) noEdit = false; @property({ type: Boolean, reflect: true }) noOutput = false; @property() language = "markup"; @property() defaultCode?: string; @property() currentCode?: string; @property() codeOutput?: string; //ELEMENTS @property() templateEl: HTMLTemplateElement | null; @query("#codePreview") codePreview; @query("#codeRender") codeRender; //States @state() codeEdited = false; // createRenderRoot() { // return this; // } connectedCallback() { super.connectedCallback(); if (!this.toggleCode) { this.showCode = true; } this.templateEl = this.querySelector("template"); this.defaultCode = this.templateEl?.innerHTML .toString() .replace(/</g, "<") .replace(/>/g, ">"); if (this.defaultCode) { Prism.plugins.NormalizeWhitespace.setDefaults({ "remove-trailing": true, "remove-indent": true, "left-trim": true, "right-trim": true, "remove-initial-line-feed": true, "tabs-to-tabs": 2, }); const nw = Prism.plugins.NormalizeWhitespace; const normalizedCode = nw .normalize(this.defaultCode) .replaceAll('=""', "") .replaceAll(""", '"') .replaceAll('"{', "'{") .replaceAll('}"', "}'") .replaceAll("&", "&"); this.currentCode = Prism.highlight( normalizedCode, Prism.languages[this.language], this.language ); } this.codeOutput = this.defaultCode; } updateCodeRender() { if (this.defaultCode !== this.currentCode) { this.codeEdited = true; } this.codeOutput = this.codePreview?.innerText; } resetCode() { this.codeEdited = false; if (this.defaultCode) { this.currentCode = ""; window.requestAnimationFrame(() => { this.currentCode = Prism.highlight( this.defaultCode || "", Prism.languages[this.language], this.language ); }); } this.codeOutput = this.defaultCode; } handleToggleCode() { this.showCode = !this.showCode; } handleCopyCode(e: Event) { if (this.codeOutput) { navigator.clipboard.writeText(this.codeOutput); const button = e.currentTarget as HTMLButtonElement; button?.setAttribute("active", ""); setTimeout(() => { button?.removeAttribute("active"); }, 500); } } updated(changedProperties: PropertyValues) { super.updated(changedProperties); if (changedProperties.has("codeOutput")) { this.appendOutput(); } } appendOutput() { let output = this.querySelector("[slot=output]") as HTMLElement; if (!output) { output = document.createElement("div"); output.setAttribute("slot", "output"); this.appendChild(output); } if (output) { output.innerHTML = this.codeOutput || ""; } } handleGetSDUI() { SDUIUtils.toJson(this.templateEl?.content.children); } render() { // ${this.language === "markup" ? html`
${unsafeHTML(this.codeOutput || "")}
` : nothing} // return html`
${this.language === "markup" && !this.noOutput ? html`` : nothing}
${this.codeEdited ? html`` : nothing} ${this.language == "markup" ? html` SDUI ` : nothing} ${this.toggleCode ? html` ` : nothing}
${unsafeHTML(this.currentCode)}
`; } }