mirror of
https://github.com/mayurankv/Obsidian-Code-Styler.git
synced 2026-07-22 08:10:29 +00:00
Update spacing
This commit is contained in:
parent
b58362a937
commit
c8ba7dbed7
17 changed files with 6282 additions and 6436 deletions
|
|
@ -1,10 +1,10 @@
|
|||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
# Top Level EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
|
|
|
|||
44
.eslintrc
44
.eslintrc
|
|
@ -1,23 +1,23 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -18,19 +18,19 @@ The plugin lets you customize the codeblocks in the following way:
|
|||
- Exclude languages. You can define languages separated by a comma, to which the plugin will not apply.
|
||||
- Set background color for codeblocks.
|
||||
- Lets you highlight specific lines.
|
||||
- Customize highlight color
|
||||
- Customize highlight color
|
||||
- Lets you define multiple highlight colors to highlight lines.
|
||||
- Display filename
|
||||
- If a filename is defined a header will be inserted, where it is possible to customize the text (color, bold, italic), and the header (color, header line) itself as well
|
||||
- If a filename is defined a header will be inserted, where it is possible to customize the text (color, bold, italic), and the header (color, header line) itself as well
|
||||
- Fold code
|
||||
- If the header is displayed (either by defining filename or other way explained below), you can click on the header to fold the codeblock below it
|
||||
- If the header is displayed (either by defining filename or other way explained below), you can click on the header to fold the codeblock below it
|
||||
- Display codeblock language. This displays the language (if specified) of the codeblock in the header.
|
||||
- Customize text color, background color, bold text, italic text for the language tag inside the header.
|
||||
- By default the language tag is only displayed, if the header is displayed, and a if a language is defined for a codeblock. You can however force, to always display the codeblock language, even if the header would not be displayed.
|
||||
- Customize text color, background color, bold text, italic text for the language tag inside the header.
|
||||
- By default the language tag is only displayed, if the header is displayed, and a if a language is defined for a codeblock. You can however force, to always display the codeblock language, even if the header would not be displayed.
|
||||
- Display codeblock language icon (if available for the specified language) in the header.
|
||||
- Add line numbers to codeblocks
|
||||
- Customize if the linenumber should also be highlighted, if a line is highlighted
|
||||
- Customize background color, and color of the line numbers
|
||||
- Customize if the linenumber should also be highlighted, if a line is highlighted
|
||||
- Customize background color, and color of the line numbers
|
||||
|
||||
## Themes
|
||||
|
||||
|
|
|
|||
6842
main.js
6842
main.js
File diff suppressed because one or more lines are too long
|
|
@ -5,260 +5,260 @@ import { syntaxTree } from "@codemirror/language";
|
|||
import { splitAndTrimString, searchString, getHighlightedLines, getLanguageIcon, getLanguageName, isExcluded } from "./Utils";
|
||||
|
||||
export function codeblockHighlight(settings: CodeblockCustomizerSettings) {
|
||||
const viewPlugin = ViewPlugin.fromClass(
|
||||
class CodeblockHighlightPlugin {
|
||||
decorations: DecorationSet;
|
||||
settings: CodeblockCustomizerSettings;
|
||||
prevAlternateColors: ColorSettings[];
|
||||
view: EditorView;
|
||||
mutationObserver: MutationObserver;
|
||||
prevBGColor: string;
|
||||
prevHLColor: string;
|
||||
prevExcludeLangs: string;
|
||||
prevTextColor: string;
|
||||
prevBackgroundColor: string;
|
||||
prevHighlightGutter: boolean;
|
||||
prevLineNumbers: boolean;
|
||||
const viewPlugin = ViewPlugin.fromClass(
|
||||
class CodeblockHighlightPlugin {
|
||||
decorations: DecorationSet;
|
||||
settings: CodeblockCustomizerSettings;
|
||||
prevAlternateColors: ColorSettings[];
|
||||
view: EditorView;
|
||||
mutationObserver: MutationObserver;
|
||||
prevBGColor: string;
|
||||
prevHLColor: string;
|
||||
prevExcludeLangs: string;
|
||||
prevTextColor: string;
|
||||
prevBackgroundColor: string;
|
||||
prevHighlightGutter: boolean;
|
||||
prevLineNumbers: boolean;
|
||||
|
||||
constructor(view: EditorView) {
|
||||
this.initialize(view, settings);
|
||||
}
|
||||
constructor(view: EditorView) {
|
||||
this.initialize(view, settings);
|
||||
}
|
||||
|
||||
initialize(view: EditorView, settings: CodeblockCustomizerSettings) {
|
||||
this.view = view;
|
||||
this.settings = settings;
|
||||
this.decorations = this.buildDecorations(view);
|
||||
this.prevAlternateColors = [];
|
||||
this.mutationObserver = setupMutationObserver(view, this);
|
||||
this.prevBGColor = '';
|
||||
this.prevHLColor = '';
|
||||
this.prevExcludeLangs = '';
|
||||
this.prevTextColor = '';
|
||||
this.prevBackgroundColor = '';
|
||||
this.prevHighlightGutter = false;
|
||||
this.prevLineNumbers = false;
|
||||
}// initialize
|
||||
initialize(view: EditorView, settings: CodeblockCustomizerSettings) {
|
||||
this.view = view;
|
||||
this.settings = settings;
|
||||
this.decorations = this.buildDecorations(view);
|
||||
this.prevAlternateColors = [];
|
||||
this.mutationObserver = setupMutationObserver(view, this);
|
||||
this.prevBGColor = '';
|
||||
this.prevHLColor = '';
|
||||
this.prevExcludeLangs = '';
|
||||
this.prevTextColor = '';
|
||||
this.prevBackgroundColor = '';
|
||||
this.prevHighlightGutter = false;
|
||||
this.prevLineNumbers = false;
|
||||
}// initialize
|
||||
|
||||
forceUpdate(editorView: EditorView) {
|
||||
this.view = editorView;
|
||||
this.decorations = this.buildDecorations(this.view);
|
||||
this.view.requestMeasure();
|
||||
}// forceUpdate
|
||||
forceUpdate(editorView: EditorView) {
|
||||
this.view = editorView;
|
||||
this.decorations = this.buildDecorations(this.view);
|
||||
this.view.requestMeasure();
|
||||
}// forceUpdate
|
||||
|
||||
shouldUpdate(update: ViewUpdate) {
|
||||
return (update.docChanged || update.viewportChanged || !this.compareSettings());
|
||||
}// shouldUpdate
|
||||
shouldUpdate(update: ViewUpdate) {
|
||||
return (update.docChanged || update.viewportChanged || !this.compareSettings());
|
||||
}// shouldUpdate
|
||||
|
||||
compareSettings() {
|
||||
return (
|
||||
this.settings.backgroundColor === this.prevBGColor &&
|
||||
this.settings.highlightColor === this.prevHLColor &&
|
||||
this.settings.ExcludeLangs === this.prevExcludeLangs &&
|
||||
compareArrays(this.settings.alternateColors, this.prevAlternateColors) &&
|
||||
this.settings.gutterTextColor === this.prevTextColor &&
|
||||
this.settings.gutterBackgroundColor === this.prevBackgroundColor &&
|
||||
this.settings.bGutterHighlight === this.prevHighlightGutter &&
|
||||
this.settings.bEnableLineNumbers === this.prevLineNumbers
|
||||
);
|
||||
}// compareSettings
|
||||
|
||||
updateSettings() {
|
||||
this.prevBGColor = this.settings.backgroundColor;
|
||||
this.prevHLColor = this.settings.highlightColor;
|
||||
this.prevExcludeLangs = this.settings.ExcludeLangs;
|
||||
this.prevAlternateColors = this.settings.alternateColors.map(({name}) => {
|
||||
return {name};
|
||||
});
|
||||
this.prevTextColor = this.settings.gutterTextColor;
|
||||
this.prevBackgroundColor = this.settings.gutterBackgroundColor;
|
||||
this.prevHighlightGutter = this.settings.bGutterHighlight;
|
||||
this.prevLineNumbers = this.settings.bEnableLineNumbers;
|
||||
}// updateSettings
|
||||
compareSettings() {
|
||||
return (
|
||||
this.settings.backgroundColor === this.prevBGColor &&
|
||||
this.settings.highlightColor === this.prevHLColor &&
|
||||
this.settings.ExcludeLangs === this.prevExcludeLangs &&
|
||||
compareArrays(this.settings.alternateColors, this.prevAlternateColors) &&
|
||||
this.settings.gutterTextColor === this.prevTextColor &&
|
||||
this.settings.gutterBackgroundColor === this.prevBackgroundColor &&
|
||||
this.settings.bGutterHighlight === this.prevHighlightGutter &&
|
||||
this.settings.bEnableLineNumbers === this.prevLineNumbers
|
||||
);
|
||||
}// compareSettings
|
||||
|
||||
updateSettings() {
|
||||
this.prevBGColor = this.settings.backgroundColor;
|
||||
this.prevHLColor = this.settings.highlightColor;
|
||||
this.prevExcludeLangs = this.settings.ExcludeLangs;
|
||||
this.prevAlternateColors = this.settings.alternateColors.map(({name}) => {
|
||||
return {name};
|
||||
});
|
||||
this.prevTextColor = this.settings.gutterTextColor;
|
||||
this.prevBackgroundColor = this.settings.gutterBackgroundColor;
|
||||
this.prevHighlightGutter = this.settings.bGutterHighlight;
|
||||
this.prevLineNumbers = this.settings.bEnableLineNumbers;
|
||||
}// updateSettings
|
||||
|
||||
update(update: ViewUpdate) {
|
||||
if (this.shouldUpdate(update)) {
|
||||
this.updateSettings();
|
||||
this.decorations = this.buildDecorations(update.view);
|
||||
}
|
||||
}// update
|
||||
update(update: ViewUpdate) {
|
||||
if (this.shouldUpdate(update)) {
|
||||
this.updateSettings();
|
||||
this.decorations = this.buildDecorations(update.view);
|
||||
}
|
||||
}// update
|
||||
|
||||
destroy() {
|
||||
this.mutationObserver.disconnect();
|
||||
}// destroy
|
||||
destroy() {
|
||||
this.mutationObserver.disconnect();
|
||||
}// destroy
|
||||
|
||||
filterVisibleCodeblocks(view: EditorView, codeblocks: Codeblock[]): Codeblock[] {
|
||||
return codeblocks.filter((codeblock) => {
|
||||
return view.visibleRanges.some((visibleRange) => {
|
||||
return (codeblock.from < visibleRange.to && codeblock.to > visibleRange.from);
|
||||
});
|
||||
});
|
||||
}// filterVisibleCodeblocks
|
||||
filterVisibleCodeblocks(view: EditorView, codeblocks: Codeblock[]): Codeblock[] {
|
||||
return codeblocks.filter((codeblock) => {
|
||||
return view.visibleRanges.some((visibleRange) => {
|
||||
return (codeblock.from < visibleRange.to && codeblock.to > visibleRange.from);
|
||||
});
|
||||
});
|
||||
}// filterVisibleCodeblocks
|
||||
|
||||
deduplicateCodeblocks(codeblocks: Codeblock[]): Codeblock[] {
|
||||
const deduplicatedCodeblocks = [];
|
||||
for (let i = 0; i < codeblocks.length; i++) {
|
||||
if (i === 0 || codeblocks[i].from !== codeblocks[i - 1].from) {
|
||||
deduplicatedCodeblocks.push(codeblocks[i]);
|
||||
}
|
||||
}
|
||||
return deduplicatedCodeblocks;
|
||||
}// deduplicateCodeblocks
|
||||
|
||||
buildDecorations(view: EditorView): DecorationSet {
|
||||
let lineNumber = 0;
|
||||
let HL = [];
|
||||
let altHL = [];
|
||||
let lineNumberOffset = 0;
|
||||
let showNumbers = true;
|
||||
// const Exclude = this.settings.ExcludeLangs;
|
||||
// const ExcludeLangs = splitAndTrimString(Exclude);
|
||||
let bExclude = false;
|
||||
const alternateColors = this.settings.alternateColors || [];
|
||||
const decorations = [];
|
||||
deduplicateCodeblocks(codeblocks: Codeblock[]): Codeblock[] {
|
||||
const deduplicatedCodeblocks = [];
|
||||
for (let i = 0; i < codeblocks.length; i++) {
|
||||
if (i === 0 || codeblocks[i].from !== codeblocks[i - 1].from) {
|
||||
deduplicatedCodeblocks.push(codeblocks[i]);
|
||||
}
|
||||
}
|
||||
return deduplicatedCodeblocks;
|
||||
}// deduplicateCodeblocks
|
||||
|
||||
buildDecorations(view: EditorView): DecorationSet {
|
||||
let lineNumber = 0;
|
||||
let HL = [];
|
||||
let altHL = [];
|
||||
let lineNumberOffset = 0;
|
||||
let showNumbers = true;
|
||||
// const Exclude = this.settings.ExcludeLangs;
|
||||
// const ExcludeLangs = splitAndTrimString(Exclude);
|
||||
let bExclude = false;
|
||||
const alternateColors = this.settings.alternateColors || [];
|
||||
const decorations = [];
|
||||
|
||||
if (!view.visibleRanges || view.visibleRanges.length === 0) {
|
||||
return RangeSet.empty;
|
||||
}
|
||||
|
||||
// Find all code blocks in the document
|
||||
const codeblocks = findCodeblocks(view.state, view.state.doc.from, view.state.doc.to);
|
||||
// Find code blocks that intersect with the visible range
|
||||
const visibleCodeblocks = this.filterVisibleCodeblocks(view, codeblocks);
|
||||
// remove duplicates
|
||||
const deduplicatedCodeblocks = this.deduplicateCodeblocks(visibleCodeblocks);
|
||||
if (!view.visibleRanges || view.visibleRanges.length === 0) {
|
||||
return RangeSet.empty;
|
||||
}
|
||||
|
||||
// Find all code blocks in the document
|
||||
const codeblocks = findCodeblocks(view.state, view.state.doc.from, view.state.doc.to);
|
||||
// Find code blocks that intersect with the visible range
|
||||
const visibleCodeblocks = this.filterVisibleCodeblocks(view, codeblocks);
|
||||
// remove duplicates
|
||||
const deduplicatedCodeblocks = this.deduplicateCodeblocks(visibleCodeblocks);
|
||||
|
||||
for (const codeblock of deduplicatedCodeblocks) {
|
||||
syntaxTree(view.state).iterate({ from: codeblock.from, to: codeblock.to,
|
||||
enter(node) {
|
||||
const line = view.state.doc.lineAt(node.from);
|
||||
const lineText = view.state.sliceDoc(line.from, line.to);
|
||||
const lang = searchString(lineText, "```");
|
||||
const startLine = node.type.name.includes("HyperMD-codeblock-begin")
|
||||
const endLine = node.type.name.includes("HyperMD-codeblock-end")
|
||||
if (lang) {
|
||||
bExclude = isExcluded(lineText, settings.ExcludeLangs);
|
||||
}
|
||||
if (bExclude) {
|
||||
if (endLine) {
|
||||
bExclude = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (startLine) {
|
||||
lineNumber = 0;
|
||||
lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const params = searchString(lineText, "HL:");
|
||||
HL = getHighlightedLines(params);
|
||||
altHL = [];
|
||||
for (const { name } of alternateColors) {
|
||||
const altParams = searchString(lineText, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
}
|
||||
let lineClass = 'codeblock-customizer-line';
|
||||
if (HL.includes(lineNumber)) {
|
||||
lineClass = 'codeblock-customizer-line-highlighted';
|
||||
} else {
|
||||
const altHLMatch = altHL.filter((hl) => hl.lineNumber === lineNumber);
|
||||
if (altHLMatch.length > 0) {
|
||||
lineClass = `codeblock-customizer-line-highlighted-${altHLMatch[0].name.replace(/\s+/g, '-').toLowerCase()}`;
|
||||
}
|
||||
}
|
||||
for (const codeblock of deduplicatedCodeblocks) {
|
||||
syntaxTree(view.state).iterate({ from: codeblock.from, to: codeblock.to,
|
||||
enter(node) {
|
||||
const line = view.state.doc.lineAt(node.from);
|
||||
const lineText = view.state.sliceDoc(line.from, line.to);
|
||||
const lang = searchString(lineText, "```");
|
||||
const startLine = node.type.name.includes("HyperMD-codeblock-begin")
|
||||
const endLine = node.type.name.includes("HyperMD-codeblock-end")
|
||||
if (lang) {
|
||||
bExclude = isExcluded(lineText, settings.ExcludeLangs);
|
||||
}
|
||||
if (bExclude) {
|
||||
if (endLine) {
|
||||
bExclude = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (startLine) {
|
||||
lineNumber = 0;
|
||||
lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const params = searchString(lineText, "HL:");
|
||||
HL = getHighlightedLines(params);
|
||||
altHL = [];
|
||||
for (const { name } of alternateColors) {
|
||||
const altParams = searchString(lineText, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
}
|
||||
let lineClass = 'codeblock-customizer-line';
|
||||
if (HL.includes(lineNumber)) {
|
||||
lineClass = 'codeblock-customizer-line-highlighted';
|
||||
} else {
|
||||
const altHLMatch = altHL.filter((hl) => hl.lineNumber === lineNumber);
|
||||
if (altHLMatch.length > 0) {
|
||||
lineClass = `codeblock-customizer-line-highlighted-${altHLMatch[0].name.replace(/\s+/g, '-').toLowerCase()}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type.name === "HyperMD-codeblock_HyperMD-codeblock-bg" || startLine || endLine) {
|
||||
decorations.push(Decoration.line({attributes: {class: lineClass}}).range(node.from));
|
||||
if (node.type.name === "HyperMD-codeblock_HyperMD-codeblock-bg" || startLine || endLine) {
|
||||
decorations.push(Decoration.line({attributes: {class: lineClass}}).range(node.from));
|
||||
|
||||
decorations.push(Decoration.line({}).range(node.from));
|
||||
decorations.push(Decoration.widget({ widget: new LineNumberWidget((startLine || endLine) ? " " : lineNumber+lineNumberOffset,showNumbers),}).range(node.from));
|
||||
lineNumber++;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
return RangeSet.of(decorations, true);
|
||||
}
|
||||
},// CodeblockHighlightPlugin
|
||||
{
|
||||
decorations: (value) => value.decorations,
|
||||
}
|
||||
);
|
||||
decorations.push(Decoration.line({}).range(node.from));
|
||||
decorations.push(Decoration.widget({ widget: new LineNumberWidget((startLine || endLine) ? " " : lineNumber+lineNumberOffset,showNumbers),}).range(node.from));
|
||||
lineNumber++;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
return RangeSet.of(decorations, true);
|
||||
}
|
||||
},// CodeblockHighlightPlugin
|
||||
{
|
||||
decorations: (value) => value.decorations,
|
||||
}
|
||||
);
|
||||
|
||||
viewPlugin.name = 'codeblockHighlight';
|
||||
return viewPlugin;
|
||||
viewPlugin.name = 'codeblockHighlight';
|
||||
return viewPlugin;
|
||||
}// codeblockHighlight
|
||||
|
||||
function compareArrays(array1, array2) {
|
||||
|
||||
if (array1.length !== array2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
if ((array1[i].name !== array2[i].name) || (array1[i].currentColor !== array2[i].currentColor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
if (array1.length !== array2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
if ((array1[i].name !== array2[i].name) || (array1[i].currentColor !== array2[i].currentColor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}// compareArrays
|
||||
|
||||
class LineNumberWidget extends WidgetType {
|
||||
constructor(private lineNumber: number, private showNumbers: boolean) {
|
||||
super();
|
||||
}
|
||||
constructor(private lineNumber: number, private showNumbers: boolean) {
|
||||
super();
|
||||
}
|
||||
|
||||
eq(other: LineNumberWidget) {
|
||||
return this.lineNumber === other.lineNumber && this.showNumbers === other.showNumbers;
|
||||
}
|
||||
eq(other: LineNumberWidget) {
|
||||
return this.lineNumber === other.lineNumber && this.showNumbers === other.showNumbers;
|
||||
}
|
||||
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
const container = document.createElement("span");
|
||||
container.classList.add(`codeblock-customizer-line-number${this.showNumbers?'':'-hide'}`);
|
||||
container.innerText = `${this.lineNumber}`;
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
const container = document.createElement("span");
|
||||
container.classList.add(`codeblock-customizer-line-number${this.showNumbers?'':'-hide'}`);
|
||||
container.innerText = `${this.lineNumber}`;
|
||||
|
||||
return container;
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}// LineNumberWidget
|
||||
|
||||
function findCodeblocks(doc: Text, from: number, to: number): SyntaxNode[] {
|
||||
const tree = syntaxTree(doc);
|
||||
const codeblocks: SyntaxNode[] = [];
|
||||
const tree = syntaxTree(doc);
|
||||
const codeblocks: SyntaxNode[] = [];
|
||||
|
||||
tree.iterate({ from, to,
|
||||
enter: (node) => {
|
||||
if (
|
||||
node.type.name.includes("HyperMD-codeblock-begin") ||
|
||||
node.type.name === "HyperMD-codeblock_HyperMD-codeblock-bg" ||
|
||||
node.type.name.includes("HyperMD-codeblock-end")
|
||||
) {
|
||||
codeblocks.push(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
tree.iterate({ from, to,
|
||||
enter: (node) => {
|
||||
if (
|
||||
node.type.name.includes("HyperMD-codeblock-begin") ||
|
||||
node.type.name === "HyperMD-codeblock_HyperMD-codeblock-bg" ||
|
||||
node.type.name.includes("HyperMD-codeblock-end")
|
||||
) {
|
||||
codeblocks.push(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return codeblocks;
|
||||
return codeblocks;
|
||||
}// findCodeblocks
|
||||
|
||||
function setupMutationObserver(editorView: EditorView, pluginInstance: any) { //TODO (@mayurankv) What does this do? Work out
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (
|
||||
mutation.type === "attributes" &&
|
||||
mutation.attributeName === "class" &&
|
||||
(mutation.target.classList.contains("HyperMD-codeblock-begin") ||
|
||||
mutation.target.classList.contains("HyperMD-codeblock_HyperMD-codeblock-bg") ||
|
||||
mutation.target.classList.contains("HyperMD-codeblock-end"))
|
||||
) {
|
||||
pluginInstance.forceUpdate(editorView);
|
||||
}
|
||||
}
|
||||
});
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (
|
||||
mutation.type === "attributes" &&
|
||||
mutation.attributeName === "class" &&
|
||||
(mutation.target.classList.contains("HyperMD-codeblock-begin") ||
|
||||
mutation.target.classList.contains("HyperMD-codeblock_HyperMD-codeblock-bg") ||
|
||||
mutation.target.classList.contains("HyperMD-codeblock-end"))
|
||||
) {
|
||||
pluginInstance.forceUpdate(editorView);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(editorView.dom, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributeFilter: ['class'], // Only observe changes to the 'class' attribute
|
||||
});
|
||||
observer.observe(editorView.dom, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributeFilter: ['class'], // Only observe changes to the 'class' attribute
|
||||
});
|
||||
|
||||
return observer;
|
||||
} // setupMutationObserver
|
||||
return observer;
|
||||
} // setupMutationObserver
|
||||
|
|
|
|||
1686
src/Const.ts
1686
src/Const.ts
File diff suppressed because one or more lines are too long
0
src/EditingView.ts
Normal file
0
src/EditingView.ts
Normal file
402
src/Header.ts
402
src/Header.ts
|
|
@ -4,230 +4,230 @@ import { EditorView, Decoration, WidgetType } from "@codemirror/view";
|
|||
import { searchString, getLanguageName, getLanguageIcon, isExcluded, createContainer, createWrapper, createCodeblockLang, createCodeblockIcon, createFileName } from "./Utils";
|
||||
|
||||
function defaultFold(state: EditorState, settings: CodeblockCustomizerSettings) {
|
||||
let CollapseStart = null;
|
||||
let CollapseEnd = null;
|
||||
let Fold = false;
|
||||
let blockFound = false;
|
||||
let bExclude = false;
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
for (let i = 1; i < state.doc.lines; i++) {
|
||||
const lineText = state.doc.line(i).text.toString();
|
||||
const line = state.doc.line(i);
|
||||
bExclude = isExcluded(lineText, settings.ExcludeLangs);
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (bExclude)
|
||||
continue;
|
||||
if (CollapseStart === null) {
|
||||
Fold = searchString(lineText, "fold");
|
||||
if (Fold)
|
||||
CollapseStart = line.from;
|
||||
} else {
|
||||
blockFound = true;
|
||||
CollapseEnd = line.to;
|
||||
}
|
||||
}
|
||||
let CollapseStart = null;
|
||||
let CollapseEnd = null;
|
||||
let Fold = false;
|
||||
let blockFound = false;
|
||||
let bExclude = false;
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
for (let i = 1; i < state.doc.lines; i++) {
|
||||
const lineText = state.doc.line(i).text.toString();
|
||||
const line = state.doc.line(i);
|
||||
bExclude = isExcluded(lineText, settings.ExcludeLangs);
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (bExclude)
|
||||
continue;
|
||||
if (CollapseStart === null) {
|
||||
Fold = searchString(lineText, "fold");
|
||||
if (Fold)
|
||||
CollapseStart = line.from;
|
||||
} else {
|
||||
blockFound = true;
|
||||
CollapseEnd = line.to;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockFound) {
|
||||
if (CollapseStart != null && CollapseEnd != null ){
|
||||
const decoration = Decoration.replace({ effect: Collapse.of([doFold.range(CollapseStart, CollapseEnd)]), block:true, side:-1 });
|
||||
builder.add(CollapseStart, CollapseEnd, decoration );
|
||||
CollapseStart = null;
|
||||
CollapseEnd = null;
|
||||
}
|
||||
blockFound = false;
|
||||
}
|
||||
}// for
|
||||
|
||||
return builder.finish();
|
||||
if (blockFound) {
|
||||
if (CollapseStart != null && CollapseEnd != null ){
|
||||
const decoration = Decoration.replace({ effect: Collapse.of([doFold.range(CollapseStart, CollapseEnd)]), block:true, side:-1 });
|
||||
builder.add(CollapseStart, CollapseEnd, decoration );
|
||||
CollapseStart = null;
|
||||
CollapseEnd = null;
|
||||
}
|
||||
blockFound = false;
|
||||
}
|
||||
}// for
|
||||
|
||||
return builder.finish();
|
||||
}// defaultFold
|
||||
|
||||
let settings: CodeblockCustomizerSettings;
|
||||
export const codeblockHeader = StateField.define<DecorationSet>({
|
||||
create(state): DecorationSet {
|
||||
return Decoration.none;
|
||||
},
|
||||
update(oldState: DecorationSet, transaction: Transaction): DecorationSet {
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
let WidgetStart = null;
|
||||
let Fold = false;
|
||||
let fileName = null;
|
||||
let bExclude = false;
|
||||
let specificHeader = true;
|
||||
for (let i = 1; i < transaction.state.doc.lines; i++) {
|
||||
const lineText = transaction.state.doc.line(i).text.toString();
|
||||
const line = transaction.state.doc.line(i);
|
||||
const lang = searchString(lineText, "```");
|
||||
bExclude = isExcluded(lineText, this.settings.ExcludeLangs);
|
||||
specificHeader = true;
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (WidgetStart === null) {
|
||||
WidgetStart = line;
|
||||
fileName = searchString(lineText, "file:");
|
||||
Fold = searchString(lineText, "fold");
|
||||
if (!bExclude) {
|
||||
if (fileName === null || fileName === "") {
|
||||
if (Fold) {
|
||||
fileName = 'Collapsed Code';
|
||||
} else {
|
||||
fileName = '';
|
||||
specificHeader = false;
|
||||
}
|
||||
}
|
||||
builder.add(WidgetStart.from, WidgetStart.from, createDecorationWidget(fileName, getLanguageName(lang), specificHeader));
|
||||
//EditorView.requestMeasure;
|
||||
}
|
||||
} else {
|
||||
WidgetStart = null;
|
||||
Fold = false;
|
||||
fileName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.finish();
|
||||
},
|
||||
provide(field: StateField<DecorationSet>): Extension {
|
||||
return EditorView.decorations.from(field);
|
||||
},
|
||||
create(state): DecorationSet {
|
||||
return Decoration.none;
|
||||
},
|
||||
update(oldState: DecorationSet, transaction: Transaction): DecorationSet {
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
let WidgetStart = null;
|
||||
let Fold = false;
|
||||
let fileName = null;
|
||||
let bExclude = false;
|
||||
let specificHeader = true;
|
||||
for (let i = 1; i < transaction.state.doc.lines; i++) {
|
||||
const lineText = transaction.state.doc.line(i).text.toString();
|
||||
const line = transaction.state.doc.line(i);
|
||||
const lang = searchString(lineText, "```");
|
||||
bExclude = isExcluded(lineText, this.settings.ExcludeLangs);
|
||||
specificHeader = true;
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (WidgetStart === null) {
|
||||
WidgetStart = line;
|
||||
fileName = searchString(lineText, "file:");
|
||||
Fold = searchString(lineText, "fold");
|
||||
if (!bExclude) {
|
||||
if (fileName === null || fileName === "") {
|
||||
if (Fold) {
|
||||
fileName = 'Collapsed Code';
|
||||
} else {
|
||||
fileName = '';
|
||||
specificHeader = false;
|
||||
}
|
||||
}
|
||||
builder.add(WidgetStart.from, WidgetStart.from, createDecorationWidget(fileName, getLanguageName(lang), specificHeader));
|
||||
//EditorView.requestMeasure;
|
||||
}
|
||||
} else {
|
||||
WidgetStart = null;
|
||||
Fold = false;
|
||||
fileName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.finish();
|
||||
},
|
||||
provide(field: StateField<DecorationSet>): Extension {
|
||||
return EditorView.decorations.from(field);
|
||||
},
|
||||
});// codeblockHeader
|
||||
|
||||
function createDecorationWidget(textToDisplay: string, languageName: string, specificHeader: boolean) {
|
||||
return Decoration.widget({
|
||||
widget: new TextAboveCodeblockWidget(textToDisplay, languageName, specificHeader), block: true});
|
||||
return Decoration.widget({
|
||||
widget: new TextAboveCodeblockWidget(textToDisplay, languageName, specificHeader), block: true});
|
||||
}// createDecorationWidget
|
||||
|
||||
const Collapse = StateEffect.define(), UnCollapse = StateEffect.define()
|
||||
|
||||
let pluginSettings: CodeblockCustomizerSettings;
|
||||
export const collapseField = StateField.define({
|
||||
create(state) {
|
||||
return defaultFold(state, collapseField.pluginSettings);
|
||||
//return Decoration.none
|
||||
},
|
||||
update(value, tr) {
|
||||
value = value.map(tr.changes)
|
||||
for (const effect of tr.effects) {
|
||||
if (effect.is(Collapse))
|
||||
value = value.update({add: effect.value, sort: true});
|
||||
else if (effect.is(UnCollapse))
|
||||
value = value.update({filter: effect.value});
|
||||
}
|
||||
return value;
|
||||
},
|
||||
provide: f => EditorView.decorations.from(f)
|
||||
create(state) {
|
||||
return defaultFold(state, collapseField.pluginSettings);
|
||||
//return Decoration.none
|
||||
},
|
||||
update(value, tr) {
|
||||
value = value.map(tr.changes)
|
||||
for (const effect of tr.effects) {
|
||||
if (effect.is(Collapse))
|
||||
value = value.update({add: effect.value, sort: true});
|
||||
else if (effect.is(UnCollapse))
|
||||
value = value.update({filter: effect.value});
|
||||
}
|
||||
return value;
|
||||
},
|
||||
provide: f => EditorView.decorations.from(f)
|
||||
})
|
||||
|
||||
const doFold = Decoration.replace({block: true});
|
||||
|
||||
class TextAboveCodeblockWidget extends WidgetType {
|
||||
text: string;
|
||||
observer: MutationObserver;
|
||||
view: EditorView;
|
||||
text: string;
|
||||
observer: MutationObserver;
|
||||
view: EditorView;
|
||||
|
||||
constructor(text: string, Lang: string, specificHeader: boolean) {
|
||||
super();
|
||||
this.text = text;
|
||||
this.Lang = Lang;
|
||||
this.specificHeader = specificHeader;
|
||||
this.observer = new MutationObserver(this.handleMutation);
|
||||
}
|
||||
|
||||
handleMutation = (mutations, view) => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.target.hasAttribute("data-clicked")){
|
||||
handleClick(this.view, mutation.target);
|
||||
//this.view.update([]);
|
||||
//this.view.state.update();
|
||||
//EditorView.requestMeasure;
|
||||
}
|
||||
});
|
||||
//this.view.update([]);
|
||||
//this.view.state.update();
|
||||
//this.view.requestMeasure();
|
||||
}
|
||||
|
||||
eq(other: TextAboveCodeblockWidget) {
|
||||
return other.text == this.text && other.Lang == this.Lang && other.specificHeader == this.specificHeader
|
||||
}
|
||||
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
this.view = view;
|
||||
const container = createContainer(this.specificHeader);
|
||||
if (this.Lang){
|
||||
const Icon = getLanguageIcon(this.Lang)
|
||||
if (Icon) {
|
||||
container.appendChild(createCodeblockIcon(this.Lang));
|
||||
}
|
||||
container.appendChild(createCodeblockLang(this.Lang));
|
||||
}
|
||||
constructor(text: string, Lang: string, specificHeader: boolean) {
|
||||
super();
|
||||
this.text = text;
|
||||
this.Lang = Lang;
|
||||
this.specificHeader = specificHeader;
|
||||
this.observer = new MutationObserver(this.handleMutation);
|
||||
}
|
||||
|
||||
handleMutation = (mutations, view) => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.target.hasAttribute("data-clicked")){
|
||||
handleClick(this.view, mutation.target);
|
||||
//this.view.update([]);
|
||||
//this.view.state.update();
|
||||
//EditorView.requestMeasure;
|
||||
}
|
||||
});
|
||||
//this.view.update([]);
|
||||
//this.view.state.update();
|
||||
//this.view.requestMeasure();
|
||||
}
|
||||
|
||||
eq(other: TextAboveCodeblockWidget) {
|
||||
return other.text == this.text && other.Lang == this.Lang && other.specificHeader == this.specificHeader
|
||||
}
|
||||
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
this.view = view;
|
||||
const container = createContainer(this.specificHeader);
|
||||
if (this.Lang){
|
||||
const Icon = getLanguageIcon(this.Lang)
|
||||
if (Icon) {
|
||||
container.appendChild(createCodeblockIcon(this.Lang));
|
||||
}
|
||||
container.appendChild(createCodeblockLang(this.Lang));
|
||||
}
|
||||
|
||||
container.appendChild(createFileName(this.text));
|
||||
|
||||
this.observer.view = view;
|
||||
this.observer.observe(container, { attributes: true });
|
||||
|
||||
container.addEventListener("mousedown", event => {
|
||||
container.setAttribute("data-clicked", "true");
|
||||
});
|
||||
//EditorView.requestMeasure;
|
||||
container.appendChild(createFileName(this.text));
|
||||
|
||||
this.observer.view = view;
|
||||
this.observer.observe(container, { attributes: true });
|
||||
|
||||
container.addEventListener("mousedown", event => {
|
||||
container.setAttribute("data-clicked", "true");
|
||||
});
|
||||
//EditorView.requestMeasure;
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
destroy(dom: HTMLElement) {
|
||||
dom.removeAttribute("data-clicked");
|
||||
dom.removeEventListener("mousedown", handleClick);
|
||||
this.observer.disconnect();
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
destroy(dom: HTMLElement) {
|
||||
dom.removeAttribute("data-clicked");
|
||||
dom.removeEventListener("mousedown", handleClick);
|
||||
this.observer.disconnect();
|
||||
}
|
||||
|
||||
ignoreEvent() { return false; }
|
||||
|
||||
ignoreEvent() { return false; }
|
||||
|
||||
}// TextAboveCodeblockWidget
|
||||
|
||||
|
||||
export function handleClick(view: EditorView, target: HTMLElement){
|
||||
//view.state.update();
|
||||
//view.update([]);
|
||||
//view.requestMeasure({});
|
||||
const Pos = view.posAtDOM(target);
|
||||
//view.state.update();
|
||||
//view.update([]);
|
||||
//view.requestMeasure({});
|
||||
const Pos = view.posAtDOM(target);
|
||||
|
||||
const effect = view.state.field(collapseField, false);
|
||||
let isFolded = false;
|
||||
effect.between(Pos, Pos, () => { isFolded = true});
|
||||
|
||||
let CollapseStart: number | null = null;
|
||||
let CollapseEnd: number | null = null;
|
||||
let WidgetStart: number | null = null;
|
||||
// NOTE: Can't use for loop over view.visibleRanges, because that way the closing backticks wouldn't be found and collapse would not be possible
|
||||
let blockFound = false;
|
||||
for (let i = 1; i < view.state.doc.lines; i++) {
|
||||
const lineText = view.state.doc.line(i).text.toString();
|
||||
const line = view.state.doc.line(i);
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (WidgetStart === null) {
|
||||
WidgetStart = line.from;
|
||||
if (Pos === line.from){
|
||||
CollapseStart = line.from;
|
||||
}
|
||||
} else {
|
||||
blockFound = true;
|
||||
CollapseEnd = line.to;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockFound) {
|
||||
if (CollapseStart != null && CollapseEnd != null ){
|
||||
if (isFolded){
|
||||
view.dispatch({ effects: UnCollapse.of((from, to) => to <= CollapseStart || from >= CollapseEnd) });
|
||||
}
|
||||
else {
|
||||
view.dispatch({ effects: Collapse.of([doFold.range(CollapseStart, CollapseEnd)]) });
|
||||
}
|
||||
view.requestMeasure();
|
||||
CollapseStart = null;
|
||||
CollapseEnd = null;
|
||||
}//if (CollapseStart
|
||||
WidgetStart = null;
|
||||
blockFound = false;
|
||||
}
|
||||
}// for
|
||||
}// handleClick
|
||||
const effect = view.state.field(collapseField, false);
|
||||
let isFolded = false;
|
||||
effect.between(Pos, Pos, () => { isFolded = true});
|
||||
|
||||
let CollapseStart: number | null = null;
|
||||
let CollapseEnd: number | null = null;
|
||||
let WidgetStart: number | null = null;
|
||||
// NOTE: Can't use for loop over view.visibleRanges, because that way the closing backticks wouldn't be found and collapse would not be possible
|
||||
let blockFound = false;
|
||||
for (let i = 1; i < view.state.doc.lines; i++) {
|
||||
const lineText = view.state.doc.line(i).text.toString();
|
||||
const line = view.state.doc.line(i);
|
||||
if (lineText.startsWith('```') && lineText.indexOf('```', 3) === -1) {
|
||||
if (WidgetStart === null) {
|
||||
WidgetStart = line.from;
|
||||
if (Pos === line.from){
|
||||
CollapseStart = line.from;
|
||||
}
|
||||
} else {
|
||||
blockFound = true;
|
||||
CollapseEnd = line.to;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockFound) {
|
||||
if (CollapseStart != null && CollapseEnd != null ){
|
||||
if (isFolded){
|
||||
view.dispatch({ effects: UnCollapse.of((from, to) => to <= CollapseStart || from >= CollapseEnd) });
|
||||
}
|
||||
else {
|
||||
view.dispatch({ effects: Collapse.of([doFold.range(CollapseStart, CollapseEnd)]) });
|
||||
}
|
||||
view.requestMeasure();
|
||||
CollapseStart = null;
|
||||
CollapseEnd = null;
|
||||
}//if (CollapseStart
|
||||
WidgetStart = null;
|
||||
blockFound = false;
|
||||
}
|
||||
}// for
|
||||
}// handleClick
|
||||
|
|
|
|||
|
|
@ -3,228 +3,5 @@ import { MarkdownView, MarkdownPostProcessorContext, sanitizeHTMLToDom } from "o
|
|||
import { searchString, getHighlightedLines, getLanguageName, isExcluded, getLanguageIcon, createContainer, createCodeblockLang, createCodeblockIcon, createFileName } from "./Utils";
|
||||
|
||||
export async function ReadingView(codeBlockElement: HTMLElement, context: MarkdownPostProcessorContext, plugin: CodeblockCustomizerPlugin) {
|
||||
const codeElm: HTMLElement = codeBlockElement.querySelector('pre > code');
|
||||
|
||||
if (!codeElm)
|
||||
return;
|
||||
|
||||
const classRegex = /^language-\S+/;
|
||||
const match = Array.from(codeElm.classList).some(className => classRegex.test(className));
|
||||
if (match)
|
||||
while(!codeElm.classList.contains("is-loaded"))
|
||||
await sleep(2);
|
||||
|
||||
const codeBlockSectionInfo = context.getSectionInfo(codeElm);
|
||||
|
||||
let codeBlockFirstLine = "";
|
||||
if (codeBlockSectionInfo) {
|
||||
const view = plugin.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (view && view.editor)
|
||||
codeBlockFirstLine = view.editor.getLine(codeBlockSectionInfo.lineStart);
|
||||
} else {
|
||||
// PDF export
|
||||
const file = plugin.app.vault.getAbstractFileByPath(context.sourcePath);
|
||||
if (!file) {
|
||||
//console.error(`File not found: ${context.sourcePath}`);
|
||||
return;
|
||||
}
|
||||
const cache = plugin.app.metadataCache.getCache(context.sourcePath);
|
||||
const fileContent = await plugin.app.vault.cachedRead(<TFile> file).catch((error) => {
|
||||
//console.error(`Error reading file: ${error.message}`);
|
||||
return '';
|
||||
});
|
||||
const fileContentLines = fileContent.split(/\n/g);
|
||||
const codeBlockFirstLines: string[] = [];
|
||||
|
||||
if (cache.sections) {
|
||||
for (const element of cache.sections) {
|
||||
if (element.type === 'code') {
|
||||
const lineStart = element.position.start.line;
|
||||
const codeBlockFirstLine = fileContentLines[lineStart];
|
||||
if (!isAdmonition(codeBlockFirstLine)) {
|
||||
codeBlockFirstLines.push(codeBlockFirstLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//console.error(`Metadata cache not found for file: ${context.sourcePath}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await PDFExport(codeBlockElement, plugin, codeBlockFirstLines);
|
||||
} catch (error) {
|
||||
//console.error(`Error exporting to PDF: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const codeBlockLang = searchString(codeBlockFirstLine, "```");
|
||||
const highlightedLinesParams = searchString(codeBlockFirstLine, "HL:");
|
||||
const linesToHighlight = getHighlightedLines(highlightedLinesParams);
|
||||
const FileName = searchString(codeBlockFirstLine, "file:");
|
||||
const Fold = searchString(codeBlockFirstLine, "fold");
|
||||
const lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
const showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const alternateColors = plugin.settings.alternateColors || [];
|
||||
let altHL = [];
|
||||
for (const { name } of alternateColors) {
|
||||
const altParams = searchString(codeBlockFirstLine, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
|
||||
let isCodeBlockExcluded = false;
|
||||
isCodeBlockExcluded = isExcluded(codeBlockFirstLine, plugin.settings.ExcludeLangs);
|
||||
|
||||
const codeElements = codeBlockElement.getElementsByTagName("code");
|
||||
const codeBlockPreElement: HTMLPreElement | null = codeBlockElement.querySelector("pre:not(.frontmatter)");
|
||||
if (codeBlockPreElement === null) {
|
||||
return;
|
||||
}
|
||||
if (!isCodeBlockExcluded) {
|
||||
codeBlockPreElement.classList.add(`codeblock-customizer-pre`);
|
||||
}
|
||||
|
||||
AddHeaderAndHighlight(isCodeBlockExcluded, FileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL );
|
||||
}// ReadingView
|
||||
|
||||
function isAdmonition(lineText: string): boolean {
|
||||
const adTypes = ["ad-note", "ad-seealso", "ad-abstract", "ad-summary", "ad-tldr", "ad-info", "ad-todo", "ad-tip", "ad-hint", "ad-important", "ad-success", "ad-check", "ad-done", "ad-question", "ad-help", "ad-faq", "ad-warning", "ad-caution", "ad-attention", "ad-failure", "ad-fail", "ad-missing", "ad-danger", "ad-error", "ad-bug", "ad-example", "ad-quote", "ad-cite"]; //TODO (@mayurankv) refactor to use regex
|
||||
const codeBlockLang = searchString(lineText, "```");
|
||||
return adTypes.some((adType) => codeBlockLang && codeBlockLang.startsWith(adType));
|
||||
}// isAdmonition
|
||||
|
||||
function HeaderWidget(preElements, textToDisplay: string, specificHeader: boolean, codeblockLanguage: string, Collapse: boolean) {
|
||||
const parent = preElements.parentNode;
|
||||
|
||||
const container = createContainer(specificHeader);
|
||||
if (codeblockLanguage){
|
||||
const Icon = getLanguageIcon(codeblockLanguage)
|
||||
if (Icon) {
|
||||
container.appendChild(createCodeblockIcon(codeblockLanguage));
|
||||
}
|
||||
container.appendChild(createCodeblockLang(codeblockLanguage));
|
||||
}
|
||||
container.appendChild(createFileName(textToDisplay));
|
||||
parent.insertBefore(container, preElements);
|
||||
|
||||
// Add event listener to the widget element
|
||||
container.addEventListener("click", function() {
|
||||
// Toggle the "collapsed" class on the codeblock element
|
||||
preElements.classList.toggle("codeblock-customizer-codeblock-collapsed");
|
||||
});
|
||||
|
||||
if (Collapse) {
|
||||
preElements.classList.add(`codeblock-customizer-codeblock-collapsed`);
|
||||
}
|
||||
|
||||
}// HeaderWidget
|
||||
|
||||
function createLineNumberElement(lineNumber,showNumbers) {
|
||||
const lineNumberWrapper = document.createElement("div");
|
||||
lineNumberWrapper.classList.add(`codeblock-customizer-line-number${showNumbers?'':'-hide'}`);
|
||||
lineNumberWrapper.setText(lineNumber);
|
||||
|
||||
return lineNumberWrapper;
|
||||
}// createLineNumberElement
|
||||
|
||||
function createLineTextElement(line) {
|
||||
const lineText = line !== "" ? line : "<br>";
|
||||
const sanitizedText = sanitizeHTMLToDom(lineText);
|
||||
const lineContentWrapper = createDiv({cls: `codeblock-customizer-line-text`, text: sanitizedText});
|
||||
|
||||
return lineContentWrapper;
|
||||
}// createLineTextElement
|
||||
|
||||
function highlightLines(codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL) {
|
||||
for (let i = 0; i < codeElements.length; i++) {
|
||||
let lines = codeElements[i].innerHTML.split("\n");
|
||||
const preElm = codeElements[i].parentNode;
|
||||
if (preElm === null || preElm.nodeName !== "PRE") // only process pre > code elements
|
||||
return;
|
||||
|
||||
if (lines.length == 1) {
|
||||
lines = ['',''];
|
||||
}
|
||||
codeElements[i].innerHTML = "";
|
||||
for (let j = 0; j < lines.length - 1; j++) {
|
||||
const line = lines[j];
|
||||
const lineNumber = j + 1;
|
||||
const isHighlighted = linesToHighlight.includes(lineNumber);
|
||||
const altHLMatch = altHL.filter((hl) => hl.lineNumber === lineNumber);
|
||||
|
||||
// create line element
|
||||
const lineWrapper = document.createElement("div");
|
||||
if (isHighlighted) {
|
||||
lineWrapper.classList.add(`codeblock-customizer-line-highlighted`);
|
||||
}
|
||||
else if (altHLMatch.length > 0) {
|
||||
lineWrapper.classList.add(`codeblock-customizer-line-highlighted-${altHLMatch[0].name.replace(/\s+/g, '-').toLowerCase()}`);
|
||||
}
|
||||
codeElements[i].appendChild(lineWrapper);
|
||||
|
||||
// create line number element
|
||||
const lineNumberEl = createLineNumberElement(lineNumber+lineNumberOffset,showNumbers);
|
||||
lineWrapper.appendChild(lineNumberEl);
|
||||
|
||||
// create line text element
|
||||
const lineTextEl = createLineTextElement(line);
|
||||
lineWrapper.appendChild(lineTextEl);
|
||||
}
|
||||
}
|
||||
}// highlightLines
|
||||
|
||||
function AddHeaderAndHighlight(isCodeBlockExcluded, fileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL ){
|
||||
if (!isCodeBlockExcluded) {
|
||||
let specificHeader = true;
|
||||
if (fileName === null || fileName === "") {
|
||||
if (Fold) {
|
||||
fileName = 'Collapsed Code';
|
||||
} else {
|
||||
fileName = '';
|
||||
specificHeader = false;
|
||||
}
|
||||
}
|
||||
HeaderWidget(codeBlockPreElement, fileName, specificHeader, getLanguageName(codeBlockLang), Fold);
|
||||
highlightLines(codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL);
|
||||
|
||||
if (codeBlockPreElement.parentElement) {
|
||||
codeBlockPreElement.parentElement.classList.add(`codeblock-customizer-pre-parent`);
|
||||
}
|
||||
}
|
||||
}// AddHeaderAndHighlight
|
||||
|
||||
function PDFExport(codeBlockElement: HTMLElement, plugin: CodeblockCustomizerPlugin, codeBlockFirstLines: string[]) {
|
||||
const codeBlocks = codeBlockElement.querySelectorAll('pre > code');
|
||||
codeBlocks.forEach((codeElm, key) => {
|
||||
const codeBlockFirstLine = codeBlockFirstLines[key];
|
||||
const codeBlockLang = searchString(codeBlockFirstLine, "```");
|
||||
const highlightedLinesParams = searchString(codeBlockFirstLine, "HL:");
|
||||
const linesToHighlight = getHighlightedLines(highlightedLinesParams);
|
||||
const fileName = searchString(codeBlockFirstLine, "file:");
|
||||
const Fold = searchString(codeBlockFirstLine, "fold");
|
||||
const lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
const showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const alternateColors = plugin.settings.alternateColors || [];
|
||||
let altHL = [];
|
||||
for (const { name, _ } of alternateColors) {
|
||||
const altParams = searchString(codeBlockFirstLine, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
|
||||
let isCodeBlockExcluded = false;
|
||||
isCodeBlockExcluded = isExcluded(codeBlockFirstLine, plugin.settings.ExcludeLangs);
|
||||
|
||||
const codeBlockPreElement: HTMLPreElement | null = codeElm.parentElement;
|
||||
if (codeBlockPreElement === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCodeBlockExcluded){
|
||||
codeBlockPreElement.classList.add(`codeblock-customizer-pre`);
|
||||
}
|
||||
const codeElements = codeBlockPreElement.getElementsByTagName("code");
|
||||
|
||||
AddHeaderAndHighlight(isCodeBlockExcluded, fileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL );
|
||||
})
|
||||
}// PDFExport
|
||||
}
|
||||
230
src/ReadingViewOld.ts
Normal file
230
src/ReadingViewOld.ts
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
import { MarkdownView, MarkdownPostProcessorContext, sanitizeHTMLToDom } from "obsidian";
|
||||
|
||||
import { searchString, getHighlightedLines, getLanguageName, isExcluded, getLanguageIcon, createContainer, createCodeblockLang, createCodeblockIcon, createFileName } from "./Utils";
|
||||
|
||||
export async function ReadingView(codeBlockElement: HTMLElement, context: MarkdownPostProcessorContext, plugin: CodeblockCustomizerPlugin) {
|
||||
const codeElm: HTMLElement = codeBlockElement.querySelector('pre > code');
|
||||
|
||||
if (!codeElm)
|
||||
return;
|
||||
|
||||
const classRegex = /^language-\S+/;
|
||||
const match = Array.from(codeElm.classList).some(className => classRegex.test(className));
|
||||
if (match)
|
||||
while(!codeElm.classList.contains("is-loaded"))
|
||||
await sleep(2);
|
||||
|
||||
const codeBlockSectionInfo = context.getSectionInfo(codeElm);
|
||||
|
||||
let codeBlockFirstLine = "";
|
||||
if (codeBlockSectionInfo) {
|
||||
const view = plugin.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (view && view.editor)
|
||||
codeBlockFirstLine = view.editor.getLine(codeBlockSectionInfo.lineStart);
|
||||
} else {
|
||||
// PDF export
|
||||
const file = plugin.app.vault.getAbstractFileByPath(context.sourcePath);
|
||||
if (!file) {
|
||||
//console.error(`File not found: ${context.sourcePath}`);
|
||||
return;
|
||||
}
|
||||
const cache = plugin.app.metadataCache.getCache(context.sourcePath);
|
||||
const fileContent = await plugin.app.vault.cachedRead(<TFile> file).catch((error) => {
|
||||
//console.error(`Error reading file: ${error.message}`);
|
||||
return '';
|
||||
});
|
||||
const fileContentLines = fileContent.split(/\n/g);
|
||||
const codeBlockFirstLines: string[] = [];
|
||||
|
||||
if (cache.sections) {
|
||||
for (const element of cache.sections) {
|
||||
if (element.type === 'code') {
|
||||
const lineStart = element.position.start.line;
|
||||
const codeBlockFirstLine = fileContentLines[lineStart];
|
||||
if (!isAdmonition(codeBlockFirstLine)) {
|
||||
codeBlockFirstLines.push(codeBlockFirstLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//console.error(`Metadata cache not found for file: ${context.sourcePath}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await PDFExport(codeBlockElement, plugin, codeBlockFirstLines);
|
||||
} catch (error) {
|
||||
//console.error(`Error exporting to PDF: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const codeBlockLang = searchString(codeBlockFirstLine, "```");
|
||||
const highlightedLinesParams = searchString(codeBlockFirstLine, "HL:");
|
||||
const linesToHighlight = getHighlightedLines(highlightedLinesParams);
|
||||
const FileName = searchString(codeBlockFirstLine, "file:");
|
||||
const Fold = searchString(codeBlockFirstLine, "fold");
|
||||
const lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
const showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const alternateColors = plugin.settings.alternateColors || [];
|
||||
let altHL = [];
|
||||
for (const { name } of alternateColors) {
|
||||
const altParams = searchString(codeBlockFirstLine, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
|
||||
let isCodeBlockExcluded = false;
|
||||
isCodeBlockExcluded = isExcluded(codeBlockFirstLine, plugin.settings.ExcludeLangs);
|
||||
|
||||
const codeElements = codeBlockElement.getElementsByTagName("code");
|
||||
const codeBlockPreElement: HTMLPreElement | null = codeBlockElement.querySelector("pre:not(.frontmatter)");
|
||||
if (codeBlockPreElement === null) {
|
||||
return;
|
||||
}
|
||||
if (!isCodeBlockExcluded) {
|
||||
codeBlockPreElement.classList.add(`codeblock-customizer-pre`);
|
||||
}
|
||||
|
||||
AddHeaderAndHighlight(isCodeBlockExcluded, FileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL );
|
||||
}// ReadingView
|
||||
|
||||
function isAdmonition(lineText: string): boolean {
|
||||
const adTypes = ["ad-note", "ad-seealso", "ad-abstract", "ad-summary", "ad-tldr", "ad-info", "ad-todo", "ad-tip", "ad-hint", "ad-important", "ad-success", "ad-check", "ad-done", "ad-question", "ad-help", "ad-faq", "ad-warning", "ad-caution", "ad-attention", "ad-failure", "ad-fail", "ad-missing", "ad-danger", "ad-error", "ad-bug", "ad-example", "ad-quote", "ad-cite"]; //TODO (@mayurankv) refactor to use regex
|
||||
const codeBlockLang = searchString(lineText, "```");
|
||||
return adTypes.some((adType) => codeBlockLang && codeBlockLang.startsWith(adType));
|
||||
}// isAdmonition
|
||||
|
||||
function HeaderWidget(preElements, textToDisplay: string, specificHeader: boolean, codeblockLanguage: string, Collapse: boolean) {
|
||||
const parent = preElements.parentNode;
|
||||
|
||||
const container = createContainer(specificHeader);
|
||||
if (codeblockLanguage){
|
||||
const Icon = getLanguageIcon(codeblockLanguage)
|
||||
if (Icon) {
|
||||
container.appendChild(createCodeblockIcon(codeblockLanguage));
|
||||
}
|
||||
container.appendChild(createCodeblockLang(codeblockLanguage));
|
||||
}
|
||||
container.appendChild(createFileName(textToDisplay));
|
||||
parent.insertBefore(container, preElements);
|
||||
|
||||
// Add event listener to the widget element
|
||||
container.addEventListener("click", function() {
|
||||
// Toggle the "collapsed" class on the codeblock element
|
||||
preElements.classList.toggle("codeblock-customizer-codeblock-collapsed");
|
||||
});
|
||||
|
||||
if (Collapse) {
|
||||
preElements.classList.add(`codeblock-customizer-codeblock-collapsed`);
|
||||
}
|
||||
|
||||
}// HeaderWidget
|
||||
|
||||
function createLineNumberElement(lineNumber,showNumbers) {
|
||||
const lineNumberWrapper = document.createElement("div");
|
||||
lineNumberWrapper.classList.add(`codeblock-customizer-line-number${showNumbers?'':'-hide'}`);
|
||||
lineNumberWrapper.setText(lineNumber);
|
||||
|
||||
return lineNumberWrapper;
|
||||
}// createLineNumberElement
|
||||
|
||||
function createLineTextElement(line) {
|
||||
const lineText = line !== "" ? line : "<br>";
|
||||
const sanitizedText = sanitizeHTMLToDom(lineText);
|
||||
const lineContentWrapper = createDiv({cls: `codeblock-customizer-line-text`, text: sanitizedText});
|
||||
|
||||
return lineContentWrapper;
|
||||
}// createLineTextElement
|
||||
|
||||
function highlightLines(codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL) {
|
||||
for (let i = 0; i < codeElements.length; i++) {
|
||||
let lines = codeElements[i].innerHTML.split("\n");
|
||||
const preElm = codeElements[i].parentNode;
|
||||
if (preElm === null || preElm.nodeName !== "PRE") // only process pre > code elements
|
||||
return;
|
||||
|
||||
if (lines.length == 1) {
|
||||
lines = ['',''];
|
||||
}
|
||||
codeElements[i].innerHTML = "";
|
||||
for (let j = 0; j < lines.length - 1; j++) {
|
||||
const line = lines[j];
|
||||
const lineNumber = j + 1;
|
||||
const isHighlighted = linesToHighlight.includes(lineNumber);
|
||||
const altHLMatch = altHL.filter((hl) => hl.lineNumber === lineNumber);
|
||||
|
||||
// create line element
|
||||
const lineWrapper = document.createElement("div");
|
||||
if (isHighlighted) {
|
||||
lineWrapper.classList.add(`codeblock-customizer-line-highlighted`);
|
||||
}
|
||||
else if (altHLMatch.length > 0) {
|
||||
lineWrapper.classList.add(`codeblock-customizer-line-highlighted-${altHLMatch[0].name.replace(/\s+/g, '-').toLowerCase()}`);
|
||||
}
|
||||
codeElements[i].appendChild(lineWrapper);
|
||||
|
||||
// create line number element
|
||||
const lineNumberEl = createLineNumberElement(lineNumber+lineNumberOffset,showNumbers);
|
||||
lineWrapper.appendChild(lineNumberEl);
|
||||
|
||||
// create line text element
|
||||
const lineTextEl = createLineTextElement(line);
|
||||
lineWrapper.appendChild(lineTextEl);
|
||||
}
|
||||
}
|
||||
}// highlightLines
|
||||
|
||||
function AddHeaderAndHighlight(isCodeBlockExcluded, fileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL ){
|
||||
if (!isCodeBlockExcluded) {
|
||||
let specificHeader = true;
|
||||
if (fileName === null || fileName === "") {
|
||||
if (Fold) {
|
||||
fileName = 'Collapsed Code';
|
||||
} else {
|
||||
fileName = '';
|
||||
specificHeader = false;
|
||||
}
|
||||
}
|
||||
HeaderWidget(codeBlockPreElement, fileName, specificHeader, getLanguageName(codeBlockLang), Fold);
|
||||
highlightLines(codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL);
|
||||
|
||||
if (codeBlockPreElement.parentElement) {
|
||||
codeBlockPreElement.parentElement.classList.add(`codeblock-customizer-pre-parent`);
|
||||
}
|
||||
}
|
||||
}// AddHeaderAndHighlight
|
||||
|
||||
function PDFExport(codeBlockElement: HTMLElement, plugin: CodeblockCustomizerPlugin, codeBlockFirstLines: string[]) {
|
||||
const codeBlocks = codeBlockElement.querySelectorAll('pre > code');
|
||||
codeBlocks.forEach((codeElm, key) => {
|
||||
const codeBlockFirstLine = codeBlockFirstLines[key];
|
||||
const codeBlockLang = searchString(codeBlockFirstLine, "```");
|
||||
const highlightedLinesParams = searchString(codeBlockFirstLine, "HL:");
|
||||
const linesToHighlight = getHighlightedLines(highlightedLinesParams);
|
||||
const fileName = searchString(codeBlockFirstLine, "file:");
|
||||
const Fold = searchString(codeBlockFirstLine, "fold");
|
||||
const lineNumberOffset = 0; //searchString(codeBlockFirstLine, "ln:")//TODO (@mayurankv) Set line number offset here - Should be ln_value - 1 since it is offset, not starting line number - 0 if true OR false
|
||||
const showNumbers = true; //TODO (@mayurankv) Set showNumbers to be true if ln:<number> or ln:true or false if ln:false
|
||||
const alternateColors = plugin.settings.alternateColors || [];
|
||||
let altHL = [];
|
||||
for (const { name, _ } of alternateColors) {
|
||||
const altParams = searchString(codeBlockFirstLine, `${name}:`);
|
||||
altHL = altHL.concat(getHighlightedLines(altParams).map((lineNumber) => ({ name, lineNumber })));
|
||||
}
|
||||
|
||||
let isCodeBlockExcluded = false;
|
||||
isCodeBlockExcluded = isExcluded(codeBlockFirstLine, plugin.settings.ExcludeLangs);
|
||||
|
||||
const codeBlockPreElement: HTMLPreElement | null = codeElm.parentElement;
|
||||
if (codeBlockPreElement === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCodeBlockExcluded){
|
||||
codeBlockPreElement.classList.add(`codeblock-customizer-pre`);
|
||||
}
|
||||
const codeElements = codeBlockPreElement.getElementsByTagName("code");
|
||||
|
||||
AddHeaderAndHighlight(isCodeBlockExcluded, fileName, codeBlockPreElement, codeBlockLang, Fold, codeElements, showNumbers, lineNumberOffset, linesToHighlight, altHL );
|
||||
})
|
||||
}// PDFExport
|
||||
418
src/Settings.ts
418
src/Settings.ts
|
|
@ -11,236 +11,238 @@ export type Display = "none" | "title_only" | "always";
|
|||
|
||||
// Interface Creation
|
||||
export interface CodeblockCustomizerThemeModeColors {
|
||||
codeblock: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
header: {
|
||||
backgroundColor: Color;
|
||||
title: {
|
||||
textColor: Color;
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
lineColor: Color;
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: Color;
|
||||
activeEditorLineColor: Color;
|
||||
defaultColor: Color;
|
||||
alternativeHighlights: Record<string,Color>;
|
||||
},
|
||||
codeblock: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
header: {
|
||||
backgroundColor: Color;
|
||||
title: {
|
||||
textColor: Color;
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: Color;
|
||||
textColor: Color;
|
||||
},
|
||||
lineColor: Color;
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: Color;
|
||||
activeEditorLineColor: Color;
|
||||
defaultColor: Color;
|
||||
alternativeHighlights: Record<string,Color>;
|
||||
},
|
||||
}
|
||||
export interface CodeblockCustomizerThemeSettings {
|
||||
codeblock: {
|
||||
lineNumbers: boolean;
|
||||
curvature: number;
|
||||
},
|
||||
gutter: {
|
||||
highlight: boolean;
|
||||
},
|
||||
header: {
|
||||
title: {
|
||||
textFont: string;
|
||||
textBold: boolean;
|
||||
textItalic: boolean;
|
||||
},
|
||||
languageTag: {
|
||||
display: Display;
|
||||
textFont: string;
|
||||
textBold: boolean;
|
||||
textItalic: boolean;
|
||||
},
|
||||
languageIcon: {
|
||||
display: Display;
|
||||
displayColor: boolean;
|
||||
},
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLine: boolean;
|
||||
activeEditorLine: boolean;
|
||||
},
|
||||
advanced: {
|
||||
gradientHighlights: boolean;
|
||||
gradientHighlightsColorStop: Percentage;
|
||||
languageBorderColor: boolean;
|
||||
iconSize: number;
|
||||
};
|
||||
codeblock: {
|
||||
lineNumbers: boolean;
|
||||
curvature: number;
|
||||
},
|
||||
gutter: {
|
||||
highlight: boolean;
|
||||
},
|
||||
header: {
|
||||
title: {
|
||||
textFont: string;
|
||||
textBold: boolean;
|
||||
textItalic: boolean;
|
||||
},
|
||||
languageTag: {
|
||||
display: Display;
|
||||
textFont: string;
|
||||
textBold: boolean;
|
||||
textItalic: boolean;
|
||||
},
|
||||
languageIcon: {
|
||||
display: Display;
|
||||
displayColor: boolean;
|
||||
},
|
||||
collapsePlaceholder: string;
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLine: boolean;
|
||||
activeEditorLine: boolean;
|
||||
},
|
||||
advanced: {
|
||||
gradientHighlights: boolean;
|
||||
gradientHighlightsColorStop: Percentage;
|
||||
languageBorderColor: boolean;
|
||||
iconSize: number;
|
||||
};
|
||||
}
|
||||
export interface CodeblockCustomizerThemeColors {
|
||||
light: CodeblockCustomizerThemeModeColors;
|
||||
dark: CodeblockCustomizerThemeModeColors;
|
||||
light: CodeblockCustomizerThemeModeColors;
|
||||
dark: CodeblockCustomizerThemeModeColors;
|
||||
}
|
||||
export interface CodeblockCustomizerTheme {
|
||||
settings: CodeblockCustomizerThemeSettings;
|
||||
colors: CodeblockCustomizerThemeColors;
|
||||
settings: CodeblockCustomizerThemeSettings;
|
||||
colors: CodeblockCustomizerThemeColors;
|
||||
}
|
||||
export interface CodeblockCustomizerSettings {
|
||||
themes: Record<string,CodeblockCustomizerTheme>;
|
||||
selectedTheme: string;
|
||||
defaultTheme: string;
|
||||
currentTheme: CodeblockCustomizerTheme;
|
||||
newTheme: {
|
||||
name: string;
|
||||
default: boolean;
|
||||
},
|
||||
newHighlight: string;
|
||||
excludedLangs: string;
|
||||
themes: Record<string,CodeblockCustomizerTheme>;
|
||||
selectedTheme: string;
|
||||
defaultTheme: string;
|
||||
currentTheme: CodeblockCustomizerTheme;
|
||||
newTheme: {
|
||||
name: string;
|
||||
default: boolean;
|
||||
},
|
||||
newHighlight: string;
|
||||
excludedLangs: string;
|
||||
}
|
||||
|
||||
// Theme Defaults
|
||||
const THEME_DEFAULT_SETTINGS: CodeblockCustomizerThemeSettings = {
|
||||
codeblock: {
|
||||
lineNumbers: true,
|
||||
curvature: 10,
|
||||
},
|
||||
gutter: {
|
||||
highlight: true,
|
||||
},
|
||||
header: {
|
||||
title: {
|
||||
textFont: '',
|
||||
textBold: false,
|
||||
textItalic: false,
|
||||
},
|
||||
languageTag: {
|
||||
display: "always",
|
||||
textFont: '',
|
||||
textBold: true,
|
||||
textItalic: true,
|
||||
},
|
||||
languageIcon: {
|
||||
display: "always",
|
||||
displayColor: true,
|
||||
},
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLine: true,
|
||||
activeEditorLine: false,
|
||||
},
|
||||
advanced: {
|
||||
gradientHighlights: false,
|
||||
gradientHighlightsColorStop: '70%',
|
||||
languageBorderColor: false,
|
||||
iconSize: 28,
|
||||
},
|
||||
}
|
||||
export const NEW_THEME_DEFAULT: {name: string, default: boolean} = {
|
||||
name: '',
|
||||
default: false,
|
||||
name: '',
|
||||
default: false,
|
||||
}
|
||||
const THEME_DEFAULT_SETTINGS: CodeblockCustomizerThemeSettings = {
|
||||
codeblock: {
|
||||
lineNumbers: true,
|
||||
curvature: 10,
|
||||
},
|
||||
gutter: {
|
||||
highlight: true,
|
||||
},
|
||||
header: {
|
||||
title: {
|
||||
textFont: '',
|
||||
textBold: false,
|
||||
textItalic: false,
|
||||
},
|
||||
languageTag: {
|
||||
display: "always",
|
||||
textFont: '',
|
||||
textBold: true,
|
||||
textItalic: true,
|
||||
},
|
||||
languageIcon: {
|
||||
display: "always",
|
||||
displayColor: true,
|
||||
},
|
||||
collapsePlaceholder: '',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLine: true,
|
||||
activeEditorLine: false,
|
||||
},
|
||||
advanced: {
|
||||
gradientHighlights: false,
|
||||
gradientHighlightsColorStop: '70%',
|
||||
languageBorderColor: false,
|
||||
iconSize: 28,
|
||||
},
|
||||
}
|
||||
export const THEME_FALLBACK_COLORS: CodeblockCustomizerThemeModeColors = {
|
||||
codeblock: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-normal',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '--code-background',
|
||||
title: {
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
lineColor: '--code-background',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '--color-base-30',
|
||||
activeEditorLineColor: '--color-base-20',
|
||||
defaultColor: '--text-highlight-bg',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
codeblock: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-normal',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '--code-background',
|
||||
title: {
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '--code-background',
|
||||
textColor: '--code-comment',
|
||||
},
|
||||
lineColor: '--code-background',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '--color-base-30',
|
||||
activeEditorLineColor: '--color-base-20',
|
||||
defaultColor: '--text-highlight-bg',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
}
|
||||
|
||||
// Theme Creation
|
||||
const DEFAULT_THEME: CodeblockCustomizerTheme = {
|
||||
settings: THEME_DEFAULT_SETTINGS,
|
||||
colors: {
|
||||
light: THEME_FALLBACK_COLORS,
|
||||
dark: THEME_FALLBACK_COLORS,
|
||||
},
|
||||
settings: THEME_DEFAULT_SETTINGS,
|
||||
colors: {
|
||||
light: THEME_FALLBACK_COLORS,
|
||||
dark: THEME_FALLBACK_COLORS,
|
||||
},
|
||||
}
|
||||
const SOLARIZED_THEME: CodeblockCustomizerTheme = {
|
||||
settings: THEME_DEFAULT_SETTINGS,
|
||||
colors: {
|
||||
light: {
|
||||
codeblock: {
|
||||
backgroundColor: '#FCF6E4',
|
||||
textColor: '#bababa',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '#EDE8D6',
|
||||
textColor: '#6c6c6c',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '#D5CCB4',
|
||||
title: {
|
||||
textColor: '#866704',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '#B8B5AA',
|
||||
textColor: '#C25F30',
|
||||
},
|
||||
lineColor: '#EDD489',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '#EDE8D6',
|
||||
activeEditorLineColor: '#60460633',
|
||||
defaultColor: '#E9DFBA',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
codeblock: {
|
||||
backgroundColor: '#002b36',
|
||||
textColor: '#bababa',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '#073642',
|
||||
textColor: '#6c6c6c',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '#0a4554',
|
||||
title: {
|
||||
textColor: '#dadada',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '#008080',
|
||||
textColor: '#000000',
|
||||
},
|
||||
lineColor: '#46cced',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '#073642',
|
||||
activeEditorLineColor: '#468eeb33',
|
||||
defaultColor: '#054b5c',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
settings: THEME_DEFAULT_SETTINGS,
|
||||
colors: {
|
||||
light: {
|
||||
codeblock: {
|
||||
backgroundColor: '#FCF6E4',
|
||||
textColor: '#bababa',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '#EDE8D6',
|
||||
textColor: '#6c6c6c',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '#D5CCB4',
|
||||
title: {
|
||||
textColor: '#866704',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '#B8B5AA',
|
||||
textColor: '#C25F30',
|
||||
},
|
||||
lineColor: '#EDD489',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '#EDE8D6',
|
||||
activeEditorLineColor: '#60460633',
|
||||
defaultColor: '#E9DFBA',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
codeblock: {
|
||||
backgroundColor: '#002b36',
|
||||
textColor: '#bababa',
|
||||
},
|
||||
gutter: {
|
||||
backgroundColor: '#073642',
|
||||
textColor: '#6c6c6c',
|
||||
},
|
||||
header: {
|
||||
backgroundColor: '#0a4554',
|
||||
title: {
|
||||
textColor: '#dadada',
|
||||
},
|
||||
languageTag: {
|
||||
backgroundColor: '#008080',
|
||||
textColor: '#000000',
|
||||
},
|
||||
lineColor: '#46cced',
|
||||
},
|
||||
highlights: {
|
||||
activeCodeblockLineColor: '#073642',
|
||||
activeEditorLineColor: '#468eeb33',
|
||||
defaultColor: '#054b5c',
|
||||
alternativeHighlights: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Plugin default settings
|
||||
export const DEFAULT_SETTINGS: CodeblockCustomizerSettings = {
|
||||
themes: {
|
||||
'Default': DEFAULT_THEME,
|
||||
'Solarized': SOLARIZED_THEME,
|
||||
},
|
||||
selectedTheme: 'Default',
|
||||
defaultTheme: 'Default',
|
||||
currentTheme: structuredClone(DEFAULT_THEME),
|
||||
newTheme: NEW_THEME_DEFAULT,
|
||||
newHighlight: '',
|
||||
excludedLangs: "dataview, dataviewjs, ad-*",
|
||||
themes: {
|
||||
'Default': DEFAULT_THEME,
|
||||
'Solarized': SOLARIZED_THEME,
|
||||
},
|
||||
selectedTheme: 'Default',
|
||||
defaultTheme: 'Default',
|
||||
currentTheme: structuredClone(DEFAULT_THEME),
|
||||
newTheme: NEW_THEME_DEFAULT,
|
||||
newHighlight: '',
|
||||
excludedLangs: "dataview, dataviewjs, ad-*",
|
||||
}
|
||||
|
|
|
|||
1410
src/SettingsTab.ts
1410
src/SettingsTab.ts
File diff suppressed because it is too large
Load diff
578
src/Utils.ts
578
src/Utils.ts
|
|
@ -2,342 +2,342 @@ import { Languages, manualLang, Icons } from "./Const";
|
|||
import { CodeblockCustomizerSettings } from "./Settings";
|
||||
|
||||
export function splitAndTrimString(str) {
|
||||
if (!str) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Replace * with .*
|
||||
str = str.replace(/\*/g, '.*');
|
||||
|
||||
if (!str.includes(",")) {
|
||||
return [str];
|
||||
}
|
||||
|
||||
return str.split(",").map(s => s.trim());
|
||||
if (!str) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Replace * with .*
|
||||
str = str.replace(/\*/g, '.*');
|
||||
|
||||
if (!str.includes(",")) {
|
||||
return [str];
|
||||
}
|
||||
|
||||
return str.split(",").map(s => s.trim());
|
||||
}// splitAndTrimString
|
||||
|
||||
export function searchString(str, searchTerm) {
|
||||
const originalStr = str;
|
||||
str = str.toLowerCase();
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
if (searchTerm === "file:") {
|
||||
if (str.includes(searchTerm)) {
|
||||
const startIndex = str.indexOf(searchTerm) + searchTerm.length;
|
||||
let result = "";
|
||||
if (str[startIndex] === "\"") {
|
||||
const endIndex = str.indexOf("\"", startIndex + 1);
|
||||
if (endIndex !== -1) {
|
||||
result = originalStr.substring(startIndex + 1, endIndex);
|
||||
} else {
|
||||
result = originalStr.substring(startIndex + 1);
|
||||
}
|
||||
} else {
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
if (endIndex !== -1) {
|
||||
result = originalStr.substring(startIndex, endIndex);
|
||||
} else {
|
||||
result = originalStr.substring(startIndex);
|
||||
}
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
} else if (searchTerm === "```") {
|
||||
if (str.startsWith(searchTerm)) {
|
||||
const startIndex = searchTerm.length;
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
let word = "";
|
||||
if (endIndex !==-1) {
|
||||
word = originalStr.substring(startIndex, endIndex);
|
||||
} else {
|
||||
word = originalStr.substring(startIndex);
|
||||
}
|
||||
if (!word.includes(":")) {
|
||||
if (word.toLowerCase() === "fold")
|
||||
return null;
|
||||
else
|
||||
return word;
|
||||
}
|
||||
}
|
||||
} else if (searchTerm === 'fold') {
|
||||
if (str.includes(" fold ")) {
|
||||
return true;
|
||||
}
|
||||
const index = str.indexOf(searchTerm);
|
||||
if (index !== -1 && index === str.length - searchTerm.length && str[index - 1] === " ") {
|
||||
return true;
|
||||
}
|
||||
if (str.includes("```fold ")) {
|
||||
return true;
|
||||
}
|
||||
if (str.includes("```fold") && str.indexOf("```fold") + "```fold".length === str.length) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (str.includes(searchTerm)) {
|
||||
const startIndex = str.indexOf(searchTerm) + searchTerm.length;
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
if (endIndex !== -1) {
|
||||
return originalStr.substring(startIndex, endIndex).trim();
|
||||
} else {
|
||||
return originalStr.substring(startIndex).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
const originalStr = str;
|
||||
str = str.toLowerCase();
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
if (searchTerm === "file:") {
|
||||
if (str.includes(searchTerm)) {
|
||||
const startIndex = str.indexOf(searchTerm) + searchTerm.length;
|
||||
let result = "";
|
||||
if (str[startIndex] === "\"") {
|
||||
const endIndex = str.indexOf("\"", startIndex + 1);
|
||||
if (endIndex !== -1) {
|
||||
result = originalStr.substring(startIndex + 1, endIndex);
|
||||
} else {
|
||||
result = originalStr.substring(startIndex + 1);
|
||||
}
|
||||
} else {
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
if (endIndex !== -1) {
|
||||
result = originalStr.substring(startIndex, endIndex);
|
||||
} else {
|
||||
result = originalStr.substring(startIndex);
|
||||
}
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
} else if (searchTerm === "```") {
|
||||
if (str.startsWith(searchTerm)) {
|
||||
const startIndex = searchTerm.length;
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
let word = "";
|
||||
if (endIndex !==-1) {
|
||||
word = originalStr.substring(startIndex, endIndex);
|
||||
} else {
|
||||
word = originalStr.substring(startIndex);
|
||||
}
|
||||
if (!word.includes(":")) {
|
||||
if (word.toLowerCase() === "fold")
|
||||
return null;
|
||||
else
|
||||
return word;
|
||||
}
|
||||
}
|
||||
} else if (searchTerm === 'fold') {
|
||||
if (str.includes(" fold ")) {
|
||||
return true;
|
||||
}
|
||||
const index = str.indexOf(searchTerm);
|
||||
if (index !== -1 && index === str.length - searchTerm.length && str[index - 1] === " ") {
|
||||
return true;
|
||||
}
|
||||
if (str.includes("```fold ")) {
|
||||
return true;
|
||||
}
|
||||
if (str.includes("```fold") && str.indexOf("```fold") + "```fold".length === str.length) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (str.includes(searchTerm)) {
|
||||
const startIndex = str.indexOf(searchTerm) + searchTerm.length;
|
||||
const endIndex = str.indexOf(" ", startIndex);
|
||||
if (endIndex !== -1) {
|
||||
return originalStr.substring(startIndex, endIndex).trim();
|
||||
} else {
|
||||
return originalStr.substring(startIndex).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}//searchString
|
||||
|
||||
export function getHighlightedLines(params: string): number[] {
|
||||
if (!params) {
|
||||
return [];
|
||||
}
|
||||
if (!params) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const trimmedParams = params.trim();
|
||||
const lines = trimmedParams.split(",");
|
||||
const trimmedParams = params.trim();
|
||||
const lines = trimmedParams.split(",");
|
||||
|
||||
return lines.map(line => {
|
||||
if (line.includes("-")) {
|
||||
const range = line.split("-");
|
||||
const start = parseInt(range[0], 10);
|
||||
const end = parseInt(range[1], 10);
|
||||
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
||||
}
|
||||
return parseInt(line, 10);
|
||||
}).flat();
|
||||
return lines.map(line => {
|
||||
if (line.includes("-")) {
|
||||
const range = line.split("-");
|
||||
const start = parseInt(range[0], 10);
|
||||
const end = parseInt(range[1], 10);
|
||||
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
||||
}
|
||||
return parseInt(line, 10);
|
||||
}).flat();
|
||||
}// getHighlightedLines
|
||||
|
||||
export function isExcluded(lineText: string, excludeLangs: string[]) : boolean {
|
||||
const codeBlockLang = searchString(lineText, "```");
|
||||
const regexLangs = splitAndTrimString(excludeLangs).map(lang => new RegExp(`^${lang.replace(/\*/g, '.*')}$`, 'i'));
|
||||
|
||||
for (const regexLang of regexLangs) {
|
||||
if (codeBlockLang && regexLang.test(codeBlockLang)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
const codeBlockLang = searchString(lineText, "```");
|
||||
const regexLangs = splitAndTrimString(excludeLangs).map(lang => new RegExp(`^${lang.replace(/\*/g, '.*')}$`, 'i'));
|
||||
|
||||
for (const regexLang of regexLangs) {
|
||||
if (codeBlockLang && regexLang.test(codeBlockLang)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}// isExcluded
|
||||
|
||||
export function getLanguageIcon(DisplayName) {
|
||||
if (!DisplayName)
|
||||
return "";
|
||||
|
||||
if (Icons.hasOwnProperty(DisplayName)) {
|
||||
return Icons[DisplayName];
|
||||
}
|
||||
|
||||
return null;
|
||||
if (!DisplayName)
|
||||
return "";
|
||||
|
||||
if (Icons.hasOwnProperty(DisplayName)) {
|
||||
return Icons[DisplayName];
|
||||
}
|
||||
|
||||
return null;
|
||||
}// getLanguageIcon
|
||||
|
||||
export function getLanguageName(code) {
|
||||
if (!code)
|
||||
return "";
|
||||
|
||||
code = code.toLowerCase();
|
||||
|
||||
if (Languages.hasOwnProperty(code)) {
|
||||
return Languages[code];
|
||||
} else if (manualLang.hasOwnProperty(code)) {
|
||||
return manualLang[code];
|
||||
} else if (code){
|
||||
return code.charAt(0).toUpperCase() + code.slice(1);
|
||||
}
|
||||
|
||||
return "";
|
||||
if (!code)
|
||||
return "";
|
||||
|
||||
code = code.toLowerCase();
|
||||
|
||||
if (Languages.hasOwnProperty(code)) {
|
||||
return Languages[code];
|
||||
} else if (manualLang.hasOwnProperty(code)) {
|
||||
return manualLang[code];
|
||||
} else if (code){
|
||||
return code.charAt(0).toUpperCase() + code.slice(1);
|
||||
}
|
||||
|
||||
return "";
|
||||
}// getLanguageName
|
||||
|
||||
export const BLOBS: Record<string, string> = {};
|
||||
export function loadIcons(){
|
||||
for (const [key, value] of Object.entries(Icons)) {
|
||||
BLOBS[key.replace(/\s/g, "_")] = URL.createObjectURL(new Blob([`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">${value}</svg>`], { type: "image/svg+xml" }));
|
||||
}
|
||||
for (const [key, value] of Object.entries(Icons)) {
|
||||
BLOBS[key.replace(/\s/g, "_")] = URL.createObjectURL(new Blob([`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">${value}</svg>`], { type: "image/svg+xml" }));
|
||||
}
|
||||
}// loadIcons
|
||||
|
||||
// Functions for displaying header BEGIN
|
||||
export function createContainer(specific: boolean) {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add(`codeblock-customizer-header-container${specific?'-specific':''}`);
|
||||
return container;
|
||||
const container = document.createElement("div");
|
||||
container.classList.add(`codeblock-customizer-header-container${specific?'-specific':''}`);
|
||||
return container;
|
||||
}// createContainer
|
||||
|
||||
export function createCodeblockLang(lang: string) {
|
||||
const codeblockLang = document.createElement("div");
|
||||
codeblockLang.innerText = lang;
|
||||
codeblockLang.classList.add(`codeblock-customizer-header-language-tag-${getLanguageName(lang).toLowerCase()}`);
|
||||
return codeblockLang;
|
||||
const codeblockLang = document.createElement("div");
|
||||
codeblockLang.innerText = lang;
|
||||
codeblockLang.classList.add(`codeblock-customizer-header-language-tag-${getLanguageName(lang).toLowerCase()}`);
|
||||
return codeblockLang;
|
||||
}// createCodeblockLang
|
||||
|
||||
export function createCodeblockIcon(displayLang: string) {
|
||||
const div = document.createElement("div");
|
||||
const img = document.createElement("img");
|
||||
img.classList.add("codeblock-customizer-icon");
|
||||
img.width = 28; //32
|
||||
img.src = BLOBS[displayLang.replace(/\s/g, "_")];
|
||||
const div = document.createElement("div");
|
||||
const img = document.createElement("img");
|
||||
img.classList.add("codeblock-customizer-icon");
|
||||
img.width = 28; //32
|
||||
img.src = BLOBS[displayLang.replace(/\s/g, "_")];
|
||||
|
||||
div.appendChild(img);
|
||||
|
||||
return div;
|
||||
div.appendChild(img);
|
||||
|
||||
return div;
|
||||
}// createCodeblockIcon
|
||||
|
||||
export function createFileName(text: string) {
|
||||
const fileName = document.createElement("div");
|
||||
fileName.innerText = text;
|
||||
fileName.classList.add("codeblock-customizer-header-text");
|
||||
return fileName;
|
||||
const fileName = document.createElement("div");
|
||||
fileName.innerText = text;
|
||||
fileName.classList.add("codeblock-customizer-header-text");
|
||||
return fileName;
|
||||
}// createFileName
|
||||
|
||||
// Functions for displaying header END
|
||||
|
||||
const stylesDict = {
|
||||
activeCodeBlockLineColor: 'codeblock-active-line-color',
|
||||
activeLineColor: 'editor-active-line-color',
|
||||
backgroundColor: 'codeblock-background-color',
|
||||
highlightColor: 'highlight-color',
|
||||
headerColor: 'header-background-color',
|
||||
headerTextColor: 'header-text-color',
|
||||
headerLineColor: 'header-line-color',
|
||||
gutterTextColor: 'gutter-text-color',
|
||||
gutterBackgroundColor: 'gutter-background-color',
|
||||
codeBlockLangColor: 'language-tag-text-color',
|
||||
codeBlockLangBackgroundColor: 'language-tag-background-color',
|
||||
activeCodeBlockLineColor: 'codeblock-active-line-color',
|
||||
activeLineColor: 'editor-active-line-color',
|
||||
backgroundColor: 'codeblock-background-color',
|
||||
highlightColor: 'highlight-color',
|
||||
headerColor: 'header-background-color',
|
||||
headerTextColor: 'header-text-color',
|
||||
headerLineColor: 'header-line-color',
|
||||
gutterTextColor: 'gutter-text-color',
|
||||
gutterBackgroundColor: 'gutter-background-color',
|
||||
codeBlockLangColor: 'language-tag-text-color',
|
||||
codeBlockLangBackgroundColor: 'language-tag-background-color',
|
||||
}
|
||||
|
||||
export function updateSettingStyles(settings: CodeblockCustomizerSettings) {
|
||||
let colorThemes = settings.colorThemes;
|
||||
let styleId = 'codeblock-customizer-styles'
|
||||
let styleTag = document.getElementById(styleId);
|
||||
if (typeof(styleTag) == 'undefined' || styleTag == null) {
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.id = styleId;
|
||||
document.getElementsByTagName('head')[0].appendChild(styleTag);
|
||||
}
|
||||
let currentMode = getCurrentMode()
|
||||
let defaultColors = settings.colorThemes.find((theme) => {return theme['name'] == `${currentMode.charAt(0).toUpperCase()+currentMode.slice(1)} Theme`})['colors'];
|
||||
let themeColors = settings.colorThemes.find((theme) => {return theme['name'] == settings.SelectedTheme})['colors'];
|
||||
let currentTheme = {name: 'current', colors: {}};
|
||||
for (const key of Object.keys(stylesDict)) {
|
||||
let defaultValue = accessSetting(key,defaultColors).toLowerCase();
|
||||
let themeValue = accessSetting(key,themeColors).toLowerCase();
|
||||
let settingsValue = accessSetting(key,settings).toLowerCase();
|
||||
if (defaultValue !== settingsValue) {
|
||||
currentTheme['colors'][key] = settingsValue;
|
||||
} else if (defaultValue !== themeValue) {
|
||||
currentTheme['colors'][key] = themeValue;
|
||||
}
|
||||
}
|
||||
let altHighlightStyling = settings.alternateColors.reduce((styling,altHighlight) => {return styling + `
|
||||
.codeblock-customizer-line-highlighted-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()} {
|
||||
background-color: var(--codeblock-customiser-highlight-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()}-color) !important;
|
||||
}
|
||||
`},'');
|
||||
let textSettingsStyles = `
|
||||
body.codeblock-customizer [class^="codeblock-customizer-header-language-tag"] {
|
||||
--codeblock-customizer-language-tag-text-bold: ${settings.header.bCodeblockLangBold?'bold':'normal'};
|
||||
--codeblock-customizer-language-tag-text-italic: ${settings.header.bCodeblockLangItalic?'italic':'normal'};
|
||||
}
|
||||
body.codeblock-customizer .codeblock-customizer-header-text {
|
||||
--codeblock-customizer-header-text-bold: ${settings.header.bHeaderBold?'bold':'normal'};
|
||||
--codeblock-customizer-header-text-italic: ${settings.header.bHeaderItalic?'italic':'normal'};
|
||||
}
|
||||
`;
|
||||
styleTag.innerText = colorThemes.reduce((styles,theme) => {
|
||||
return styles + formatStyles(theme,settings.alternateColors);
|
||||
},formatStyles(currentTheme,settings.alternateColors)+altHighlightStyling+textSettingsStyles).trim().replace(/[\r\n\s]+/g, ' ');
|
||||
updateSettingClasses(settings);
|
||||
let colorThemes = settings.colorThemes;
|
||||
let styleId = 'codeblock-customizer-styles'
|
||||
let styleTag = document.getElementById(styleId);
|
||||
if (typeof(styleTag) == 'undefined' || styleTag == null) {
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.id = styleId;
|
||||
document.getElementsByTagName('head')[0].appendChild(styleTag);
|
||||
}
|
||||
let currentMode = getCurrentMode()
|
||||
let defaultColors = settings.colorThemes.find((theme) => {return theme['name'] == `${currentMode.charAt(0).toUpperCase()+currentMode.slice(1)} Theme`})['colors'];
|
||||
let themeColors = settings.colorThemes.find((theme) => {return theme['name'] == settings.SelectedTheme})['colors'];
|
||||
let currentTheme = {name: 'current', colors: {}};
|
||||
for (const key of Object.keys(stylesDict)) {
|
||||
let defaultValue = accessSetting(key,defaultColors).toLowerCase();
|
||||
let themeValue = accessSetting(key,themeColors).toLowerCase();
|
||||
let settingsValue = accessSetting(key,settings).toLowerCase();
|
||||
if (defaultValue !== settingsValue) {
|
||||
currentTheme['colors'][key] = settingsValue;
|
||||
} else if (defaultValue !== themeValue) {
|
||||
currentTheme['colors'][key] = themeValue;
|
||||
}
|
||||
}
|
||||
let altHighlightStyling = settings.alternateColors.reduce((styling,altHighlight) => {return styling + `
|
||||
.codeblock-customizer-line-highlighted-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()} {
|
||||
background-color: var(--codeblock-customiser-highlight-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()}-color) !important;
|
||||
}
|
||||
`},'');
|
||||
let textSettingsStyles = `
|
||||
body.codeblock-customizer [class^="codeblock-customizer-header-language-tag"] {
|
||||
--codeblock-customizer-language-tag-text-bold: ${settings.header.bCodeblockLangBold?'bold':'normal'};
|
||||
--codeblock-customizer-language-tag-text-italic: ${settings.header.bCodeblockLangItalic?'italic':'normal'};
|
||||
}
|
||||
body.codeblock-customizer .codeblock-customizer-header-text {
|
||||
--codeblock-customizer-header-text-bold: ${settings.header.bHeaderBold?'bold':'normal'};
|
||||
--codeblock-customizer-header-text-italic: ${settings.header.bHeaderItalic?'italic':'normal'};
|
||||
}
|
||||
`;
|
||||
styleTag.innerText = colorThemes.reduce((styles,theme) => {
|
||||
return styles + formatStyles(theme,settings.alternateColors);
|
||||
},formatStyles(currentTheme,settings.alternateColors)+altHighlightStyling+textSettingsStyles).trim().replace(/[\r\n\s]+/g, ' ');
|
||||
updateSettingClasses(settings);
|
||||
}// setStyles
|
||||
|
||||
function updateSettingClasses(settings) {
|
||||
document.body.classList.remove("codeblock-customizer-active-line-highlight","codeblock-customizer-active-line-highlight-codeblock","codeblock-customizer-active-line-highlight-editor")
|
||||
if (settings.bActiveLineHighlight && settings.bActiveCodeblockLineHighlight) {
|
||||
// Inside and outside of codeblocks with different colors
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight");
|
||||
} else if (settings.bActiveLineHighlight && !settings.bActiveCodeblockLineHighlight) {
|
||||
// Only outside codeblocks
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight-editor");
|
||||
} else if (!settings.bActiveLineHighlight && settings.bActiveCodeblockLineHighlight) {
|
||||
// Only inside codeblocks
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight-codeblock");
|
||||
}
|
||||
|
||||
if (settings.bEnableLineNumbers) {
|
||||
document.body.classList.add("codeblock-customizer-show-line-numbers");
|
||||
} else {
|
||||
document.body.classList.remove("codeblock-customizer-show-line-numbers");
|
||||
}
|
||||
document.body.classList.remove("codeblock-customizer-active-line-highlight","codeblock-customizer-active-line-highlight-codeblock","codeblock-customizer-active-line-highlight-editor")
|
||||
if (settings.bActiveLineHighlight && settings.bActiveCodeblockLineHighlight) {
|
||||
// Inside and outside of codeblocks with different colors
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight");
|
||||
} else if (settings.bActiveLineHighlight && !settings.bActiveCodeblockLineHighlight) {
|
||||
// Only outside codeblocks
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight-editor");
|
||||
} else if (!settings.bActiveLineHighlight && settings.bActiveCodeblockLineHighlight) {
|
||||
// Only inside codeblocks
|
||||
document.body.classList.add("codeblock-customizer-active-line-highlight-codeblock");
|
||||
}
|
||||
|
||||
if (settings.bEnableLineNumbers) {
|
||||
document.body.classList.add("codeblock-customizer-show-line-numbers");
|
||||
} else {
|
||||
document.body.classList.remove("codeblock-customizer-show-line-numbers");
|
||||
}
|
||||
|
||||
document.body.classList.remove("codeblock-customizer-show-langnames","codeblock-customizer-show-langnames-always");
|
||||
if (settings.header.bAlwaysDisplayCodeblockLang && settings.bDisplayCodeBlockLanguage) {
|
||||
document.body.classList.add("codeblock-customizer-show-langnames-always");
|
||||
} else if (settings.bDisplayCodeBlockLanguage) {
|
||||
document.body.classList.add("codeblock-customizer-show-langnames");
|
||||
}
|
||||
document.body.classList.remove("codeblock-customizer-show-langnames","codeblock-customizer-show-langnames-always");
|
||||
if (settings.header.bAlwaysDisplayCodeblockLang && settings.bDisplayCodeBlockLanguage) {
|
||||
document.body.classList.add("codeblock-customizer-show-langnames-always");
|
||||
} else if (settings.bDisplayCodeBlockLanguage) {
|
||||
document.body.classList.add("codeblock-customizer-show-langnames");
|
||||
}
|
||||
|
||||
document.body.classList.remove("codeblock-customizer-show-langicons","codeblock-customizer-show-langicons-always");
|
||||
if (settings.header.bAlwaysDisplayCodeblockIcon && settings.bDisplayCodeBlockIcon) {
|
||||
document.body.classList.add("codeblock-customizer-show-langicons-always");
|
||||
} else if (settings.bDisplayCodeBlockIcon) {
|
||||
document.body.classList.add("codeblock-customizer-show-langicons");
|
||||
}
|
||||
document.body.classList.remove("codeblock-customizer-show-langicons","codeblock-customizer-show-langicons-always");
|
||||
if (settings.header.bAlwaysDisplayCodeblockIcon && settings.bDisplayCodeBlockIcon) {
|
||||
document.body.classList.add("codeblock-customizer-show-langicons-always");
|
||||
} else if (settings.bDisplayCodeBlockIcon) {
|
||||
document.body.classList.add("codeblock-customizer-show-langicons");
|
||||
}
|
||||
|
||||
if (settings.bGutterHighlight) {
|
||||
document.body.classList.add('codeblock-customizer-gutter-highlight');
|
||||
} else {
|
||||
document.body.classList.remove('codeblock-customizer-gutter-highlight');
|
||||
}
|
||||
if (settings.bGutterHighlight) {
|
||||
document.body.classList.add('codeblock-customizer-gutter-highlight');
|
||||
} else {
|
||||
document.body.classList.remove('codeblock-customizer-gutter-highlight');
|
||||
}
|
||||
}// updateSettingStyles
|
||||
|
||||
function formatStyles(theme: {name: string, colors: CodeblockCustomizerColors},alternateColors) { //TODO (@mayurankv) Add type hint for alternateColors
|
||||
let current = theme['name'] == "current";
|
||||
let themeClass = ''
|
||||
let altHighlightStyles = ''
|
||||
if (theme['name'] == 'Light Theme') {
|
||||
themeClass = '.theme-light';
|
||||
altHighlightStyles = addAltHighlightColors(alternateColors,true);
|
||||
} else if (theme['name'] == 'Dark Theme') {
|
||||
themeClass = '.theme-dark';
|
||||
altHighlightStyles = addAltHighlightColors(alternateColors,false);
|
||||
} else if (theme['name'] != 'current') {
|
||||
return '';
|
||||
// themeClass = theme['name'].replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
return `
|
||||
body.codeblock-customizer${current ?'':themeClass} {
|
||||
${Object.keys(stylesDict).reduce((variables,key)=>{
|
||||
let cssVariable = `--codeblock-customizer-${stylesDict[key]}`;
|
||||
let cssValue = accessSetting(key,theme['colors']);
|
||||
let cssImportant = (current?' !important':'');
|
||||
if (cssValue != null) {
|
||||
return variables + `${cssVariable}: ${cssValue + cssImportant};`;
|
||||
} else {
|
||||
return variables;
|
||||
}
|
||||
},altHighlightStyles)}
|
||||
}
|
||||
`;
|
||||
let current = theme['name'] == "current";
|
||||
let themeClass = ''
|
||||
let altHighlightStyles = ''
|
||||
if (theme['name'] == 'Light Theme') {
|
||||
themeClass = '.theme-light';
|
||||
altHighlightStyles = addAltHighlightColors(alternateColors,true);
|
||||
} else if (theme['name'] == 'Dark Theme') {
|
||||
themeClass = '.theme-dark';
|
||||
altHighlightStyles = addAltHighlightColors(alternateColors,false);
|
||||
} else if (theme['name'] != 'current') {
|
||||
return '';
|
||||
// themeClass = theme['name'].replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
return `
|
||||
body.codeblock-customizer${current ?'':themeClass} {
|
||||
${Object.keys(stylesDict).reduce((variables,key)=>{
|
||||
let cssVariable = `--codeblock-customizer-${stylesDict[key]}`;
|
||||
let cssValue = accessSetting(key,theme['colors']);
|
||||
let cssImportant = (current?' !important':'');
|
||||
if (cssValue != null) {
|
||||
return variables + `${cssVariable}: ${cssValue + cssImportant};`;
|
||||
} else {
|
||||
return variables;
|
||||
}
|
||||
},altHighlightStyles)}
|
||||
}
|
||||
`;
|
||||
}// formatStyles
|
||||
|
||||
function addAltHighlightColors(alternateColors, lightTheme: boolean) { //TODO (@mayurankv) Add type hint for alternateColors
|
||||
let key = lightTheme?'lightColor':'darkColor';
|
||||
return alternateColors.reduce((altHighlightStyles,altHighlight) => {return altHighlightStyles + `--codeblock-customiser-highlight-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()}-color: ${altHighlight[key]};`},'')
|
||||
let key = lightTheme?'lightColor':'darkColor';
|
||||
return alternateColors.reduce((altHighlightStyles,altHighlight) => {return altHighlightStyles + `--codeblock-customiser-highlight-${altHighlight['name'].replace(/\s+/g, '-').toLowerCase()}-color: ${altHighlight[key]};`},'')
|
||||
}
|
||||
|
||||
function accessSetting(key: string, settings: CodeblockCustomizerSettings) {
|
||||
if (key in settings) {
|
||||
return settings[key];
|
||||
} else if ('header' in settings) {
|
||||
if (key in settings['header']) {
|
||||
return settings['header'][key];
|
||||
} else {
|
||||
let alt_key = key.charAt(6).toLowerCase()+key.slice(7);
|
||||
if (alt_key in settings['header']) {
|
||||
return settings['header'][alt_key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
if (key in settings) {
|
||||
return settings[key];
|
||||
} else if ('header' in settings) {
|
||||
if (key in settings['header']) {
|
||||
return settings['header'][key];
|
||||
} else {
|
||||
let alt_key = key.charAt(6).toLowerCase()+key.slice(7);
|
||||
if (alt_key in settings['header']) {
|
||||
return settings['header'][alt_key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -364,14 +364,14 @@ function accessSetting(key: string, settings: CodeblockCustomizerSettings) {
|
|||
|
||||
// Setting Management
|
||||
export function getCurrentMode() {
|
||||
const body = document.querySelector('body');
|
||||
if (body !== null){
|
||||
if (body.classList.contains('theme-light')) {
|
||||
return "light";
|
||||
} else if (body.classList.contains('theme-dark')) {
|
||||
return "dark";
|
||||
}
|
||||
}
|
||||
console.log('Warning: Couldn\'t get current theme');
|
||||
return "light";
|
||||
}
|
||||
const body = document.querySelector('body');
|
||||
if (body !== null){
|
||||
if (body.classList.contains('theme-light')) {
|
||||
return "light";
|
||||
} else if (body.classList.contains('theme-dark')) {
|
||||
return "dark";
|
||||
}
|
||||
}
|
||||
console.log('Warning: Couldn\'t get current theme');
|
||||
return "light";
|
||||
}
|
||||
|
|
|
|||
99
src/main.ts
99
src/main.ts
|
|
@ -1,77 +1,64 @@
|
|||
import { Plugin } from "obsidian";
|
||||
import { Extension } from "@codemirror/state";
|
||||
|
||||
import { DEFAULT_SETTINGS, CodeblockCustomizerSettings } from './Settings';
|
||||
import { codeblockHighlight } from "./CodeBlockHighlight";
|
||||
import { codeblockHeader, collapseField } from "./Header";
|
||||
import { ReadingView } from "./ReadingView";
|
||||
import { ReadingView } from "./ReadingViewOld";
|
||||
import { SettingsTab } from "./SettingsTab";
|
||||
import { getCurrentMode, loadIcons, BLOBS, updateSettingStyles } from "./Utils";
|
||||
|
||||
// npm i @simonwep/pickr
|
||||
import { loadIcons, BLOBS, updateSettingStyles } from "./Utils";
|
||||
|
||||
export default class CodeblockCustomizerPlugin extends Plugin {
|
||||
settings: CodeblockCustomizerSettings;
|
||||
extensions: Extension[];
|
||||
|
||||
async onload() {
|
||||
document.body.classList.add('codeblock-customizer');
|
||||
await this.loadSettings();
|
||||
this.extensions = [];
|
||||
settings: CodeblockCustomizerSettings;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
document.body.classList.add('codeblock-customizer');
|
||||
|
||||
// eslint main.ts
|
||||
|
||||
/* Problems to solve:
|
||||
- if a language is excluded then:
|
||||
- header needs to unfold before removing it,
|
||||
*/
|
||||
loadIcons();
|
||||
|
||||
loadIcons();
|
||||
codeblockHeader.settings = this.settings;
|
||||
collapseField.pluginSettings = this.settings;
|
||||
|
||||
this.registerEditorExtension([
|
||||
codeblockHeader,
|
||||
collapseField,
|
||||
codeblockHighlight(this.settings)
|
||||
]);
|
||||
|
||||
const settingsTab = new SettingsTab(this.app, this);
|
||||
this.addSettingTab(settingsTab);
|
||||
|
||||
//updateSettingStyles(this.settings);
|
||||
|
||||
this.registerEvent(this.app.workspace.on('css-change', this.handleCssChange.bind(this, settingsTab), this));
|
||||
|
||||
codeblockHeader.settings = this.settings;
|
||||
this.extensions.push(codeblockHeader);
|
||||
|
||||
collapseField.pluginSettings = this.settings;
|
||||
this.extensions.push(collapseField);
|
||||
// reading mode
|
||||
this.registerMarkdownPostProcessor(async (el, ctx) => {
|
||||
await ReadingView(el, ctx, this)
|
||||
})
|
||||
|
||||
this.extensions.push(codeblockHighlight(this.settings));
|
||||
|
||||
this.registerEditorExtension(this.extensions);
|
||||
|
||||
const settingsTab = new SettingsTab(this.app, this);
|
||||
this.addSettingTab(settingsTab);
|
||||
|
||||
updateSettingStyles(this.settings);
|
||||
|
||||
this.registerEvent(this.app.workspace.on('css-change', this.handleCssChange.bind(this, settingsTab), this));
|
||||
|
||||
// reading mode
|
||||
this.registerMarkdownPostProcessor(async (el, ctx) => {
|
||||
await ReadingView(el, ctx, this)
|
||||
})
|
||||
|
||||
console.log("loading CodeBlock Customizer plugin");
|
||||
}// onload
|
||||
|
||||
handleCssChange(settingsTab) {
|
||||
console.log('updating css');
|
||||
}// handleCssChange
|
||||
|
||||
onunload() {
|
||||
console.log("unloading CodeBlock Customizer plugin");
|
||||
// unload icons
|
||||
for (const url of Object.values(BLOBS)) {
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
console.log("loading CodeBlock Customizer plugin");
|
||||
}// onload
|
||||
|
||||
handleCssChange(settingsTab) {
|
||||
console.log('updating css');
|
||||
}// handleCssChange
|
||||
|
||||
onunload() {
|
||||
console.log("unloading CodeBlock Customizer plugin");
|
||||
// unload icons
|
||||
for (const url of Object.values(BLOBS)) {
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
this.app.workspace.updateOptions();
|
||||
// updateSettingStyles(this.settings);
|
||||
this.app.workspace.updateOptions();
|
||||
// updateSettingStyles(this.settings);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
238
styles.css
238
styles.css
File diff suppressed because one or more lines are too long
22
toDo.md
22
toDo.md
|
|
@ -1,22 +0,0 @@
|
|||
# ToDo
|
||||
|
||||
@mayurankv
|
||||
|
||||
1. Appearance issues:
|
||||
1. Too large line numbers with dynamic padding in source mode
|
||||
2. Folding transition animation? CSS won't work for this.
|
||||
2. Prevent delay to render in reading mode:
|
||||
1. Caused by changes to HTML such as:
|
||||
- Changing highlighted lines
|
||||
- Changing file name
|
||||
- Presumably changing line offset
|
||||
- Presumably changing fold name
|
||||
3. Refactor to make cleaner
|
||||
1. Sort settings structure and change corresponding code
|
||||
2. Modularise code better
|
||||
3. Reuse functions across live preview and reading mode
|
||||
4. Extra Settings
|
||||
1. Placeholder text for collapsed code
|
||||
1. Global placeholder in settings
|
||||
2. Optional parameter after fold:
|
||||
2. Let users redirect certain languages to icon of choice? Definitely not urgent if at all
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue