wscode
Version:
🎉 An Editor Used on the Browser Side.
689 lines (516 loc) • 22.7 kB
HTML
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="shortcut icon" href="./logo.png">
<style>
body {
margin: 0;
}
div#wscode {
width: 100vw;
height: 100vh;
}
.github {
position: fixed;
transform: rotate(45deg);
top: 60px;
line-height: 1.6em;
right: -60px;
background-color: #9e9695;
outline: 4px solid #9e9695;
transform-origin: 150px 23px;
border: 2px dashed #faf6f5;
width: 300px;
text-align: center;
color: #f7f3f2;
z-index: 2;
font-family: sans-serif;
text-decoration: none;
}
</style>
<!-- 本地最新 -->
<!-- <script src="./dist/wscode.js"></script> -->
<!-- CDN最新 -->
<script src="https://cdn.jsdelivr.net/npm/wscode"></script>
<title>Example | Web Studio Code</title>
<script>
// 合并内容
var toShaderReult = function (words) {
var resultData = [[]], lineNum = 0;
words.forEach(word => {
var codeArray = word.content.split(/\n/);
resultData[lineNum].push({
color: word.color,
content: codeArray[0]
});
for (var index = 1; index < codeArray.length; index++) {
lineNum += 1;
resultData.push([]);
resultData[lineNum].push({
color: word.color,
content: codeArray[index]
});
}
});
return resultData;
};
// JS关键字
var keyWords = [
"abstract", "arguments", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "debugger", "default", "delete", "do",
"double", "else", "enum", "eval", "export",
"extends", "false", "final", "finally", "float",
"for", "function", "goto", "if", "implements",
"import", "in", "instanceof", "int", "interface",
"let", "long", "native", "new", "null",
"package", "private", "protected", "public", "return",
"short", "static", "super", "switch", "synchronized",
"this", "throw", "throws", "transient", "true",
"try", "typeof", "var", "void", "volatile",
"while", "with", "yield"
];
function _inner_CSS_shader(textString, colors) {
var shaderArray = [];
// 当前面对的
var i = 0;
// 获取往后n个值
var nextNValue = function (n) {
return textString.substring(i, n + i > textString.length ? textString.length : n + i);
};
var template = "";
// 1:选择器 tag
// 2:属性名 attr
// 3:属性值 string
var state = "tag";
// 初始化模板,开始文本捕获
var initTemplate = function () {
if (template != "") {
shaderArray.push({
color: colors[state],
content: template
});
}
template = "";
};
while (true) {
/* 1.注释 */
if (nextNValue(2) == '/*') {
initTemplate();
while (nextNValue(2) !== '*/' && i < textString.length) {
template += textString[i++];
}
shaderArray.push({
color: colors.annotation,
content: template + nextNValue(2)
});
i += 2;
template = "";
}
/* 2.字符串 */
else if (["'", '"'].indexOf(nextNValue(1)) > -1) {
var strBorder = nextNValue(1);
initTemplate();
do {
template += textString[i++];
} while (nextNValue(1) != strBorder && i < textString.length)
// 因为可能是没有字符导致的结束
if (nextNValue(1) != strBorder) {
strBorder = "";
} else {
i += 1;
}
shaderArray.push({
color: colors.string,
content: template + strBorder
});
template = "";
}
/* 3.边界 */
else if ([":", '{', '}', ";"].indexOf(nextNValue(1)) > -1) {
initTemplate();
shaderArray.push({
color: colors.border,
content: nextNValue(1)
});
template = "";
if (nextNValue(1) == '{' || nextNValue(1) == ';') {
state = 'attr';
} else if (nextNValue(1) == '}') {
state = 'tag';
} else {
state = 'string';
}
i += 1;
}
/* 追加字符 */
else {
if (i >= textString.length) {
initTemplate();
break;
} else {
template += textString[i++];
}
}
}
return shaderArray;
}
function _inner_ES_shader(textString, colors) {
var shaderArray = [];
// 当前面对的
var i = 0;
// 获取往后n个值
var nextNValue = function (n) {
return textString.substring(i, n + i > textString.length ? textString.length : n + i);
};
var template = "";
// 初始化模板,开始文本捕获
var initTemplate = function () {
if (template != "") {
// 考虑开始的(s
if (template[0] == '(') {
shaderArray.push({
color: colors.border,
content: "("
});
template = template.substr(1);
}
shaderArray.push({
color: colors.text,
content: template
});
}
template = "";
};
while (true) {
/* 1.注释1 */
if (nextNValue(2) == '/*') {
initTemplate();
while (nextNValue(2) !== '*/' && i < textString.length) {
template += textString[i++];
}
shaderArray.push({
color: colors.annotation,
content: template + nextNValue(2)
});
i += 2;
template = "";
}
/* 2.注释2 */
else if (nextNValue(2) == '//') {
initTemplate();
while (nextNValue(1) !== '\n' && i < textString.length) {
template += textString[i++];
}
shaderArray.push({
color: colors.annotation,
content: template
});
template = "";
}
/* 3.字符串 */
else if (["'", '"', '`'].indexOf(nextNValue(1)) > -1) {
var strBorder = nextNValue(1);
initTemplate();
do {
template += textString[i++];
} while (nextNValue(1) != strBorder && i < textString.length)
// 因为可能是没有字符导致的结束
if (nextNValue(1) != strBorder) {
strBorder = "";
} else {
i += 1;
}
shaderArray.push({
color: colors.string,
content: template + strBorder
});
template = "";
}
/* 4.函数定义 */
else if (nextNValue(1) == '(' && (template[0] == ' ' || (i - template.length - 1 >= 0 && textString[i - template.length - 1] == " "))) {
shaderArray.push({
color: colors.tag,
content: template
});
i += 1;
template = "(";
}
/* 5.方法调用 */
else if (nextNValue(1) == '(') {
shaderArray.push({
color: colors.attr,
content: template
});
i += 1;
template = "(";
}
/* 6.边界 */
else if ([";", '{', '}', '(', ')', '.', '\n', '=', '+', '>', '<', '[', ']', '-', '*', '/', '^', '*', '!'].indexOf(nextNValue(1)) > -1) {
initTemplate();
shaderArray.push({
color: colors.border,
content: nextNValue(1)
});
template = "";
i += 1;
}
/* 7.关键字 */
else if (nextNValue(1) == ' ' && keyWords.indexOf(template.trim()) > -1) {
shaderArray.push({
color: colors.key,
content: template + " "
});
template = "";
i += 1;
}
/* 追加字符 */
else {
if (i >= textString.length) {
initTemplate();
break;
} else {
template += textString[i++];
}
}
}
return shaderArray;
}
/**
* HTML着色器
*/
function HTML_shader(textString) {
var colors = {
"annotation": "#6a9955",/*注释颜色*/
"border": "#ffffff",/*边界颜色*/
"tag": "#1e50b3",/*结点颜色*/
"attr": "#1e83b1",/*属性颜色*/
"string": "#ac4c1e",/*字符串颜色*/
"key": "#ff0000"/*关键字颜色*/
};
var shaderArray = [];
// 当前面对的
var i = 0;
// 获取往后n个值
var nextNValue = function (n) {
return textString.substring(i, n + i > textString.length ? textString.length : n + i);
};
var template = "";
// 初始化模板,开始文本捕获
var initTemplate = function () {
if (template != "") {
shaderArray.push({
color: colors.text,
content: template
});
}
template = "";
};
// 匹配属性值模板
var getAttrValueTemplate = function () {
var endStr = " ";
// 寻找属性值边界
if (nextNValue(1) == '"') endStr = '"';
if (nextNValue(1) == "'") endStr = "'";
// 到达边界前一直寻找下一个
do {
template += textString[i++];
} while (nextNValue(1) != endStr && i < textString.length);
// 如果是匹配成功而不是匹配到末尾
if (endStr != " " && i < textString.length) {
template += endStr;
i += 1;
}
shaderArray.push({
color: colors.string,
content: template
});
template = "";
};
while (true) {
/* 1.注释 */
if (nextNValue(4) == '<!--') {
initTemplate();
while (nextNValue(3) !== '-->' && i < textString.length) {
template += textString[i++];
}
shaderArray.push({
color: colors.annotation,
content: template + nextNValue(3)
});
i += 3;
template = "";
}
/* 2.</ */
else if (nextNValue(2) == '</') {
initTemplate();
shaderArray.push({
color: colors.border,
content: "</"
});
i += 2;
while (nextNValue(1) !== '>' && i < textString.length) {
template += textString[i++];
}
if (template != "") {
shaderArray.push({
color: colors.tag,
content: template
});
template = "";
if (i < textString.length) {
shaderArray.push({
color: colors.border,
content: ">"
});
i += 1;
}
}
}
/* 3.< */
else if (nextNValue(1) == '<' && nextNValue(2) != '< ') {
var specialTag = "";
initTemplate();
shaderArray.push({
color: colors.border,
content: "<"
});
i += 1;
// 寻找标签名称
while (nextNValue(1) != '>' && nextNValue(1) != ' ' && i < textString.length) {
template += textString[i++];
}
if (template != '') {
// 针对style和script这样特殊的标签,内部需要调用对应的着色器着色
if (template == "style" || template == 'script') {
specialTag = "</" + template + ">";
}
shaderArray.push({
color: colors.tag,
content: template
});
template = '';
if (i < textString.length) {
// 寻找标签属性
while (i < textString.length) {
// 遇到这个表示标签结束了
// 也就意味着标签匹配结束
if (nextNValue(1) == ">") {
initTemplate();
shaderArray.push({
color: colors.border,
content: ">"
});
i += 1;
break;
}
// 如果是空格,表示是属性之间,接着查看下一个即可
else if (nextNValue(1) != ' ') {
initTemplate();
// 匹配属性名称
if (nextNValue(1) != '"' && nextNValue(1) != "'") {
// 如果不是=或>和空格就继续
while (nextNValue(1) != "=" && nextNValue(1) != '>' && i < textString.length && nextNValue(1) != " ") {
template += textString[i++];
}
if (template != "") {
shaderArray.push({
color: colors.attr,
content: template
});
template = "";
// 如果下一个是=,就接着找属性值
if (nextNValue(1) == '=') {
shaderArray.push({
color: colors.text,
content: "="
});
i += 1;
if (i < textString.length && nextNValue(1) != " " && nextNValue(1) != '>') {
// 寻找属性值
getAttrValueTemplate();
}
}
} else {
template += textString[i++];
}
} else if (nextNValue(1) == '=') {
shaderArray.push({
color: colors.text,
content: "="
});
i += 1;
} else {
if (i < textString.length && nextNValue(1) != " " && nextNValue(1) != '>') {
getAttrValueTemplate();
}
}
} else {
template += textString[i++];
}
}
}
}
if (specialTag != "") {
var oldI = i, oldTemplate = template;
while (nextNValue(specialTag.length) != specialTag && i < textString.length) {
template += textString[i++];
}
if (i < textString.length) {
var innerShaderArray = {
"style>": _inner_CSS_shader,
"script>": _inner_ES_shader
}[specialTag.replace(/<\//, '')](template, colors);
innerShaderArray.forEach(innerShader => {
shaderArray.push(innerShader);
});
template = "";
} else {
template = oldTemplate;
i = oldI;
}
}
}
/* 追加字符 */
else {
if (i >= textString.length) {
initTemplate();
break;
} else {
template += textString[i++];
}
}
}
return toShaderReult(shaderArray);
}
</script>
</head>
<body>
<a href="https://github.com/yelloxing/Web-Studio-Code" class='github' target="_blank">Fork me on Github</a>
<div id="wscode"></div>
<script>
window.wscode = new WSCode({
// 编辑器挂载点
el: document.getElementById('wscode'),
// 设置字体
"font-family": "serif",
// 设置字重
"font-weight": 800,
// 设置tab代表多少空格
tabSpace: 2,
// 着色器
shader: HTML_shader,
// 初始化文本
content: "<html lang=\"zh-cn\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Example | Web Studio Code</title>\n <style>\n /*css样式*/\n body {\n margin: 0px;\n }\n </style>\n</head>\n<body>\n <script>\n\n /*js代码*/\n function doit() {\n console.log('你好,世界!');\n }\n\n \</script\>\n</body>\n</html>\n\n<!-- Developed by 心叶(yelloxing@gmail.com) -->"
});
console.log(wscode);
// 通过这个钩子,可以监听编辑器数据的改变
wscode.updated(function(){
console.log('数据更新了'+new Date());
});
</script>
</body>
</html>