Skip to content

Commit

Permalink
Merge pull request #18 from obgnail/dev
Browse files Browse the repository at this point in the history
添加fence_enhance
  • Loading branch information
obgnail authored Jul 18, 2023
2 parents 301781f + 21dfb3a commit cfa0ad8
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 49 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
| 4 | commander | 命令行环境 ||
| 5 | read_only | 只读模式 ||
| 6 | collapse_paragraph | 章节折叠 ||
| 7 | copy_code | 一键复制代码 ||
| 7 | fence_enhance | 一键复制代码,折叠代码 ||
| 8 | resize_table | 调整表格行高列宽 ||
| 9 | resize_image | 调整图片显示大小 ||
| 10 | go_top | 一键到文章顶部 ||
Expand Down Expand Up @@ -193,9 +193,13 @@ ctrl+鼠标滚轮滚动,修改图片大小。



### copy_code:一键复制代码
### fence_enhance:一键复制代码,折叠代码

![copy_code](assets/copy_code.png)
![fence_enhance](assets/fence_enhance.png)

> Fold、Copy 可选,如不需要,可以关闭任意一个。
> fence_enhance.js 易于扩展,你可以根据自己的需要添加功能,比如显示代码块编程语言。


Expand Down
Binary file added assets/fence_enhance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 100 additions & 45 deletions plugin/copy_code.js → plugin/fence_enhance.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(() => {
/* 1. Typora是延迟加载页面的,文件内容都是通过延迟执行的js写入document的,具体代码在frame.js中$__System.registerDynamic函数中。
2. 糟糕的是md-fences在frame.js中是很晚生成的,并且有清空innerHTML操作的,你必须等到frame.js执行完毕后才能你的脚本,使用onload,DOMContentLoaded,statechange什么的都不行。
2. 糟糕的是md-fences在frame.js中是很晚生成的,并且有清空innerHTML操作的,你必须等到frame.js执行完毕后才能执行你的脚本,使用onload,DOMContentLoaded,statechange什么的都不行。
否则你插入的标签都会被清空,一切白费。原因很简单:frame.js执行的时机很晚,你可以认为是一个在网页全部加载完毕后执行的Ajax请求。
3. 这里给出清空md-fences的函数链条,打个断点就知道了:
restoreEditStateFromData -> refresh -> refreshUnder -> refreshEditor -> addCodeBlock -> b.addClass("ty-contain-cm").html("");
Expand All @@ -14,6 +14,13 @@
const config = {
// 启用脚本,若为false,以下配置全部失效
ENABLE: true,
// 启用复制代码功能
ENABLE_COPY: true,
// 启用折叠代码功能
ENABLE_FOLD: true,
// 折叠形式
FOLD_OVERFLOW: "hidden",

LOOP_DETECT_INTERVAL: 20,
CLICK_CHECK_INTERVAL: 300,
}
Expand All @@ -24,18 +31,24 @@

(() => {
const css = `
#write .md-fences .typora-copy-code {
#write .md-fences .fence-enhance {
display: inline-flex;
position: absolute;
top: .1em;
right: .5em;
z-index: 99999;
z-index: 8;
}
#write .fence-enhance .typora-copy-code, .typora-fold-code {
opacity: 0.5;
color: #4183C4;
opacity: 0.6;
font-weight: bold;
border-bottom: 1px solid #4183C4;
cursor: pointer;
border-bottom: 1px solid #4183C4;
}
#write .fence-enhance .typora-copy-code {
margin-left: 10px;
}
#write .md-fences .typora-copy-code.copied {
#write .fence-enhance .typora-copy-code.copied, .typora-fold-code.folded {
color: purple;
border-color: purple;
}
Expand All @@ -46,63 +59,86 @@
document.getElementsByTagName("head")[0].appendChild(style);
})()

const addCopyElement = (target) => {
let a = target.querySelector(".typora-copy-code");
if (!a) {
a = document.createElement("a");
a.setAttribute("class", "typora-copy-code");
a.innerText = "Copy";
target.appendChild(a);
}
}
const addEnhanceElement = fence => {
let enhance = fence.querySelector(".fence-enhance");
if (!enhance) {
enhance = document.createElement("div");
enhance.setAttribute("class", "fence-enhance");

if (config.ENABLE_FOLD) {
const foldButton = document.createElement("div");
foldButton.classList.add("typora-fold-code");
foldButton.innerText = "Fold";
enhance.appendChild(foldButton);
}

const decorator = (original, after) => {
return function () {
const result = original.apply(this, arguments);
after.call(this, result, ...arguments);
return result;
};
}
if (config.ENABLE_COPY) {
const copyButton = document.createElement("div");
copyButton.classList.add("typora-copy-code");
copyButton.innerText = "Copy";
enhance.appendChild(copyButton);
}

const after = (result, ...args) => {
const cid = args[0];
if (cid) {
const ele = document.querySelector(`#write .md-fences[cid=${cid}]`);
addCopyElement(ele);
fence.appendChild(enhance);
}
}

const _timer = setInterval(() => {
if (File && File.editor && File.editor.fences && File.editor.fences.addCodeBlock) {
clearInterval(_timer);

const decorator = (original, after) => {
return function () {
const result = original.apply(this, arguments);
after.call(this, result, ...arguments);
return result;
};
}

const after = (result, ...args) => {
const cid = args[0];
if (cid) {
const ele = document.querySelector(`#write .md-fences[cid=${cid}]`);
addEnhanceElement(ele);
}
}
File.editor.fences.addCodeBlock = decorator(File.editor.fences.addCodeBlock, after);
}
}, config.LOOP_DETECT_INTERVAL);

const badChars = [
"%E2%80%8B", // ZERO WIDTH SPACE \u200b
"%C2%A0", // NO-BREAK SPACE \u00A0
"%0A" // NO-BREAK SPACE \u0A
];
const replaceChars = ["", "%20", ""];

let lastClickTime = 0;
document.getElementById("write").addEventListener("click", ev => {
const button = ev.target.closest(".typora-copy-code");
if (!button) {
const copy = config.ENABLE_COPY && ev.target.closest(".typora-copy-code");
const fold = config.ENABLE_FOLD && ev.target.closest(".typora-fold-code");
if (!copy && !fold) {
return
}

ev.preventDefault();
ev.stopPropagation();

if (copy) {
copyCode(ev, copy);
} else {
foldCode(ev, fold);
}
})

let lastClickTime = 0;
const badChars = [
"%E2%80%8B", // ZERO WIDTH SPACE \u200b
"%C2%A0", // NO-BREAK SPACE \u00A0
"%0A" // NO-BREAK SPACE \u0A
];
const replaceChars = ["", "%20", ""];

const copyCode = (ev, copyButton) => {
if (ev.timeStamp - lastClickTime < config.CLICK_CHECK_INTERVAL) {
return
}
lastClickTime = ev.timeStamp;

const lines = button.closest(".md-fences").querySelectorAll(".CodeMirror-code .CodeMirror-line")
if (!lines) {
const lines = copyButton.closest(".md-fences").querySelectorAll(".CodeMirror-code .CodeMirror-line")
if (lines.length === 0) {
return
}

Expand All @@ -123,13 +159,32 @@
const result = contentList.join("\n");
navigator.clipboard.writeText(result);

button.classList.add("copied");
button.innerText = "Copied";
copyButton.classList.add("copied");
copyButton.innerText = "Copied";
setTimeout(() => {
button.classList.remove("copied");
button.innerText = "Copy";
copyButton.classList.remove("copied");
copyButton.innerText = "Copy";
}, 1000)
})
}

const foldCode = (ev, foldButton) => {
const scroll = foldButton.closest(".md-fences").querySelector(".CodeMirror-scroll");
if (!scroll) {
return
}
document.activeElement.blur();
if (scroll.style.height && scroll.style.overflowY) {
scroll.style.height = "";
scroll.style.overflowY = "";
foldButton.classList.remove("folded");
foldButton.innerText = "Fold";
} else {
scroll.style.height = window.getComputedStyle(foldButton).lineHeight;
scroll.style.overflowY = config.FOLD_OVERFLOW;
foldButton.classList.add("folded");
foldButton.innerText = "Folded";
}
}

console.log("copy_code.js had been injected");
console.log("fence_enhance.js had been injected");
})()
2 changes: 1 addition & 1 deletion plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ window.onload = () => {
_require('truncate_text', './plugin/truncate_text.js');
_require('resize_image', './plugin/resize_image.js');
_require('commander', './plugin/commander.js');
_require('copy_code', './plugin/copy_code.js');
_require('fence_enhance', './plugin/fence_enhance.js');
_require('go_top', './plugin/go_top.js');
_require('file_counter', './plugin/file_counter.js');
_require('collapse_paragraph', './plugin/collapse_paragraph.js');
Expand Down

0 comments on commit cfa0ad8

Please sign in to comment.