mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 18:12:29 +08:00
feat(client): integrate katex
This commit is contained in:
parent
255e529714
commit
7b787fff59
@ -40,6 +40,7 @@
|
|||||||
"jquery-hotkeys": "0.2.2",
|
"jquery-hotkeys": "0.2.2",
|
||||||
"jquery.fancytree": "2.38.5",
|
"jquery.fancytree": "2.38.5",
|
||||||
"jsplumb": "2.15.6",
|
"jsplumb": "2.15.6",
|
||||||
|
"katex": "0.16.22",
|
||||||
"knockout": "3.5.1",
|
"knockout": "3.5.1",
|
||||||
"leaflet": "1.9.4",
|
"leaflet": "1.9.4",
|
||||||
"leaflet-gpx": "2.2.0",
|
"leaflet-gpx": "2.2.0",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import renderService from "./render.js";
|
import renderService from "./render.js";
|
||||||
import protectedSessionService from "./protected_session.js";
|
import protectedSessionService from "./protected_session.js";
|
||||||
import protectedSessionHolder from "./protected_session_holder.js";
|
import protectedSessionHolder from "./protected_session_holder.js";
|
||||||
import libraryLoader from "./library_loader.js";
|
|
||||||
import openService from "./open.js";
|
import openService from "./open.js";
|
||||||
import froca from "./froca.js";
|
import froca from "./froca.js";
|
||||||
import utils from "./utils.js";
|
import utils from "./utils.js";
|
||||||
@ -16,6 +15,7 @@ import { normalizeMimeTypeForCKEditor } from "./mime_type_definitions.js";
|
|||||||
import renderDoc from "./doc_renderer.js";
|
import renderDoc from "./doc_renderer.js";
|
||||||
import { t } from "../services/i18n.js";
|
import { t } from "../services/i18n.js";
|
||||||
import WheelZoom from 'vanilla-js-wheel-zoom';
|
import WheelZoom from 'vanilla-js-wheel-zoom';
|
||||||
|
import { renderMathInElement } from "./math.js";
|
||||||
|
|
||||||
let idCounter = 1;
|
let idCounter = 1;
|
||||||
|
|
||||||
@ -94,8 +94,6 @@ async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HT
|
|||||||
$renderedContent.append($('<div class="ck-content">').html(blob.content));
|
$renderedContent.append($('<div class="ck-content">').html(blob.content));
|
||||||
|
|
||||||
if ($renderedContent.find("span.math-tex").length > 0) {
|
if ($renderedContent.find("span.math-tex").length > 0) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
|
||||||
|
|
||||||
renderMathInElement($renderedContent[0], { trust: true });
|
renderMathInElement($renderedContent[0], { trust: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,5 @@ export default {
|
|||||||
requireCss,
|
requireCss,
|
||||||
requireLibrary,
|
requireLibrary,
|
||||||
loadHighlightingTheme,
|
loadHighlightingTheme,
|
||||||
KATEX,
|
|
||||||
HIGHLIGHT_JS
|
HIGHLIGHT_JS
|
||||||
};
|
};
|
||||||
|
5
apps/client/src/services/math.ts
Normal file
5
apps/client/src/services/math.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import katex from "katex";
|
||||||
|
import "katex/contrib/mhchem";
|
||||||
|
import "katex/dist/katex.min.css";
|
||||||
|
export { default as renderMathInElement } from "katex/contrib/auto-render";
|
||||||
|
export default katex;
|
7
apps/client/src/types-lib.d.ts
vendored
7
apps/client/src/types-lib.d.ts
vendored
@ -24,3 +24,10 @@ declare module "draggabilly" {
|
|||||||
declare module "@mind-elixir/node-menu" {
|
declare module "@mind-elixir/node-menu" {
|
||||||
export default mindmap;
|
export default mindmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module "katex/contrib/auto-render" {
|
||||||
|
var renderMathInElement: (element: HTMLElement, options: {
|
||||||
|
trust: boolean;
|
||||||
|
}) => void;
|
||||||
|
export default renderMathInElement;
|
||||||
|
}
|
||||||
|
9
apps/client/src/types.d.ts
vendored
9
apps/client/src/types.d.ts
vendored
@ -131,15 +131,6 @@ declare global {
|
|||||||
language: string
|
language: string
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var renderMathInElement: (element: HTMLElement, options: {
|
|
||||||
trust: boolean;
|
|
||||||
}) => void;
|
|
||||||
|
|
||||||
var katex: {
|
|
||||||
renderToString(text: string, opts: {
|
|
||||||
throwOnError: boolean
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Panzoom
|
* Panzoom
|
||||||
|
@ -3,7 +3,6 @@ import utils from "../../services/utils.js";
|
|||||||
import server from "../../services/server.js";
|
import server from "../../services/server.js";
|
||||||
import toastService from "../../services/toast.js";
|
import toastService from "../../services/toast.js";
|
||||||
import appContext from "../../components/app_context.js";
|
import appContext from "../../components/app_context.js";
|
||||||
import libraryLoader from "../../services/library_loader.js";
|
|
||||||
import openService from "../../services/open.js";
|
import openService from "../../services/open.js";
|
||||||
import protectedSessionHolder from "../../services/protected_session_holder.js";
|
import protectedSessionHolder from "../../services/protected_session_holder.js";
|
||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
@ -12,6 +11,7 @@ import options from "../../services/options.js";
|
|||||||
import type FNote from "../../entities/fnote.js";
|
import type FNote from "../../entities/fnote.js";
|
||||||
import type { NoteType } from "../../entities/fnote.js";
|
import type { NoteType } from "../../entities/fnote.js";
|
||||||
import { Dropdown, Modal } from "bootstrap";
|
import { Dropdown, Modal } from "bootstrap";
|
||||||
|
import { renderMathInElement } from "../../services/math.js";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
const TPL = /*html*/`
|
||||||
<div class="revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
<div class="revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
||||||
@ -315,8 +315,6 @@ export default class RevisionsDialog extends BasicWidget {
|
|||||||
this.$content.html(`<div class="ck-content">${fullRevision.content}</div>`);
|
this.$content.html(`<div class="ck-content">${fullRevision.content}</div>`);
|
||||||
|
|
||||||
if (this.$content.find("span.math-tex").length > 0) {
|
if (this.$content.find("span.math-tex").length > 0) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
|
||||||
|
|
||||||
renderMathInElement(this.$content[0], { trust: true });
|
renderMathInElement(this.$content[0], { trust: true });
|
||||||
}
|
}
|
||||||
} else if (revisionItem.type === "code") {
|
} else if (revisionItem.type === "code") {
|
||||||
|
@ -11,8 +11,8 @@ import RightPanelWidget from "./right_panel_widget.js";
|
|||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import OnClickButtonWidget from "./buttons/onclick_button.js";
|
import OnClickButtonWidget from "./buttons/onclick_button.js";
|
||||||
import appContext, { type EventData } from "../components/app_context.js";
|
import appContext, { type EventData } from "../components/app_context.js";
|
||||||
import libraryLoader from "../services/library_loader.js";
|
|
||||||
import type FNote from "../entities/fnote.js";
|
import type FNote from "../entities/fnote.js";
|
||||||
|
import katex from "../services/math.js";
|
||||||
|
|
||||||
const TPL = /*html*/`<div class="highlights-list-widget">
|
const TPL = /*html*/`<div class="highlights-list-widget">
|
||||||
<style>
|
<style>
|
||||||
@ -175,7 +175,6 @@ export default class HighlightsListWidget extends RightPanelWidget {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ReferenceError && e.message.includes("katex is not defined")) {
|
if (e instanceof ReferenceError && e.message.includes("katex is not defined")) {
|
||||||
// Load KaTeX if it is not already loaded
|
// Load KaTeX if it is not already loaded
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
|
||||||
try {
|
try {
|
||||||
rendered = katex.renderToString(latexCode, {
|
rendered = katex.renderToString(latexCode, {
|
||||||
throwOnError: false
|
throwOnError: false
|
||||||
|
@ -19,7 +19,7 @@ import RightPanelWidget from "./right_panel_widget.js";
|
|||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import OnClickButtonWidget from "./buttons/onclick_button.js";
|
import OnClickButtonWidget from "./buttons/onclick_button.js";
|
||||||
import appContext, { type EventData } from "../components/app_context.js";
|
import appContext, { type EventData } from "../components/app_context.js";
|
||||||
import libraryLoader from "../services/library_loader.js";
|
import katex from "../services/math.js";
|
||||||
import type FNote from "../entities/fnote.js";
|
import type FNote from "../entities/fnote.js";
|
||||||
|
|
||||||
const TPL = /*html*/`<div class="toc-widget">
|
const TPL = /*html*/`<div class="toc-widget">
|
||||||
@ -59,7 +59,7 @@ const TPL = /*html*/`<div class="toc-widget">
|
|||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 7px;
|
padding-left: 7px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
@ -234,7 +234,6 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ReferenceError && e.message.includes("katex is not defined")) {
|
if (e instanceof ReferenceError && e.message.includes("katex is not defined")) {
|
||||||
// Load KaTeX if it is not already loaded
|
// Load KaTeX if it is not already loaded
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
|
||||||
try {
|
try {
|
||||||
rendered = katex.renderToString(latexCode, {
|
rendered = katex.renderToString(latexCode, {
|
||||||
throwOnError: false
|
throwOnError: false
|
||||||
@ -277,13 +276,13 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
let curLevel = 2;
|
let curLevel = 2;
|
||||||
const $ols = [$toc];
|
const $ols = [$toc];
|
||||||
let $previousLi: JQuery<HTMLElement> | undefined;
|
let $previousLi: JQuery<HTMLElement> | undefined;
|
||||||
|
|
||||||
if (!(this.noteContext?.viewScope?.tocCollapsedHeadings instanceof Set)) {
|
if (!(this.noteContext?.viewScope?.tocCollapsedHeadings instanceof Set)) {
|
||||||
this.noteContext!.viewScope!.tocCollapsedHeadings = new Set<string>();
|
this.noteContext!.viewScope!.tocCollapsedHeadings = new Set<string>();
|
||||||
}
|
}
|
||||||
const tocCollapsedHeadings = this.noteContext!.viewScope!.tocCollapsedHeadings as Set<string>;
|
const tocCollapsedHeadings = this.noteContext!.viewScope!.tocCollapsedHeadings as Set<string>;
|
||||||
const validHeadingKeys = new Set<string>(); // Used to clean up obsolete entries in tocCollapsedHeadings
|
const validHeadingKeys = new Set<string>(); // Used to clean up obsolete entries in tocCollapsedHeadings
|
||||||
|
|
||||||
let headingCount = 0;
|
let headingCount = 0;
|
||||||
for (let m = null, headingIndex = 0; (m = headingTagsRegex.exec(html)) !== null; headingIndex++) {
|
for (let m = null, headingIndex = 0; (m = headingTagsRegex.exec(html)) !== null; headingIndex++) {
|
||||||
//
|
//
|
||||||
@ -301,7 +300,7 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
if ($previousLi) {
|
if ($previousLi) {
|
||||||
const headingKey = `h${newLevel}_${headingIndex}_${$previousLi?.text().trim()}`;
|
const headingKey = `h${newLevel}_${headingIndex}_${$previousLi?.text().trim()}`;
|
||||||
this.setupCollapsibleHeading($ol, $previousLi, headingKey, tocCollapsedHeadings, validHeadingKeys);
|
this.setupCollapsibleHeading($ol, $previousLi, headingKey, tocCollapsedHeadings, validHeadingKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (levelDelta < 0) {
|
} else if (levelDelta < 0) {
|
||||||
// Close as many lists as curLevel - newLevel
|
// Close as many lists as curLevel - newLevel
|
||||||
@ -406,7 +405,7 @@ export default class TocWidget extends RightPanelWidget {
|
|||||||
const willCollapse = !$previousLi.hasClass("collapsed");
|
const willCollapse = !$previousLi.hasClass("collapsed");
|
||||||
$previousLi.addClass("animating");
|
$previousLi.addClass("animating");
|
||||||
|
|
||||||
if (willCollapse) { // Collapse
|
if (willCollapse) { // Collapse
|
||||||
$ol.css("maxHeight", `${$ol.prop("scrollHeight")}px`);
|
$ol.css("maxHeight", `${$ol.prop("scrollHeight")}px`);
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
@ -310,7 +310,9 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
math: {
|
math: {
|
||||||
engine: "katex",
|
engine: "katex",
|
||||||
outputType: "span", // or script
|
outputType: "span", // or script
|
||||||
lazyLoad: async () => await libraryLoader.requireLibrary(libraryLoader.KATEX),
|
lazyLoad: async () => {
|
||||||
|
(window as any).katex = (await import("../../services/math.js")).default
|
||||||
|
},
|
||||||
forceOutputType: false, // forces output to use outputType
|
forceOutputType: false, // forces output to use outputType
|
||||||
enablePreview: true // Enable preview view
|
enablePreview: true // Enable preview view
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
|
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
|
||||||
import libraryLoader from "../../services/library_loader.js";
|
|
||||||
import { applySyntaxHighlight } from "../../services/syntax_highlight.js";
|
import { applySyntaxHighlight } from "../../services/syntax_highlight.js";
|
||||||
import type FNote from "../../entities/fnote.js";
|
import type FNote from "../../entities/fnote.js";
|
||||||
import type { CommandListenerData, EventData } from "../../components/app_context.js";
|
import type { CommandListenerData, EventData } from "../../components/app_context.js";
|
||||||
import { getLocaleById } from "../../services/i18n.js";
|
import { getLocaleById } from "../../services/i18n.js";
|
||||||
import appContext from "../../components/app_context.js";
|
import appContext from "../../components/app_context.js";
|
||||||
import { getMermaidConfig } from "../../services/mermaid.js";
|
import { getMermaidConfig } from "../../services/mermaid.js";
|
||||||
|
import { renderMathInElement } from "../../services/math.js";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
const TPL = /*html*/`
|
||||||
<div class="note-detail-readonly-text note-detail-printable" tabindex="100">
|
<div class="note-detail-readonly-text note-detail-printable" tabindex="100">
|
||||||
@ -121,8 +121,6 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (this.$content.find("span.math-tex").length > 0) {
|
if (this.$content.find("span.math-tex").length > 0) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
|
||||||
|
|
||||||
renderMathInElement(this.$content[0], { trust: true });
|
renderMathInElement(this.$content[0], { trust: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,7 @@
|
|||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@types/xml2js": "0.4.14",
|
"@types/xml2js": "0.4.14",
|
||||||
"express-http-proxy": "2.1.1",
|
"express-http-proxy": "2.1.1",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"katex": "0.16.22",
|
|
||||||
"@anthropic-ai/sdk": "0.51.0",
|
"@anthropic-ai/sdk": "0.51.0",
|
||||||
"@braintree/sanitize-url": "7.1.1",
|
"@braintree/sanitize-url": "7.1.1",
|
||||||
"@triliumnext/commons": "workspace:*",
|
"@triliumnext/commons": "workspace:*",
|
||||||
|
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@ -257,6 +257,9 @@ importers:
|
|||||||
jsplumb:
|
jsplumb:
|
||||||
specifier: 2.15.6
|
specifier: 2.15.6
|
||||||
version: 2.15.6
|
version: 2.15.6
|
||||||
|
katex:
|
||||||
|
specifier: 0.16.22
|
||||||
|
version: 0.16.22
|
||||||
knockout:
|
knockout:
|
||||||
specifier: 3.5.1
|
specifier: 3.5.1
|
||||||
version: 3.5.1
|
version: 3.5.1
|
||||||
@ -725,9 +728,6 @@ importers:
|
|||||||
jsdom:
|
jsdom:
|
||||||
specifier: 26.1.0
|
specifier: 26.1.0
|
||||||
version: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
|
version: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
|
||||||
katex:
|
|
||||||
specifier: 0.16.22
|
|
||||||
version: 0.16.22
|
|
||||||
marked:
|
marked:
|
||||||
specifier: 15.0.11
|
specifier: 15.0.11
|
||||||
version: 15.0.11
|
version: 15.0.11
|
||||||
|
Loading…
x
Reference in New Issue
Block a user