Last active
August 13, 2024 15:38
-
-
Save pedrovhb/4693d04dbb967262944ad9ff2e89e6a6 to your computer and use it in GitHub Desktop.
CSS Highlights API syntax highlighting code custom element
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div><div> | |
<script type="module"> | |
import { LitElement, html, css } from 'https://esm.sh/lit'; | |
import "https://esm.sh/[email protected]"; | |
class HlCode extends LitElement { | |
static properties = { | |
lang: { type: String } | |
}; | |
static styles = css` | |
pre { | |
background-color: #f4f4f4; | |
padding: 1em; | |
border-radius: 5px; | |
overflow-x: auto; | |
} | |
code { | |
font-family: 'Consolas', 'Monaco', 'Andale Mono', 'Ubuntu Mono', monospace; | |
} | |
::highlight(syntax-highlight-keyword) { color: #07a; } | |
::highlight(syntax-highlight-function) { color: #DD4A68; } | |
::highlight(syntax-highlight-string) { color: #690; } | |
::highlight(syntax-highlight-punctuation) { color: #999; } | |
::highlight(syntax-highlight-operator) { color: #9a6e3a; } | |
::highlight(syntax-highlight-comment) { color: slategray; } | |
`; | |
render() { | |
return html` | |
<pre><code id="codeBlock"><slot></slot></code></pre> | |
`; | |
} | |
firstUpdated() { | |
this.updateComplete.then(() => { | |
this.highlightCode(); | |
}); | |
} | |
highlightCode() { | |
const codeBlock = this.shadowRoot.querySelector("#codeBlock"); | |
const code = this.textContent.trim(); | |
if (codeBlock && window.CSS && CSS.highlights) { | |
const highlighters = {}; | |
const language = Prism.languages[this.lang] || Prism.languages.javascript; | |
const tokens = Prism.tokenize(code, language); | |
console.log('Code:', code); | |
console.log('Tokens:', tokens); | |
codeBlock.textContent = code; | |
let currentPosition = 0; | |
tokens.forEach(token => { | |
const content = typeof token === 'string' ? token : token.content; | |
const type = typeof token === 'string' ? 'text' : token.type; | |
if (!highlighters[type]) { | |
highlighters[type] = new Highlight(); | |
} | |
if (codeBlock.firstChild) { | |
const range = new Range(); | |
range.setStart(codeBlock.firstChild, currentPosition); | |
range.setEnd(codeBlock.firstChild, currentPosition + content.length); | |
highlighters[type].add(range); | |
} | |
currentPosition += content.length; | |
}); | |
Object.entries(highlighters).forEach(([type, highlighter]) => { | |
CSS.highlights.set(`syntax-highlight-${type}`, highlighter); | |
}); | |
console.log('Highlighting complete'); | |
} else { | |
console.error("codeBlock not found in shadow DOM or CSS.highlights not supported"); | |
} | |
} | |
} | |
customElements.define('hl-code', HlCode); | |
</script> | |
<hl-code lang="python">def foo() -> int: | |
return 42</hl-code> | |
</div></div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment