马黑黑 发表于 2025-3-11 18:18

简易代码编辑器带行号版本源码

复制代码,存为本地 editor.html 或自己喜欢的名称:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>简易代码编辑器</title>
<style>
    #paBox { width: 60vw; height: 60vh; min-width: 400px; min-height: 200px; border: 1px solid rgba(0,0,0,.5); border-radius: 4px; resize: both; overflow: hidden; position: relative; display: grid; place-items: center; margin: 20px auto; }
    #paBox::before { position: absolute; content: ''; left: 0; width: 50px; height: 100%; background: #eee; }
    @media screen and (max-width: 1280px) { #paBox { width: 90vw; height: 65vh; font-size: 12px; } }
    #paBox:hover, #paBox:has(textarea:focus) { box-shadow: 2px 2px 10px rgba(0,0,0,.5); }
    #lineNumberBox, #textEditor { position: absolute; width: calc(100% - 60px); height: calc(100% - 20px); border: none; tab-size: 4; white-space: pre-wrap; word-break: break-all; box-sizing: border-box; padding: 0; font: normal 16px/20px Consolas,'Consolas', 'Courier New', Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; overflow: hidden auto; scroll-padding: 8px; }
    #textEditor { right: 0; resize: none; outline: none; }
    #lineNumberBox { counter-reset: idxNum 0; left: 0; pointer-events: none; }
    #lineNumberBox > div { counter-increment: idxNum 1; position: relative; color: transparent; }
    #lineNumberBox > div::before { position: absolute; content: counter(idxNum); min-width: 30px; text-align: right; cursor: pointer; color: rgba(0,0,0,.3); pointer-events: auto; }
    #lineNumberBox > div:hover::before { color: rgba(0,0,0,.7); font-weight: bold; }
    .textCenter { text-align: center; }
</style>
</head>
<body>

<h2 class="textCenter">简易代码编辑器</h2>
<div id="paBox">
    <div id="lineNumberBox"><div></div></div>
    <textarea id="textEditor" placeholder="输入CSS+HTML+JS代码..." autofocus></textarea>
</div>
<div class="textCenter"><button class="preview-btn" onclick="preView()" title="预览效果">运行代码</button></div>

<script>
const lineNumberBox = document.getElementById('lineNumberBox');

const getCurrentLineIndent = () => {
    const cursorPos = textEditor.selectionStart;
    const content = textEditor.value;
    let lineStart = content.lastIndexOf('\n', cursorPos - 1) + 1;
    const line = content.slice(lineStart, cursorPos);
    return line.match(/^[\t ]*/)?. || '';
};

const insertTextAtCursor = (text) => {
    const start = textEditor.selectionStart;
    const end = textEditor.selectionEnd;
    const content = textEditor.value;
    textEditor.value = content.slice(0, start) + text + content.slice(end);
    textEditor.selectionStart = textEditor.selectionEnd = start + text.length;
};

const insertLineNumber = () => {
    const textAr = textEditor.value.replace(/[<>]/g, (match) => match === '<' ? '&lt;' : '&gt;').split('\n');
    let resTxt = '';
    textAr.forEach((a, k) => {
      resTxt += `<div onclick="selectLine(${k})">${a || '<br>'}</div>`;
    });
    lineNumberBox.innerHTML = resTxt;
};

const selectLine = (num) => {
    let mpos, tstr = '';
    let ar = textEditor.value.split('\n');
    for (j = 0; j < num; j ++) {
      tstr += ar + 2;
    }
    mpos = tstr.length;
    textEditor.setSelectionRange(mpos, mpos + ar.length);
    textEditor.focus();
};

const preView = () => {
      const value = textEditor.value;
      window.localStorage.setItem('ed1', value);
      const previewWindow = window.open('', 'preview1', 'width=1200,height=768');
      previewWindow.document.open();
      previewWindow.document.write(value);
      previewWindow.document.close();
    }

textEditor.onkeydown = (e) => {
    if (e.key === 'Tab') {
      e.preventDefault();
      insertTextAtCursor('\t');
    }
    if (e.key === 'Enter') {
      e.preventDefault();
      const indent = getCurrentLineIndent();
      insertTextAtCursor('\n' + indent);
      insertLineNumber();
    }
};

textEditor.oninput = () => insertLineNumber();
textEditor.onscroll = () =>lineNumberBox.scrollTop = textEditor.scrollTop;
lineNumberBox.onwheel = (e) => e.preventDefault();
paBox.onmouseenter = () => textEditor.focus();
textEditor.value = window.localStorage.getItem('ed1');
insertLineNumber();
textEditor.setSelectionRange(0, 0);
</script>

</body>
</html>

马黑黑 发表于 2025-3-11 18:30

这个就不在这里演示了,也不提供文档下载,自己保存为所需文件名的文档即可。用记事本保存的话注意一下编码类型是否是utf-8,如果不是可能会对中文支持不好。

马黑黑 发表于 2025-3-11 18:32

想一睹芳容再决定是否存留的,可以方法这里:

http://qhxy.52qingyin.cn/pencilcode/editor.html

马黑黑 发表于 2025-3-11 18:34

代码行数在超出 999 行的,行号都可以一看,超过1000行代码的行号可能会显得有点拥挤

花飞飞 发表于 2025-3-11 18:49

马黑黑 发表于 2025-3-11 18:30
这个就不在这里演示了,也不提供文档下载,自己保存为所需文件名的文档即可。用记事本保存的话注意一下编码 ...

新的编辑器更新了,加上了行号。。收到收到。。小哥哥你真帅。。{:4_170:}

花飞飞 发表于 2025-3-11 18:52

马黑黑 发表于 2025-3-11 18:32
想一睹芳容再决定是否存留的,可以方法这里:

http://qhxy.52qingyin.cn/pencilcode/editor.html

好么,这里也更新好了。。。我把之前桌面存的都替换一下下{:4_173:}

花飞飞 发表于 2025-3-11 18:53

马黑黑 发表于 2025-3-11 18:34
代码行数在超出 999 行的,行号都可以一看,超过1000行代码的行号可能会显得有点拥挤

做贴子连三百都少见,更别说三九了。。{:4_173:}
音画爱好者的福星。。

红影 发表于 2025-3-11 19:09

这个好,存下来,随时可以在本地使用了。谢谢黑黑{:4_187:}

红影 发表于 2025-3-11 19:17

好东西啊,赶紧保存了{:4_187:}

马黑黑 发表于 2025-3-11 19:20

红影 发表于 2025-3-11 19:17
好东西啊,赶紧保存了

不知道本地运行的咋样?有问题说说

马黑黑 发表于 2025-3-11 19:21

红影 发表于 2025-3-11 19:09
这个好,存下来,随时可以在本地使用了。谢谢黑黑

加了行号,加了自动保存(只要预览过的就覆盖保存)

马黑黑 发表于 2025-3-11 19:21

花飞飞 发表于 2025-3-11 18:53
做贴子连三百都少见,更别说三九了。。
音画爱好者的福星。。

一般100行左右用这个没问题

马黑黑 发表于 2025-3-11 19:22

花飞飞 发表于 2025-3-11 18:52
好么,这里也更新好了。。。我把之前桌面存的都替换一下下

用编辑器打开它,覆盖代码即可

马黑黑 发表于 2025-3-11 19:22

花飞飞 发表于 2025-3-11 18:49
新的编辑器更新了,加上了行号。。收到收到。。小哥哥你真帅。。

{:4_203:}

花飞飞 发表于 2025-3-11 19:32

马黑黑 发表于 2025-3-11 19:21
一般100行左右用这个没问题

经你封装之后,目前做贴子代码是越来越少。{:4_173:}
一百行 的也少见。。
能自动保存这个太好了。。
我恨不得PS也给它加个自动保存,可惜都得手动

花飞飞 发表于 2025-3-11 19:33

马黑黑 发表于 2025-3-11 19:22
用编辑器打开它,覆盖代码即可

你这是专业操作。我这次存和上次存的名字不一样。一个有行号一个没行号。{:4_173:}

花飞飞 发表于 2025-3-11 19:34

马黑黑 发表于 2025-3-11 19:22


新款武器没几天就有升级版了。。乐一个{:4_173:}

马黑黑 发表于 2025-3-11 19:34

花飞飞 发表于 2025-3-11 19:33
你这是专业操作。我这次存和上次存的名字不一样。一个有行号一个没行号。

都行。两个的功能其实是一样的,然后它自动保存的会彼此覆盖

马黑黑 发表于 2025-3-11 19:34

花飞飞 发表于 2025-3-11 19:32
经你封装之后,目前做贴子代码是越来越少。
一百行 的也少见。。
能自动保存这个太好了。。


PS可以设置自动保存的

马黑黑 发表于 2025-3-11 19:35

花飞飞 发表于 2025-3-11 19:34
新款武器没几天就有升级版了。。乐一个
该乐乐乐
页: [1] 2 3 4 5 6 7 8
查看完整版本: 简易代码编辑器带行号版本源码