Skip to content

Commit

Permalink
Feature Supported: available in live-preview mode
Browse files Browse the repository at this point in the history
  • Loading branch information
lijyze committed Jun 15, 2022
1 parent 2810791 commit 4c4bfba
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 31 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,20 @@ All features won't apply universally, if you need any feature, you need to corre

## Notice

- **Code block won't update if you only change params of blocks.**
- **Code block won't update in preview mode if you only change params of blocks.**

Obsidian cache every section of artical, but it directly ignore anything follows the first space after ```` ```language ````. Which means if you only change params of a code block, obsidian will think nothing has been changed, so it won't call any post processor in preview view render process.

## Manually installing the plugin

- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/obsidian-advanced-codeblock/`.

## Releases

### 1.1.0

1. Funcitonalities are available in live-preview mode!

## Donating

<a href="https://www.buymeacoffee.com/lijyze" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png" alt="Buy Me A Coffee" style="height: 40px !important;width: 160px !important;" ></a>
21 changes: 16 additions & 5 deletions lib/prism-line-highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ export function extendLineHighlightPlugin (Prism) {
if (hasLineNumbers && Prism.plugins.lineNumbers) {
var startNode = Prism.plugins.lineNumbers.getLine(pre, start);
var endNode = Prism.plugins.lineNumbers.getLine(pre, end);
let i = 1, element = endNode;
while (element.previousSibling) {
element = element.previousSibling
i++;
}

if (startNode) {
var top = startNode.offsetTop + codePreOffset + 'px';
Expand All @@ -176,12 +181,18 @@ export function extendLineHighlightPlugin (Prism) {
});
}

if (endNode) {
var height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';
mutateActions.push(function () {
line.style.height = height;
});
if (start === end && end > i) {
mutateActions.pop();
return ;
} else {
if (endNode) {
var height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';
mutateActions.push(function () {
line.style.height = height;
});
}
}

} else {
mutateActions.push(function () {
line.setAttribute('data-start', String(start));
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-advanced-codeblock",
"name": "Advanced Codeblock",
"version": "1.0.3",
"version": "1.1.0",
"minAppVersion": "0.12.0",
"description": "Give additioinal features to code blocks.",
"author": "Lijyze",
Expand Down
99 changes: 83 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
"@types/prismjs": "^1.26.0",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"@codemirror/language": "^0.19.0",
"@codemirror/stream-parser": "https://github.com/lishid/stream-parser",
"builtin-modules": "^3.2.0",
"esbuild": "0.13.12",
"obsidian": "latest",
"tslib": "2.3.1",
"typescript": "4.4.4"
},
"dependencies": {
"prismjs": "^1.28.0"
}
}
126 changes: 126 additions & 0 deletions src/CM6Extensions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { ViewPlugin, ViewUpdate, EditorView, DecorationSet, Decoration, WidgetType } from '@codemirror/view'
import { RangeSetBuilder } from '@codemirror/rangeset'
import { syntaxTree } from '@codemirror/language'
import { lineClassNodeProp } from '@codemirror/stream-parser'
import { braceSurroundingRegex, paramRegex } from './util'

interface CodeblockInfo {
showLineNumbers: boolean;
highlightLines: number[] | null;
}

class LineNumberWidget extends WidgetType {
idx: number;

constructor(idx: number) {
super();
this.idx = idx
}

toDOM() {
const el = document.createElement('span');
el.className = 'live-preview-codeblock-line-nums';
el.textContent = '' + this.idx;
return el;
}
}

export const livePreviewCM6Extension = ViewPlugin.fromClass(class {
decorations: DecorationSet

constructor(view: EditorView) {
this.decorations = this.buildDecorations(view);
}

update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) this.decorations = this.buildDecorations(update.view);
}

destory() {}

buildDecorations(view: EditorView) {
const builder = new RangeSetBuilder<Decoration>();
const codeblockInfo: CodeblockInfo = {
showLineNumbers: false,
highlightLines: null,
}
let idx = 1;

for (const {from, to} of view.visibleRanges) {
try {
const tree = syntaxTree(view.state)

tree.iterate({
from, to,
enter: (type, from, to) => {
const lineClasses = type.prop(lineClassNodeProp)

if (!lineClasses) return ;
const classes = new Set(lineClasses.split(' '));
const isCodeblockBegin = classes.has('HyperMD-codeblock-begin');
const isCodeblockLine =
classes.has('HyperMD-codeblock-bg')
&& !classes.has('HyperMD-codeblock-begin')
&& !classes.has('HyperMD-codeblock-end');

// reset data when found codeblock begin line.
if (isCodeblockBegin) {
idx = 1;
const codeblockParams = view.state.doc.lineAt(from).text.match(paramRegex).slice(1);
const highlightParam = codeblockParams.find((param) => braceSurroundingRegex.test(param))?.slice(1, -1);
codeblockInfo.showLineNumbers = false;
codeblockInfo.highlightLines = null;

if (codeblockParams.includes('nums')) codeblockInfo.showLineNumbers = true;
if (highlightParam) codeblockInfo.highlightLines = highlightParam.replace(' ', '').split(',').flatMap((line) => {
if (!+line) {
const res = [];
const [start, end] = line.split('-');
for (let i = +start; i <= +end; i++) {
res.push(i);
}

return res;
}

return [+line];
});
}
if (!isCodeblockLine) return ;

if (codeblockInfo.showLineNumbers) {
const deco = Decoration.widget({
widget: new LineNumberWidget(idx)
});
builder.add(from, from, deco);
}

if (codeblockInfo.highlightLines) {
if (codeblockInfo.highlightLines.includes(idx)) {
const line = view.state.doc.lineAt(from);
const deco = Decoration.line({
attributes: {class: 'live-preview-codeblock-highlight'}
})

// @ts-ignore
deco.startSide = builder.last.startSide;
deco.endSide = deco.startSide

builder.add(line.from, line.from, deco);
}
}

idx++;
}
})
} catch (error) {
console.log(error)
}
}

return builder.finish();
}
},
{
decorations: v => v.decorations
})
6 changes: 5 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Plugin } from "obsidian";
import { commonCodeblockPostProcessor } from "./postProcessor";
import { livePreviewCM6Extension } from './CM6Extensions';

export default class ObsidianAdvancedCodeblockPlugin extends Plugin {
async onload() {
console.log("Loading Advanced Codeblock");

// Handle every code blocks
// Add functionality to live-preview mode
this.registerEditorExtension([livePreviewCM6Extension]);

// Add functionality to preview mode
this.registerMarkdownPostProcessor((element, context) => {
commonCodeblockPostProcessor(element, context, this.app, this);
});
Expand Down
Loading

0 comments on commit 4c4bfba

Please sign in to comment.