代碼增加分號

This commit is contained in:
Waiting 2023-03-14 23:55:12 +08:00
parent 65e0f28d1a
commit 5b90fcb609
8 changed files with 166 additions and 158 deletions

View file

@ -1,23 +1,31 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": { "node": true },
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off"
}
}
"root": true,
"parser": "@typescript-eslint/parser",
"env": {
"node": true
},
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"args": "none"
}
],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/semi": ["error", "always"]
}
}

View file

@ -1,7 +1,7 @@
import {Graph} from '@antv/x6';
import {Utils} from './Utils'
import {Utils} from './Utils';
const myUtils = new Utils()
const myUtils = new Utils();
// 類名稱區塊高度
const classNameBoxHeight = 30;
@ -21,11 +21,11 @@ Graph.registerPortLayout(
y: classNameBoxHeight + index * funcNameBoxHeight,
},
angle: 0,
}
})
};
});
},
//true,
)
);
/**
*
@ -135,7 +135,7 @@ Graph.registerNode(
},
},
true,
)
);
class ClassShape {
@ -148,14 +148,14 @@ class ClassShape {
public createClassShape(className: string, funcNames: string[]) {
// 計算 類聲明 圖形寬度
let maxWidth = 100
maxWidth = Math.max(maxWidth, myUtils.getTextWidth(className, "14px bold") + 60)
let maxWidth = 100;
maxWidth = Math.max(maxWidth, myUtils.getTextWidth(className, "14px bold") + 60);
funcNames.forEach((funcName: string) => {
maxWidth = Math.max(maxWidth, myUtils.getTextWidth(funcName, "13px") + 20)
})
maxWidth = Math.max(maxWidth, myUtils.getTextWidth(funcName, "13px") + 20);
});
// 定義頂部類名稱方塊
let classShape = {
const classShape = {
"id": myUtils.getClassShapeId(className, '', 'class'),
"shape": 'clazz-shape',
"label": className,
@ -167,15 +167,15 @@ class ClassShape {
"y": 100
},
"ports": [{}]
}
classShape.ports = []
};
classShape.ports = [];
// 定義下方函數名稱方塊
funcNames.forEach((funcName: string) => {
// 代碼塊 連接桩
let port = {
const port = {
"id": myUtils.getClassShapeId(className, funcName, 'function'),
"group": "list",
"attrs": {
@ -215,12 +215,12 @@ class ClassShape {
targetCodeBlock: myUtils.getCodeBlockShapeId(className, funcName),
}
}
}
classShape.ports.push(port)
})
};
classShape.ports.push(port);
});
return classShape
return classShape;
}
}
export {ClassShape}
export {ClassShape};

View file

@ -1,12 +1,12 @@
import hljs from 'highlight.js';
import {CodeData, Utils} from './Utils'
import {CodeData, Utils} from './Utils';
const myUtils = new Utils()
const myUtils = new Utils();
type CodeBlockContent = {
language: string, // 程式語言
code: string // 具體代碼
}
};
class CodeBlockShape {
@ -18,23 +18,23 @@ class CodeBlockShape {
public createCodeBlockShape(codeData: CodeData) {
// 結果對象集合
let result = []
const result = [];
// 將 CodeData 中的每個 func 的 code 轉換成 AntV 的 HTML 對象
let codeDataFuncs = codeData.funcs
const codeDataFuncs = codeData.funcs;
for (const codeDataFunc of codeDataFuncs) {
// 獲取 代碼塊字串,並分割成行
let codeText = codeDataFunc.code
let codeTextLines = codeText.split('\n')
const codeText = codeDataFunc.code;
const codeTextLines = codeText.split('\n');
// 獲取 代碼塊所需高度
let blockHeight = myUtils.getTextHeight(codeDataFunc.code) + 30;
const blockHeight = myUtils.getTextHeight(codeDataFunc.code) + 30;
// 計算代碼塊所需寬度
let blockWidth = 0
let blockWidth = 0;
for (let i = 0; i < codeTextLines.length; i++) {
blockWidth = Math.max(blockWidth, myUtils.getTextWidth(codeTextLines[i], "13px") + 60)
blockWidth = Math.max(blockWidth, myUtils.getTextWidth(codeTextLines[i], "13px") + 60);
}
// 構建 HTML 對象
@ -52,14 +52,14 @@ class CodeBlockShape {
}
},
html() {
const wrap = document.createElement('div')
wrap.innerHTML = '<pre style="padding-left: 20px">' + hljs.highlight(codeText, {language: codeDataFunc.language}).value + '</pre>'
return wrap
const wrap = document.createElement('div');
wrap.innerHTML = '<pre style="padding-left: 20px">' + hljs.highlight(codeText, {language: codeDataFunc.language}).value + '</pre>';
return wrap;
},
}
};
// 將 HTML 對象加入到返回結果中
result.push(htmlShape)
result.push(htmlShape);
}
return result;

View file

@ -1,7 +1,7 @@
import { Shape } from '@antv/x6';
import { CodeData, Utils } from './Utils'
import { CodeData, Utils } from './Utils';
const myUtils = new Utils()
const myUtils = new Utils();
class Edge {
@ -12,7 +12,7 @@ class Edge {
*/
public createFuncToCodeEdges(codeData: CodeData) {
let result = [];
const result = [];
// 遍歷所有的 函數對象,替每個 函數 與 代碼塊圖形 創建 連線對象
for (const func of codeData.funcs) {
@ -44,10 +44,10 @@ class Edge {
},
},
},
})
});
// 將 連線對象 加入到 返回結果 中
result.push(edge)
result.push(edge);
}
return result;
@ -60,7 +60,7 @@ class Edge {
*/
public createFuncCallEdges(codeData: CodeData) {
let result = [];
const result = [];
// 遍歷 CodeData 中的每個 函數對象
for (const func of codeData.funcs) {
@ -103,10 +103,10 @@ class Edge {
stroke: "#2bb37b",
},
},
})
});
// 將 連線對象 加入到 返回結果 中
result.push(edge)
result.push(edge);
}
}
@ -115,4 +115,4 @@ class Edge {
}
export { Edge }
export { Edge };

View file

@ -1,15 +1,15 @@
import {Cell, Graph, Shape} from '@antv/x6';
import {Cell, Graph} from '@antv/x6';
import {CodeBlockContent, CodeBlockShape} from './CodeBlockShape';
import {ClassShape} from './ClassShape';
import {CLASS_SHAPE_ID_TAG, CODE_BLOCK_ID_TAG, CodeData, Utils} from './Utils';
import {Edge} from './Edge'
import {Edge} from './Edge';
const myUtils = new Utils()
const codeBlockShape = new CodeBlockShape()
const classShape = new ClassShape()
const edge = new Edge()
const myUtils = new Utils();
const codeBlockShape = new CodeBlockShape();
const classShape = new ClassShape();
const edge = new Edge();
export let initGraph = function (codeBlocks: CodeBlockContent[]) {
export const initGraph = function (codeBlocks: CodeBlockContent[]) {
// 創建畫布
const graph = new Graph({
@ -26,30 +26,30 @@ export let initGraph = function (codeBlocks: CodeBlockContent[]) {
});
// 將 代碼塊字串 集合 解析成 CodeData 對象集合,並將相同 className 的對象進行合併
let codeDatas: CodeData[] = []
let codeDatas: CodeData[] = [];
codeBlocks.forEach((codeBlock: CodeBlockContent) => {
let codeData: CodeData = myUtils.parseCodeData(codeBlock)
codeDatas.push(codeData)
})
codeDatas = myUtils.mergeCodeDatas(codeDatas)
const codeData: CodeData = myUtils.parseCodeData(codeBlock);
codeDatas.push(codeData);
});
codeDatas = myUtils.mergeCodeDatas(codeDatas);
// 將 CodeData 對象列表 繪製成 類圖形、代碼塊圖形
for (const codeData of codeDatas) {
// 將 類圖形、代碼塊圖形 加入到 畫布 中
let funcNames = codeData.funcs.map(item => item.name)
graph.addNode(classShape.createClassShape(codeData.className, funcNames))
graph.addNodes(codeBlockShape.createCodeBlockShape(codeData))
const funcNames = codeData.funcs.map(item => item.name);
graph.addNode(classShape.createClassShape(codeData.className, funcNames));
graph.addNodes(codeBlockShape.createCodeBlockShape(codeData));
// 創建 函數名稱 與 代碼塊圖形 的 連線
graph.addEdges(edge.createFuncToCodeEdges(codeData))
graph.addEdges(edge.createFuncToCodeEdges(codeData));
}
// 繪製 CodeData 中的 函數調用 連線
for (const codeData of codeDatas) {
graph.addEdges(edge.createFuncCallEdges(codeData))
graph.addEdges(edge.createFuncCallEdges(codeData));
}
// 綁定 開啟/關閉 代碼塊圖形 事件
@ -57,46 +57,46 @@ export let initGraph = function (codeBlocks: CodeBlockContent[]) {
graph.on('toggle:codeBlock', ({e}) => {
// 獲取 代碼塊圖形、開關文字 對象
let codeBlock = graph.getCellById(e.currentTarget.getAttribute('target-code-block'))
let toggleText = e.currentTarget.parentNode.childNodes[5].children[0]
const codeBlock = graph.getCellById(e.currentTarget.getAttribute('target-code-block'));
const toggleText = e.currentTarget.parentNode.childNodes[5].children[0];
// 如果當前 代碼塊圖形 正在顯示,則關閉。反之則開啟
if (codeBlock.getProp().visible) {
codeBlock.hide()
toggleText.textContent = '+'
toggleText.setAttribute('dy', '0.3em')
codeBlock.hide();
toggleText.textContent = '+';
toggleText.setAttribute('dy', '0.3em');
} else {
// 計算 代碼塊 顯示位置
const intervalX = 100
const posX = e.offsetX + intervalX
const posY = e.offsetY - (codeBlock.getProp().size.height / 2)
codeBlock.prop("position", {x: posX, y: posY})
const intervalX = 100;
const posX = e.offsetX + intervalX;
const posY = e.offsetY - (codeBlock.getProp().size.height / 2);
codeBlock.prop("position", {x: posX, y: posY});
// 顯示 代碼塊,並更新按鈕內容
codeBlock.show()
toggleText.textContent = '-'
toggleText.setAttribute('dy', '0.3em')
codeBlock.show();
toggleText.textContent = '-';
toggleText.setAttribute('dy', '0.3em');
}
})
});
// 最大的 類圖形 的寬度
let maxClassShapeWidth = 0;
// 所有的 類圖形 集合
let classShapes: Cell[] = [];
const classShapes: Cell[] = [];
// 遍歷 所有的圖形
for (const node of graph.getCells()) {
// 默認隱藏所有的 代碼塊
if (node.id.startsWith(CODE_BLOCK_ID_TAG)) {
node.hide()
node.hide();
}
// 計算 類圖形 最大寬度、加入到集合中
if (node.id.startsWith(CLASS_SHAPE_ID_TAG)) {
maxClassShapeWidth = Math.max(maxClassShapeWidth, node.getProp().size.width)
classShapes.push(node)
maxClassShapeWidth = Math.max(maxClassShapeWidth, node.getProp().size.width);
classShapes.push(node);
}
}
@ -104,23 +104,23 @@ export let initGraph = function (codeBlocks: CodeBlockContent[]) {
*
*/
// 左側保留寬度
const marginLeftWidth = 100
const marginLeftWidth = 100;
// 類圖形的 Y 座標
let curY = 200
let curY = 200;
// 多個 類圖形 的 上下間格
const intervalY = 150
const intervalY = 150;
// 所有 類圖形 的 中線 X 座標
const midX = marginLeftWidth + (maxClassShapeWidth / 2)
const midX = marginLeftWidth + (maxClassShapeWidth / 2);
for (const classShape of classShapes) {
// 計算 類圖形 的 左上X 座標,並設置
const posX = midX - (classShape.getProp().size.width / 2)
classShape.prop("position", {x: posX, y: curY})
const posX = midX - (classShape.getProp().size.width / 2);
classShape.prop("position", {x: posX, y: curY});
// 下個 類圖形 的 Y 座標 = 當前 類圖形 高度 + 間隔
curY = curY + classShape.getProp().size.height + intervalY
curY = curY + classShape.getProp().size.height + intervalY;
}
}
};

View file

@ -6,7 +6,7 @@ import {CodeBlockContent} from "./CodeBlockShape";
export default class SourceCodeView extends ItemView {
// 代碼塊內容 集合
codeBlocks: CodeBlockContent[]
codeBlocks: CodeBlockContent[];
constructor(codeBlocks: CodeBlockContent[], leaf: WorkspaceLeaf) {
super(leaf);
@ -28,7 +28,7 @@ export default class SourceCodeView extends ItemView {
container.empty();
// 創建 AntV 需要的容器
const div = document.createElement("div")
const div = document.createElement("div");
div.id = 'container';
container.appendChild(div);

View file

@ -4,22 +4,22 @@ import {CodeBlockContent} from "./CodeBlockShape";
type CodeData = {
className: string, // 類名稱
funcs: CodeDataFunc[] // 函數名稱 與 代碼塊字串 集合
}
};
type CodeDataFunc = {
language: string, // 程式語言
name: string, // 函數名稱
code: string, // 代碼塊字串
calls: CodeDataFuncCall[] // 調用的函數集合
}
};
type CodeDataFuncCall = {
className: string, // 類名稱
functionName: string // 函數名稱
}
};
export const CLASS_SHAPE_ID_TAG: string = "class-";
export const CODE_BLOCK_ID_TAG: string = 'code-block-';
export const CLASS_SHAPE_ID_TAG = "class-";
export const CODE_BLOCK_ID_TAG = 'code-block-';
class Utils {
@ -43,12 +43,12 @@ class Utils {
public getTextHeight(codeText: string) {
// 創建一個新容器,將 HTML 代碼加入到容器中
let node = document.createElement('div');
const node = document.createElement('div');
node.innerHTML = '<pre style="padding-left: 20px">' + hljs.highlight(codeText, {language: 'java'}).value + '</pre>';
document.body.appendChild(node);
// 計算 容器高度
let height: number = parseInt(global.getComputedStyle(node).height.split('px')[0]);
const height: number = parseInt(global.getComputedStyle(node).height.split('px')[0]);
// 移除容器
document.body.removeChild(node);
@ -67,61 +67,61 @@ class Utils {
const content = codeBlockContent.code;
// 類名、方法名 的 標示符
const classTag = '@class'
const functionTag = '@function'
const callTag = '@call'
const classTag = '@class';
const functionTag = '@function';
const callTag = '@call';
let codeLines = content.split('\n')
const codeLines = content.split('\n');
// 取得 註釋塊 的代碼
let commentLines = []
const commentLines = [];
for (let i = 0; i < codeLines.length; i++) {
let codeLine = codeLines[i]
const codeLine = codeLines[i];
// 找到註釋開頭,則從當前行開始,加入到註釋塊列表中
if (codeLine.indexOf('/**') != -1) {
commentLines.push(codeLine)
commentLines.push(codeLine);
} else if (commentLines.length > 0) {
commentLines.push(codeLine)
commentLines.push(codeLine);
}
// 當碰到第一個多行註釋的結尾,則跳出循環
if (codeLine.indexOf('*/') != -1) {
break
break;
}
}
// 從 註釋塊 中獲取 類名、方法名、調用的函數集合
let className = ''
let functionName = ''
let calls: CodeDataFuncCall[] = []
let className = '';
let functionName = '';
const calls: CodeDataFuncCall[] = [];
commentLines.forEach((comment) => {
// 獲取 類名
if (comment.indexOf(classTag) != -1) {
className = comment.substring(comment.indexOf(classTag) + classTag.length).trim()
className = comment.substring(comment.indexOf(classTag) + classTag.length).trim();
}
// 獲取 方法名
if (comment.indexOf(functionTag) != -1) {
functionName = comment.substring(comment.indexOf(functionTag) + functionTag.length).trim()
functionName = comment.substring(comment.indexOf(functionTag) + functionTag.length).trim();
}
// 獲取 調用的函數
if (comment.indexOf(callTag) != -1) {
let callStr = comment.substring(comment.indexOf(callTag) + callTag.length).trim()
const callStr = comment.substring(comment.indexOf(callTag) + callTag.length).trim();
calls.push({
className: callStr.substring(0, callStr.indexOf('@')).trim(),
functionName: callStr.substring(callStr.indexOf('@') + 1).trim()
})
});
}
})
});
// 封裝結果
let result: CodeData = {
const result: CodeData = {
className: className,
funcs: [{
language: lang,
@ -129,9 +129,9 @@ class Utils {
code: content,
calls: calls
}]
}
};
return result
return result;
}
/**
@ -143,11 +143,11 @@ class Utils {
*/
public getClassShapeId(className: string, functionName: string, type: 'class' | 'function'): string {
if (type == 'class') {
return CLASS_SHAPE_ID_TAG + className
return CLASS_SHAPE_ID_TAG + className;
} else if (type == 'function') {
return CLASS_SHAPE_ID_TAG + className + '-' + functionName
return CLASS_SHAPE_ID_TAG + className + '-' + functionName;
}
return ''
return '';
}
/**
@ -157,7 +157,7 @@ class Utils {
* @returns Id
*/
public getCodeBlockShapeId(className: string, functionName: string): string {
return CODE_BLOCK_ID_TAG + className + '-' + functionName
return CODE_BLOCK_ID_TAG + className + '-' + functionName;
}
/**
@ -168,27 +168,27 @@ class Utils {
public mergeCodeDatas(codeDatas: CodeData[]): CodeData[] {
// 對有相同 className 的 CodeData 的 func 進行合併
let classNameToCodeData = new Map()
const classNameToCodeData = new Map();
codeDatas.forEach((codeData: CodeData) => {
// 如果在 Map 中已存在相應的 CodeData則將 func 進行合併
if (classNameToCodeData.has(codeData.className)) {
let tempCodeData = classNameToCodeData.get(codeData.className) as CodeData
tempCodeData.funcs.push(codeData.funcs[0])
const tempCodeData = classNameToCodeData.get(codeData.className) as CodeData;
tempCodeData.funcs.push(codeData.funcs[0]);
}
// 如果在 Map 中還沒有相應的 CodeData則將當前 CodeData 加入到 Map 中
else {
classNameToCodeData.set(codeData.className, codeData)
classNameToCodeData.set(codeData.className, codeData);
}
})
});
// 封裝返回結果
let result: CodeData[] = []
for (let codeData of Array.from(classNameToCodeData.values())) {
result.push(codeData)
const result: CodeData[] = [];
for (const codeData of Array.from(classNameToCodeData.values())) {
result.push(codeData);
}
return result
return result;
}
}

View file

@ -1,13 +1,13 @@
import {Plugin, Workspace, WorkspaceLeaf} from 'obsidian';
import {Plugin, WorkspaceLeaf} from 'obsidian';
import SourceCodeView from "./SourceCodeView";
import {CodeBlockContent} from "./CodeBlockShape";
export const SOURCE_CODE_VIEW_TYPE = 'source-code-view'
export const SOURCE_CODE_VIEW_TYPE = 'source-code-view';
export default class SourceCodeViewPlugin extends Plugin {
// Obsidian 中 Markdown 的 代碼塊內容 集合
codeBlockContents: CodeBlockContent[] = []
codeBlockContents: CodeBlockContent[] = [];
/**
*
@ -22,7 +22,7 @@ export default class SourceCodeViewPlugin extends Plugin {
// 註冊 Obsidian 左側的按鈕
this.addRibbonIcon("file-json", "Show Resource Code View", () => {
this.initView()
this.initView();
});
}
@ -45,7 +45,7 @@ export default class SourceCodeViewPlugin extends Plugin {
this.app.vault.process(activeFile, (data) => {
// 清理數據
this.codeBlockContents = []
this.codeBlockContents = [];
// 獲取文件內所有的 Markdown 代碼塊
const regex = /```(\w+)\s([\s\S]*?)```/gm;
@ -53,16 +53,16 @@ export default class SourceCodeViewPlugin extends Plugin {
while ((match = regex.exec(data)) !== null) {
const lang = match[1]; // 程式語言
const content = match[2]; // 代碼塊內容
this.codeBlockContents.push({language: lang, code: content})
this.codeBlockContents.push({language: lang, code: content});
}
// 開啟分頁
const preview = this.app.workspace.getLeaf('split', 'vertical')
const preview = this.app.workspace.getLeaf('split', 'vertical');
const mmPreview = new SourceCodeView(this.codeBlockContents, preview);
preview.open(mmPreview)
preview.open(mmPreview);
// 不更改文件內容
return data
return data;
});
}