完善代码组件;修复代码沙盒组件
parent
b8b72dd1ea
commit
3eafe5ca05
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@bd/ui",
|
"name": "@bd/ui",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"description": "",
|
"description": "",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/*"
|
"dist/*"
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
/**
|
||||||
|
* 简单的代码着色 (html, css, js)
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2021/01/30 14:00:12
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DOCTYPE_EXP = /<\!DOCTYPE html>/
|
||||||
|
const TAG_START_EXP = /<([\w\-]+)([\w\W]*?)>/g
|
||||||
|
const TAG_END_EXP = /<\/([\w\-]+)>/g
|
||||||
|
const TAG_ATTR_EXP =
|
||||||
|
/[@a-zA-Z\-.]+=(["'])[^"]+\1|[@a-zA-Z\-.]+=[a-zA-Z0-9]+|[@a-zA-Z\-.]+/g
|
||||||
|
const TAG_CM_EXP = /<!--([\w\W]*?)-->/g
|
||||||
|
const SCRIPT_TAG = /(<script[^>]*?>)([\w\W]*?)(<\/script>)/g
|
||||||
|
const IMPORT_1 = /import (['"])([^'"]*?)\1/g
|
||||||
|
const IMPORT_2 = /import ([\w\W]*?) from (['"])([^'"]*?)\2/g
|
||||||
|
const IMPORT_3 = /import\((['"])([^'"]*?)\1\)/g
|
||||||
|
const KEYWOWRD1 =
|
||||||
|
/\b(var|const|let|function|for|switch|with|if|else|export|import|assert|as|from|async|await|break|continue|return|class|try|catch|throw|new|while|this|super|default|case|debugger|delete|do|goto|in|static|get|set|public|private|protected|package|typeof|void)\b/g
|
||||||
|
const KEYWOWRD2 = /\s(=|-|\+|\/|\*|<|>|%)\s/g
|
||||||
|
const KEYWOWRD3 =
|
||||||
|
/(\+\=|-=|\/=|\*=|--|\+\+|===|==|=>|\.\.\.|\.|\?\.|\?\?|&&|\|\|)/g
|
||||||
|
const BUILDIN1 = /\b(null|undefined|true|false|NaN|Infinity)\b/g
|
||||||
|
const BUILDIN2 =
|
||||||
|
/\b(Object|String|Array|Boolean|Number|Function|class|Promise|Map|Set|WeakMap|WeakSet|URL)\b/g
|
||||||
|
const STR = /(['"`])(.*?)(?<!\\)\1/g
|
||||||
|
const NUM = /\b(\d+)\b/g
|
||||||
|
const FN = /([\.\s])([a-zA-Z$_#][\da-zA-Z_]*)\s?(\(.*?\)?)/g
|
||||||
|
const CM1 = /(?=\s)?([ ]*\/\/.*)|(^\/\/.*)/g
|
||||||
|
const CM2 = /\/\*([\w\W]*?)\*\//g
|
||||||
|
const EXP = /([=\(][ ]*)\/(.+?)\/([gmi]*)/g
|
||||||
|
const INLINE = {
|
||||||
|
code: /`([^`]*?[^`\\\s])`/g,
|
||||||
|
codeBlock: /^```(.*?)$/gm,
|
||||||
|
strong: [/__([\s\S]*?[^\s\\])__(?!_)/g, /\*\*([\s\S]*?[^\s\\])\*\*(?!\*)/g],
|
||||||
|
em: [/_([\s\S]*?[^\s\\_])_(?!_)/g, /\*([\s\S]*?[^\s\\*])\*(?!\*)/g],
|
||||||
|
del: /~~([\s\S]*?[^\s\\~])~~/g,
|
||||||
|
qlinkVar: /^\[(\d+)\]: ([\S]+)\s*?((['"])[\s\S]*?\4)?\s*?$/gm, // 引用声明
|
||||||
|
qlink: /\[([^\]]*?)\]\[(\d*?)\]/g, // 引用链接
|
||||||
|
img: /\!\[([^\]]*?)\]\(([^)]*?)\)/g,
|
||||||
|
a: /\[([^\]]*?)\]\(([^)]*?)(\s+"([\s\S]*?)")*?\)/g,
|
||||||
|
head: /^(#{1,6} )(.*)$/gm,
|
||||||
|
quote: /^(>{1,} )(.*)$/gm,
|
||||||
|
task: /^([\-\+\*]) \[( |x)\] (.*)$/gm,
|
||||||
|
list: /^([ \t]*?([\-\+\*]|\d+\.) )(.*)$/gm,
|
||||||
|
br: /^([\-\*_=]{3})(.*?)$/gm
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJs(code) {
|
||||||
|
return code
|
||||||
|
.replace(IMPORT_1, (m, pun, dep) => {
|
||||||
|
return `import ${pun}[link]${dep}[/link]${pun}`
|
||||||
|
})
|
||||||
|
.replace(IMPORT_2, (m, alias, pun, dep) => {
|
||||||
|
alias = alias.replace(/(\{|\}|,)/g, '[cm]$1[/cm]')
|
||||||
|
return `import ${alias} from ${pun}[link]${dep}[/link]${pun}`
|
||||||
|
})
|
||||||
|
.replace(IMPORT_3, (m, pun, dep) => {
|
||||||
|
return `import(${pun}[link]${dep}[/link]${pun})`
|
||||||
|
})
|
||||||
|
.replace(EXP, (m, pun, str, flag) => {
|
||||||
|
str = str.replace(/&/g, '&').replace(/(\\.)/g, '[fn]$1[/fn]')
|
||||||
|
|
||||||
|
return `${pun}[type]/[/type][cm]${str}[/cm][type]/[/type]${
|
||||||
|
flag ? `[num]${flag}[/num]` : ''
|
||||||
|
}`
|
||||||
|
})
|
||||||
|
.replace(FN, '$1[fn]$2[/fn]$3')
|
||||||
|
.replace(KEYWOWRD1, '[key]<em>$1</em>[/key]')
|
||||||
|
.replace(KEYWOWRD2, ' [key]$1[/key] ')
|
||||||
|
.replace(KEYWOWRD3, '[key]$1[/key]')
|
||||||
|
.replace(BUILDIN1, '[num]<em>$1</em>[/num]')
|
||||||
|
.replace(BUILDIN2, '[type]<strong><em>$1</em></strong>[/type]')
|
||||||
|
.replace(NUM, '[num]$1[/num]')
|
||||||
|
.replace(STR, (m, pun, str) => {
|
||||||
|
if (str.startsWith('[link]') && str.endsWith('[/link]')) {
|
||||||
|
str = str.slice(6, -7).replace(/\[(\w+)\](.*?)\[\/\1\]/g, '$2')
|
||||||
|
return `[cm]${pun}[/cm][link]${str}[/link][cm]${pun}[/cm]`
|
||||||
|
}
|
||||||
|
str = str
|
||||||
|
.replace(/\[(\w+)\](.*?)\[\/\1\]/g, '$2')
|
||||||
|
.replace(/<(\/?)xmp>/g, '<$1xmp>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/(\\.)/g, '[fn]$1[/fn]')
|
||||||
|
|
||||||
|
return `[cm]${pun}[/cm][str]${str}[/str][cm]${pun}[/cm]`
|
||||||
|
})
|
||||||
|
.replace(CM1, (m, str) => {
|
||||||
|
if (str.includes('[/link]') || str.includes('[link]')) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
str = str
|
||||||
|
.replace(/\[(\w+)\](.*?)\[\/\1\]/g, '$2')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
return `[cm]${str}[/cm]`
|
||||||
|
})
|
||||||
|
.replace(CM2, (m, str) => {
|
||||||
|
str = str
|
||||||
|
.replace(/\[(\w+)\](.*?)\[\/\1\]/g, '$2')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
|
||||||
|
str = `/*${str}*/`.split('\n').map(s => `[cm]${s}[/cm]`)
|
||||||
|
return str.join('\n')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function rebuild(code) {
|
||||||
|
// console.log(code)
|
||||||
|
return code
|
||||||
|
.replace(/\[(\/?)tag\]/g, (m, s) => (s ? '</i>' : '<i class="r">'))
|
||||||
|
.replace(/\[(\/?)attr\]/g, (m, s) => (s ? '</i>' : '<i class="b">'))
|
||||||
|
.replace(/\[(\/?)str\]/g, (m, s) => (s ? '</i>' : '<i class="g">'))
|
||||||
|
.replace(/\[(\/?)key\]/g, (m, s) => (s ? '</i>' : '<i class="r">'))
|
||||||
|
.replace(/\[(\/?)str\]/g, (m, s) => (s ? '</i>' : '<i class="g">'))
|
||||||
|
.replace(/\[(\/?)num\]/g, (m, s) => (s ? '</i>' : '<i class="pp">'))
|
||||||
|
.replace(/\[(\/?)fn\]/g, (m, s) => (s ? '</i>' : '<i class="b">'))
|
||||||
|
.replace(/\[(\/?)cm\]/g, (m, s) => (s ? '</i>' : '<i class="gr">'))
|
||||||
|
.replace(/\[(\/?)type\]/g, (m, s) => (s ? '</i>' : '<i class="o">'))
|
||||||
|
.replace(/\[(\/?)link\]/g, (m, s) => (s ? '</i>' : '<i class="link">'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorMd(code) {
|
||||||
|
code = code
|
||||||
|
.replace(INLINE.head, '[cm]$1[/cm][tag]<strong>$2</strong>[/tag]')
|
||||||
|
.replace(INLINE.br, '[cm]$1[/cm][tag]$2[/tag]')
|
||||||
|
.replace(INLINE.quote, '[cm]$1[/cm]<em>$2</em>')
|
||||||
|
.replace(
|
||||||
|
INLINE.task,
|
||||||
|
'[cm]$1 [[/cm][attr]$2[/attr][cm]][/cm] <strong>$3</strong>'
|
||||||
|
)
|
||||||
|
.replace(INLINE.list, '[cm]$1[/cm]<strong>$3</strong>')
|
||||||
|
.replace(INLINE.code, '[cm]`[/cm][tag]$1[/tag][cm]`[/cm]')
|
||||||
|
.replace(INLINE.codeBlock, '[cm]```[/cm][tag]$1[/tag]')
|
||||||
|
.replace(INLINE.strong[0], '[cm]__[/cm]<strong>$1</strong>[cm]__[/cm]')
|
||||||
|
.replace(INLINE.strong[1], '[cm]**[/cm]<strong>$1</strong>[cm]**[/cm]')
|
||||||
|
.replace(INLINE.em[0], '[cm]_[/cm]<em>$1</em>[cm]_[/cm]')
|
||||||
|
.replace(INLINE.em[1], '[cm]*[/cm]<em>$1</em>[cm]*[/cm]')
|
||||||
|
.replace(INLINE.del, '[cm]~~[/cm]<del>$1</del>[cm]~~[/cm]')
|
||||||
|
.replace(
|
||||||
|
INLINE.qlinkVar,
|
||||||
|
'[[attr]$1[/attr]]: [link]$2[/link] [tag]$3[/tag]'
|
||||||
|
)
|
||||||
|
.replace(INLINE.qlink, '[[attr]$1[/attr]][[link]$2[/link]]')
|
||||||
|
.replace(INLINE.img, '![[attr]$1[/attr]]([link]$2[/link])')
|
||||||
|
.replace(INLINE.a, (m1, txt, link, m2, attr = '') => {
|
||||||
|
if (attr) {
|
||||||
|
attr = ` "[tag]${attr}[/tag]"`
|
||||||
|
}
|
||||||
|
return `[[attr]${txt}[/attr]]([link]${link}[/link]${attr})`
|
||||||
|
})
|
||||||
|
return rebuild(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorHtml(code) {
|
||||||
|
code = code
|
||||||
|
.replace(DOCTYPE_EXP, '[tag]<!DOCTYPE [attr]html[/attr]>[/tag]')
|
||||||
|
.replace(SCRIPT_TAG, (m, tag1, txt, tag2) => {
|
||||||
|
return tag1 + parseJs(txt) + tag2
|
||||||
|
})
|
||||||
|
.replace(TAG_START_EXP, (m, tag, attr) => {
|
||||||
|
if (attr) {
|
||||||
|
attr = attr.replace(TAG_ATTR_EXP, function (t) {
|
||||||
|
if (~t.indexOf('=')) {
|
||||||
|
t = t.split('=')
|
||||||
|
let a = t.shift()
|
||||||
|
let b = t.join('=').replace(/(\n+)/g, '[/str]\n[str]')
|
||||||
|
return `[attr]${a}[/attr]=[str]${b}[/str]`
|
||||||
|
} else {
|
||||||
|
return `[attr]${t}[/attr]`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return `[tag]<${tag}[/tag]${attr}[tag]>[/tag]`
|
||||||
|
})
|
||||||
|
.replace(TAG_END_EXP, (m, tag) => {
|
||||||
|
return `[tag]</${tag}>[/tag]`
|
||||||
|
})
|
||||||
|
.replace(TAG_CM_EXP, '[cm]<!--$1-->[/cm]')
|
||||||
|
return rebuild(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorCss(code) {
|
||||||
|
code = code
|
||||||
|
.replace(
|
||||||
|
/:(hover|after|active|last\-child|first\-child)/g,
|
||||||
|
'<i class="o">:$1</i>'
|
||||||
|
)
|
||||||
|
.replace(/([\.#])([\w\-]+)/g, '<i class="gr">$1</i><i class="o">$2</i>')
|
||||||
|
.replace(
|
||||||
|
/([a-zA-Z\-]+):\s?([^;\n]+);?/g,
|
||||||
|
'<b class="gr">$1: </b><i class="b">$2</i><i class="gr">;</i>'
|
||||||
|
)
|
||||||
|
.replace(/([,\{\}])/g, '<i class="gr">$1</i>')
|
||||||
|
.replace(/&/g, '<i class="r">&</i>')
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorJs(code) {
|
||||||
|
return rebuild(parseJs(code))
|
||||||
|
}
|
|
@ -3,11 +3,29 @@
|
||||||
* @author yutent<yutent.io@gmail.com>
|
* @author yutent<yutent.io@gmail.com>
|
||||||
* @date 2023/03/20 18:02:01
|
* @date 2023/03/20 18:02:01
|
||||||
*/
|
*/
|
||||||
import { html, css, Component, nextTick } from '@bd/core'
|
import { html, raw, css, Component, nextTick } from '@bd/core'
|
||||||
|
import { colorHtml, colorJs, colorCss, colorMd } from './colorful.js'
|
||||||
|
import '../icon/index.js'
|
||||||
|
import '../layer/index.js'
|
||||||
|
|
||||||
|
function trim(str) {
|
||||||
|
return str
|
||||||
|
.trim()
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
}
|
||||||
|
|
||||||
class Code extends Component {
|
class Code extends Component {
|
||||||
static props = {
|
static props = {
|
||||||
code: { type: String, default: '', attribute: false },
|
code: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
attribute: false,
|
||||||
|
observer(v) {
|
||||||
|
this.setCode(v.trim())
|
||||||
|
}
|
||||||
|
},
|
||||||
lang: ''
|
lang: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +78,17 @@ class Code extends Component {
|
||||||
background: var(--color-green-1);
|
background: var(--color-green-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.act {
|
||||||
|
--size: 18px;
|
||||||
|
margin: 0 6px;
|
||||||
|
color: var(--color-grey-2);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-grey-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -95,21 +124,94 @@ class Code extends Component {
|
||||||
content: counter(code);
|
content: counter(code);
|
||||||
counter-increment: code;
|
counter-increment: code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.r {
|
||||||
|
color: var(--color-red-2);
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
color: var(--color-blue-2);
|
||||||
|
}
|
||||||
|
.g {
|
||||||
|
color: var(--color-green-2);
|
||||||
|
}
|
||||||
|
.gr {
|
||||||
|
color: var(--color-grey-2);
|
||||||
|
}
|
||||||
|
.o {
|
||||||
|
color: var(--color-orange-1);
|
||||||
|
}
|
||||||
|
.pp {
|
||||||
|
color: #a46ad3;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
font-style: italic;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--color-grey-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
|
#code = []
|
||||||
|
|
||||||
|
setCode(txt, a) {
|
||||||
|
let lang = this.lang
|
||||||
|
|
||||||
|
switch (lang) {
|
||||||
|
case 'js':
|
||||||
|
case 'javascript':
|
||||||
|
case 'ts':
|
||||||
|
case 'typescript':
|
||||||
|
txt = colorJs(txt)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'html':
|
||||||
|
txt = colorHtml(txt)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'css':
|
||||||
|
case 'scss':
|
||||||
|
case 'less':
|
||||||
|
txt = colorCss(txt)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'md':
|
||||||
|
case 'markdown':
|
||||||
|
txt = colorMd(txt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#code = txt.split('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
copyCode() {
|
||||||
|
navigator.clipboard.writeText(this.code)
|
||||||
|
layer.toast('复制到粘贴板成功', 'success')
|
||||||
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
var txt = this.innerHTML || this.textContent
|
var txt = this.innerHTML || this.textContent
|
||||||
txt = txt.trim().replace(/^[\r\n]|\s{2,}$/g, '')
|
txt = txt.trim().replace(/^[\r\n]|\s{2,}$/g, '')
|
||||||
|
|
||||||
if (txt.startsWith('<xmp>') && txt.endsWith('</xmp>')) {
|
if (txt.startsWith('<xmp>') && txt.endsWith('</xmp>')) {
|
||||||
txt = txt.slice(5, -6).trim()
|
txt = txt.slice(5, -6).trim()
|
||||||
|
} else if (this.firstElementChild?.tagName === 'TEXTAREA') {
|
||||||
|
txt = this.firstElementChild.value.trim()
|
||||||
|
} else if (txt.startsWith('<pre>') && txt.endsWith('</pre>')) {
|
||||||
|
txt = trim(txt.slice(5, -6))
|
||||||
|
} else {
|
||||||
|
txt = trim(txt)
|
||||||
}
|
}
|
||||||
if (txt) {
|
|
||||||
this.textContent = ''
|
this.textContent = ''
|
||||||
|
if (txt) {
|
||||||
nextTick(_ => {
|
nextTick(_ => {
|
||||||
this.code = txt.replace(/</g, '<').replace(/>/g, '>')
|
this.code = txt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,9 +222,15 @@ class Code extends Component {
|
||||||
<header class="title">
|
<header class="title">
|
||||||
<section><i></i><i></i><i></i></section>
|
<section><i></i><i></i><i></i></section>
|
||||||
<section>${this.lang}</section>
|
<section>${this.lang}</section>
|
||||||
|
<wc-icon
|
||||||
|
title="复制"
|
||||||
|
class="act"
|
||||||
|
name="doc"
|
||||||
|
@click=${this.copyCode}
|
||||||
|
></wc-icon>
|
||||||
</header>
|
</header>
|
||||||
<div class="code-block">
|
<div class="code-block">
|
||||||
${this.code.split('\n').map(s => html`<code>${s}</code>`)}
|
${this.#code.map(s => html`<code>${raw(s)}</code>`)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|
|
@ -4,17 +4,18 @@
|
||||||
* @date 2023/03/06 15:17:25
|
* @date 2023/03/06 15:17:25
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { css, html, raw, bind, Component, nextTick, classMap } from '@bd/core'
|
||||||
css,
|
|
||||||
html,
|
|
||||||
bind,
|
|
||||||
Component,
|
|
||||||
nextTick,
|
|
||||||
styleMap,
|
|
||||||
classMap
|
|
||||||
} from '@bd/core'
|
|
||||||
import '../icon/index.js'
|
import '../icon/index.js'
|
||||||
import { gzip } from '@bytedo/gzip'
|
import { gzip } from '@bytedo/gzip'
|
||||||
|
import { colorHtml, colorJs, colorCss } from '../code/colorful.js'
|
||||||
|
|
||||||
|
function trim(str) {
|
||||||
|
return str
|
||||||
|
.trim()
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
}
|
||||||
|
|
||||||
class Sandbox extends Component {
|
class Sandbox extends Component {
|
||||||
static props = {
|
static props = {
|
||||||
|
@ -80,6 +81,7 @@ class Sandbox extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe {
|
iframe {
|
||||||
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
@ -114,9 +116,8 @@ class Sandbox extends Component {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#cache[this.tab].panel
|
this.#cache[this.tab].panel.style.display = ''
|
||||||
.$animate(true)
|
this.#cache[key].panel.style.display = 'block'
|
||||||
.then(_ => this.#cache[key].panel.$animate())
|
|
||||||
|
|
||||||
this.tab = key
|
this.tab = key
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,6 +198,7 @@ class Sandbox extends Component {
|
||||||
mounted() {
|
mounted() {
|
||||||
//
|
//
|
||||||
this.#cache.preview.panel = this.$refs.preview
|
this.#cache.preview.panel = this.$refs.preview
|
||||||
|
this.$refs.preview.style.display = 'block'
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -226,7 +228,7 @@ class Sandbox extends Component {
|
||||||
></wc-icon>
|
></wc-icon>
|
||||||
</header>
|
</header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<iframe ref="preview" #animation=${{}}></iframe>
|
<iframe ref="preview"></iframe>
|
||||||
<slot name="javascript"></slot>
|
<slot name="javascript"></slot>
|
||||||
<slot name="html"></slot>
|
<slot name="html"></slot>
|
||||||
<slot name="css"></slot>
|
<slot name="css"></slot>
|
||||||
|
@ -236,21 +238,23 @@ class Sandbox extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Lang extends Component {
|
class Lang extends Component {
|
||||||
static animation = {}
|
|
||||||
|
|
||||||
static props = {
|
static props = {
|
||||||
code: { type: String, default: '', attribute: false }
|
code: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
attribute: false,
|
||||||
|
observer(v) {
|
||||||
|
this.setCode(v.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: none;
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 10px 0;
|
background: #fff;
|
||||||
border-radius: 3px;
|
|
||||||
background: #f7f8fb;
|
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -287,21 +291,79 @@ class Lang extends Component {
|
||||||
content: counter(code);
|
content: counter(code);
|
||||||
counter-increment: code;
|
counter-increment: code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.r {
|
||||||
|
color: var(--color-red-2);
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
color: var(--color-blue-2);
|
||||||
|
}
|
||||||
|
.g {
|
||||||
|
color: var(--color-green-2);
|
||||||
|
}
|
||||||
|
.gr {
|
||||||
|
color: var(--color-grey-2);
|
||||||
|
}
|
||||||
|
.o {
|
||||||
|
color: var(--color-orange-1);
|
||||||
|
}
|
||||||
|
.pp {
|
||||||
|
color: #a46ad3;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
font-style: italic;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--color-grey-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
|
#code = []
|
||||||
|
|
||||||
|
setCode(txt, a) {
|
||||||
|
let lang = this.getAttribute('slot')
|
||||||
|
|
||||||
|
switch (lang) {
|
||||||
|
case 'javascript':
|
||||||
|
txt = colorJs(txt)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'html':
|
||||||
|
txt = colorHtml(txt)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'css':
|
||||||
|
txt = colorCss(txt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#code = txt.split('\n')
|
||||||
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
var txt = this.innerHTML || this.textContent
|
var txt = this.innerHTML || this.textContent
|
||||||
txt = txt.trim().replace(/^[\r\n]|\s{2,}$/g, '')
|
txt = txt.trim().replace(/^[\r\n]|\s{2,}$/g, '')
|
||||||
|
|
||||||
if (txt.startsWith('<xmp>') && txt.endsWith('</xmp>')) {
|
if (txt.startsWith('<xmp>') && txt.endsWith('</xmp>')) {
|
||||||
txt = txt.slice(5, -6).trim()
|
txt = txt.slice(5, -6).trim()
|
||||||
|
} else if (this.firstElementChild?.tagName === 'TEXTAREA') {
|
||||||
|
txt = this.firstElementChild.value.trim()
|
||||||
|
} else if (txt.startsWith('<pre>') && txt.endsWith('</pre>')) {
|
||||||
|
txt = trim(txt.slice(5, -6))
|
||||||
|
} else {
|
||||||
|
txt = trim(txt)
|
||||||
}
|
}
|
||||||
if (txt) {
|
|
||||||
this.textContent = ''
|
this.textContent = ''
|
||||||
|
if (txt) {
|
||||||
nextTick(_ => {
|
nextTick(_ => {
|
||||||
this.code = txt.replace(/</g, '<').replace(/>/g, '>')
|
this.code = txt
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +371,7 @@ class Lang extends Component {
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<div class="code-block">
|
<div class="code-block">
|
||||||
${this.code.split('\n').map(s => html`<code>${s}</code>`)}
|
${this.#code.map(s => html`<code>${raw(s)}</code>`)}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue