Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the beta and mobile markdown editors #6

Merged
merged 3 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 15 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@
"name": "joplin-plugin-markdown-table-colorize",
"version": "1.1.4",
"scripts": {
"dist": "webpack --joplin-plugin-config buildMain && webpack --joplin-plugin-config buildExtraScripts && webpack --joplin-plugin-config createArchive",
"dist": "webpack --env joplin-plugin-config=buildMain && webpack --env joplin-plugin-config=buildExtraScripts && webpack --env joplin-plugin-config=createArchive",
"prepare": "npm run dist",
"update": "npm install -g generator-joplin && yo joplin --update"
"updateVersion": "webpack --env joplin-plugin-config=updateVersion",
"update": "npm install -g generator-joplin && yo joplin --node-package-manager npm --update --force"
},
"license": "MIT",
"keywords": [
"joplin-plugin"
],
"devDependencies": {
"@types/node": "^14.0.14",
"@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.26.0",
"@types/node": "^18.7.13",
"chalk": "^4.1.0",
"copy-webpack-plugin": "^6.1.0",
"fs-extra": "^9.0.1",
"glob": "^7.1.6",
"on-build-webpack": "^0.1.0",
"tar": "^6.0.5",
"ts-loader": "^7.0.5",
"typescript": "^3.9.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"yargs": "^16.2.0"
"copy-webpack-plugin": "^11.0.0",
"fs-extra": "^10.1.0",
"glob": "^8.0.3",
"tar": "^6.1.11",
"ts-loader": "^9.3.1",
"typescript": "^4.8.2",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
}
}
2 changes: 1 addition & 1 deletion plugin.config.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extraScripts": []
"extraScripts": ["contentScripts/codeMirror6.ts"]
}
4 changes: 4 additions & 0 deletions src/mdTableColorize.js → src/contentScripts/codeMirror5.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ function calcState(line) {


function plugin(CodeMirror) {
if (CodeMirror.cm6) {
return;
}

CodeMirror.defineOption("mdTableColorize", false, async function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.off("changes", colorizeTable);
Expand Down
169 changes: 169 additions & 0 deletions src/contentScripts/codeMirror6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@

import { RangeSetBuilder } from '@codemirror/state';
import { ensureSyntaxTree } from '@codemirror/language';
import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';


type DecorationDescription = { from: number, to: number, decoration: Decoration };

function plugin(codeMirrorWrapper: any) {
if (!codeMirrorWrapper.cm6) return;

const cellDecorations: Decoration[] = [];
const getCellDecoration = (level: number) => {
while (level > cellDecorations.length) {
cellDecorations.push(Decoration.mark({ class: `cm-tabcolor-col${level}`}));
}
return cellDecorations[level - 1];
};
// Use line decorations for full headers and rows to prevent font styles
// from overriding more-specific styles set for individual cells.
const headerDecoration = Decoration.line({ class: 'cm-tabcolor-header' });
const rowDecoration = Decoration.line({ class: 'cm-tabcolor-row' });
// Use a mark decoration to avoid changing the background color for the full line.
const delimiterRowDecoration = Decoration.mark({ class: 'cm-tabcolor-delimiter-row' });

// See https://codemirror.net/examples/zebra/ for more on decorations in
// CodeMirror 6.
const decoratorPlugin = ViewPlugin.fromClass(class {
public decorations: DecorationSet;

public constructor(editor: EditorView) {
this.updateDecorations(editor);
}

public update(viewUpdate: ViewUpdate) {
if (viewUpdate.docChanged || viewUpdate.viewportChanged) {
this.updateDecorations(viewUpdate.view);
}
}

private updateDecorations(view: EditorView) {
const decorations: DecorationDescription[] = [];
// Extends the decoration most recently added to `decorations` to
// extend to `position`.
// This is intended to allow extending the previous cell on the current
// line. As such, decorations on previous lines are ignored.
const extendPreviousCellToInclude = (position: number) => {
if (decorations.length > 0) {
const lastDecoration = decorations[decorations.length - 1];
const doc = view.state.doc;
const lastLineNumber = doc.lineAt(lastDecoration.to).number;
const extendToLineNumber = doc.lineAt(position).number;

// Only extend the previous decoration if it's for a cell
// on the same line
if (lastLineNumber === extendToLineNumber) {
decorations[decorations.length - 1] = {
from: lastDecoration.from,
to: position,
decoration: lastDecoration.decoration,
};
}
}
}

for (const { from, to } of view.visibleRanges) {
let column = 0;
let nextCellStart = 0;
let inRowOrHeader = false;

type NodeType = { from: number, name: string, to: number };
let previousNode: NodeType|null = null;

const addCell = (node: NodeType) => {
column ++;
const decoration = getCellDecoration(column);
decorations.push({
from: nextCellStart,
to: node.to,
decoration,
});
nextCellStart = node.to;
};

ensureSyntaxTree(view.state, to)
.iterate({
from, to,
enter: node => {
if (node.name === 'TableRow' || node.name === 'TableHeader') {
column = 0;
nextCellStart = node.from;
inRowOrHeader = true;
}
else if (node.name === 'TableDelimiter') {
// When table cells are empty, TableCells are
// not reported in the CodeMirror syntax tree
if (previousNode.name === 'TableDelimiter') {
addCell(previousNode);
}
if (previousNode.name !== 'TableRow' && previousNode.name !== 'TableHeader') {
extendPreviousCellToInclude(node.to);
nextCellStart = node.to;
}
}
else if (node.name === 'TableCell') {
addCell(node);
}

// node stores a reference to the current syntax tree node,
// so we need to copy it:
previousNode = { from: node.from, name: node.name, to: node.to };
},
leave: node => {
if (node.name === 'TableRow' || node.name === 'TableHeader') {
extendPreviousCellToInclude(node.to);

decorations.push({
// We use a full-line decoration, so use the
// same from and to:
from: node.from,
to: node.from,

decoration: node.name === 'TableRow' ? rowDecoration : headerDecoration,
});

inRowOrHeader = false;
}
// The table separator just below the header is a single node
// with name TableDelimiter. Handle this case:
else if (node.name === 'TableDelimiter' && !inRowOrHeader) {
decorations.push({
from: node.from,
to: node.to,
decoration: delimiterRowDecoration,
});
}
},
});
}
// To add to a RangeSetBuilder, decorations need to be sorted
// first by start position, then by length.
decorations.sort((a, b) => {
if (a.from !== b.from) {
return a.from - b.from;
}
return a.to - b.to;
});

const decorationBuilder = new RangeSetBuilder<Decoration>();
for (const decorationSpec of decorations) {
decorationBuilder.add(decorationSpec.from, decorationSpec.to, decorationSpec.decoration);
}
this.decorations = decorationBuilder.finish();
}
}, { decorations: extension => extension.decorations });

codeMirrorWrapper.addExtension([
decoratorPlugin,
]);
}

export default function(_context: any) {
return {
plugin: plugin,
assets: function() {
return [ { name: "tabcolor.css" } ];
}
}
};
6 changes: 6 additions & 0 deletions src/tabcolor.css → src/contentScripts/tabcolor.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
font-weight: bolder;
color: var(--joplin-color);
}
/* CodeMirror 6 only */
.cm-tabcolor-delimiter-row {
background-color: #CCCCCC;
color: #212529;
}

.cm-tabcolor-col1, .cm-tabcolor-col9 {
background-color: #FFECED;
color: #212529;
Expand Down
9 changes: 7 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ joplin.plugins.register({
console.info('Markdown Table: Colorize started!');
await joplin.contentScripts.register(
ContentScriptType.CodeMirrorPlugin,
'mdTableColorize',
'./mdTableColorize.js'
'mdTableColorize-cm5',
'./contentScripts/codeMirror5.js'
);
await joplin.contentScripts.register(
ContentScriptType.CodeMirrorPlugin,
'mdTableColorize-cm6',
'./contentScripts/codeMirror6.js'
);
},
});