feat(share): enable syntax highlighting

This commit is contained in:
Elian Doran 2025-06-09 18:22:30 +03:00
parent 54ffeeaed9
commit 1bcb811835
No known key found for this signature in database
8 changed files with 82 additions and 47 deletions

View File

@ -109,39 +109,6 @@ function isClipboardEmpty() {
return clipboardBranchIds.length === 0;
}
export function copyText(text: string) {
if (!text) {
return;
}
let succeeded = false;
try {
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
succeeded = true;
} else {
// Fallback method: https://stackoverflow.com/a/72239825
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
succeeded = document.execCommand('copy');
document.body.removeChild(textArea);
}
} catch (e) {
console.warn(e);
succeeded = false;
}
if (succeeded) {
toast.showMessage(t("clipboard.copy_success"));
} else {
toast.showError(t("clipboard.copy_failed"));
}
}
export default {
pasteAfter,
pasteInto,

View File

@ -0,0 +1,37 @@
export function copyText(text: string) {
if (!text) {
return;
}
try {
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
return true;
} else {
// Fallback method: https://stackoverflow.com/a/72239825
const textArea = document.createElement("textarea");
textArea.value = text;
try {
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return document.execCommand('copy');
} finally {
document.body.removeChild(textArea);
}
}
} catch (e) {
console.warn(e);
return false;
}
}
export async function copyTextWithToast(text: string) {
const t = (await import("./i18n.js")).t;
const toast = (await import("./toast.js")).default;
if (copyText(text)) {
toast.showMessage(t("clipboard.copy_success"));
} else {
toast.showError(t("clipboard.copy_failed"));
}
}

View File

@ -1,4 +1,5 @@
import server from "./server.js";
import { isShare } from "./utils.js";
type OptionValue = number | string;
@ -7,7 +8,9 @@ class Options {
private arr!: Record<string, OptionValue>;
constructor() {
this.initializedPromise = server.get<Record<string, OptionValue>>("options").then((data) => this.load(data));
if (!isShare) {
this.initializedPromise = server.get<Record<string, OptionValue>>("options").then((data) => this.load(data));
}
}
load(arr: Record<string, OptionValue>) {

View File

@ -1,4 +1,4 @@
import utils from "./utils.js";
import utils, { isShare } from "./utils.js";
import ValidationError from "./validation_error.js";
type Headers = Record<string, string | null | undefined>;
@ -28,6 +28,10 @@ export interface StandardResponse {
}
async function getHeaders(headers?: Headers) {
if (isShare) {
return {};
}
const appContext = (await import("../components/app_context.js")).default;
const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null;

View File

@ -2,7 +2,9 @@ import { ensureMimeTypes, highlight, highlightAuto, loadTheme, Themes, type Auto
import mime_types from "./mime_types.js";
import options from "./options.js";
import { t } from "./i18n.js";
import { copyText } from "./clipboard.js";
import { copyText } from "./clipboard_ext.js";
import { isShare } from "./utils.js";
import { MimeType } from "@triliumnext/commons";
let highlightingLoaded = false;
@ -14,9 +16,6 @@ let highlightingLoaded = false;
*/
export async function formatCodeBlocks($container: JQuery<HTMLElement>) {
const syntaxHighlightingEnabled = isSyntaxHighlightEnabled();
if (syntaxHighlightingEnabled) {
await ensureMimeTypesForHighlighting();
}
const codeBlocks = $container.find("pre code");
for (const codeBlock of codeBlocks) {
@ -49,11 +48,11 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
const text = $codeBlock.text();
let highlightedText: HighlightResult | AutoHighlightResult | null = null;
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO) {
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO && !isShare) {
await ensureMimeTypesForHighlighting();
highlightedText = highlightAuto(text);
} else if (normalizedMimeType) {
await ensureMimeTypesForHighlighting();
await ensureMimeTypesForHighlighting(normalizedMimeType);
highlightedText = highlight(text, { language: normalizedMimeType });
}
@ -62,7 +61,7 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
}
}
export async function ensureMimeTypesForHighlighting() {
export async function ensureMimeTypesForHighlighting(mimeTypeHint?: string) {
if (highlightingLoaded) {
return;
}
@ -72,7 +71,20 @@ export async function ensureMimeTypesForHighlighting() {
loadHighlightingTheme(currentThemeName);
// Load mime types.
const mimeTypes = mime_types.getMimeTypes();
let mimeTypes: MimeType[];
if (mimeTypeHint) {
mimeTypes = [
{
title: mimeTypeHint,
enabled: true,
mime: mimeTypeHint.replace("-", "/")
}
]
} else {
mimeTypes = mime_types.getMimeTypes();
}
await ensureMimeTypes(mimeTypes);
highlightingLoaded = true;
@ -96,8 +108,12 @@ export function loadHighlightingTheme(themeName: string) {
* @returns whether syntax highlighting should be enabled for code blocks.
*/
export function isSyntaxHighlightEnabled() {
const theme = options.get("codeBlockTheme");
return !!theme && theme !== "none";
if (!isShare) {
const theme = options.get("codeBlockTheme");
return !!theme && theme !== "none";
} else {
return true;
}
}
/**

View File

@ -4,6 +4,8 @@ import type { ViewScope } from "./link.js";
const SVG_MIME = "image/svg+xml";
export const isShare = !window.glob;
function reloadFrontendApp(reason?: string) {
if (reason) {
logInfo(`Frontend app reload: ${reason}`);

View File

@ -3,6 +3,12 @@ import "@triliumnext/ckeditor5/content.css";
import "@triliumnext/share-theme/styles/index.css";
import "@triliumnext/share-theme/scripts/index.js";
import { formatCodeBlocks } from "./services/syntax_highlight.js";
import $ from "jquery";
window.$ = $;
formatCodeBlocks($("#content"));
/**
* Fetch note with given ID from backend
*

View File

@ -6,7 +6,7 @@ import options from "../../../services/options.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import utils from "../../../services/utils.js";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/emoji_definitions/en.json?url";
import { copyText } from "../../../services/clipboard.js";
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
const TEXT_FORMATTING_GROUP = {
label: "Text formatting",
@ -116,7 +116,7 @@ export function buildConfig(): EditorConfig {
enabled: isSyntaxHighlightEnabled()
},
clipboard: {
copy: copyText
copy: copyTextWithToast
},
// This value must be kept in sync with the language defined in webpack.config.js.
language: "en"