@simple-mark/codemirror 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +10 -3
- package/index.js +32 -11
- package/package.json +3 -3
package/index.d.ts
CHANGED
|
@@ -22,11 +22,15 @@ export declare function links(): Extension;
|
|
|
22
22
|
//#region packages/codemirror/src/image-resolver.d.ts
|
|
23
23
|
/**
|
|
24
24
|
* Turns a path as written in the document into a URL to load, or several to try in order
|
|
25
|
-
* (the first that loads is shown), or null if it can't be loaded.
|
|
25
|
+
* (the first that loads is shown), or null if it can't be loaded. `undefined` means the host
|
|
26
|
+
* doesn't know yet (its file is still loading): the editor shows that it is loading, and the
|
|
27
|
+
* host calls `refreshImages` once it knows.
|
|
26
28
|
*/
|
|
27
|
-
type ImageResolver = (src: string) => string | readonly string[] | null;
|
|
29
|
+
type ImageResolver = (src: string) => string | readonly string[] | null | undefined;
|
|
28
30
|
/** How image (and file) paths are resolved; by default they are used as written. */
|
|
29
31
|
export declare const imageResolver: Facet<ImageResolver, ImageResolver>;
|
|
32
|
+
/** Resolves the images again, e.g. when files the resolver was waiting for have loaded. */
|
|
33
|
+
export declare function refreshImages(view: EditorView): void;
|
|
30
34
|
//#endregion
|
|
31
35
|
//#region packages/codemirror/src/previews.d.ts
|
|
32
36
|
/** Image and math previews; the source text always stays visible. */
|
|
@@ -84,7 +88,10 @@ export interface EditorOptions {
|
|
|
84
88
|
theme?: Theme;
|
|
85
89
|
/** Line ending to read and write ("\n", "\r\n"); by default the one `doc` uses. */
|
|
86
90
|
lineSeparator?: string;
|
|
87
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Turns an image path from the document into a URL to load (default: as written). Return
|
|
93
|
+
* undefined while the file is still loading, and call `refreshImages(view)` when it has.
|
|
94
|
+
*/
|
|
88
95
|
resolveImage?: ImageResolver;
|
|
89
96
|
/**
|
|
90
97
|
* Opens a followed link (Ctrl/Cmd+Click) or a clicked image preview. Default: web addresses
|
package/index.js
CHANGED
|
@@ -5,18 +5,24 @@ import { Decoration, EditorView, ViewPlugin, WidgetType, hoverTooltip, keymap, s
|
|
|
5
5
|
import { cellAt, charWidth, defaultTheme, headingAnchors, linkAt, linkKind, markdownExtensions, markdownStyles, mathSource, parseTable, previewBlocks, renderTable, resolveLineLook, resolveLook, rowLine } from "@simple-mark/model";
|
|
6
6
|
import { ensureSyntaxTree, syntaxTree } from "@codemirror/language";
|
|
7
7
|
//#region packages/codemirror/src/image-resolver.ts
|
|
8
|
-
/** The URLs a resolver gives for `src`, in order. */
|
|
8
|
+
/** The URLs a resolver gives for `src`, in order; undefined while the host is still loading. */
|
|
9
9
|
function resolvedUrls(resolve, src) {
|
|
10
10
|
const result = resolve(src);
|
|
11
|
-
return result === null ? [] : typeof result === "string" ? [result] : [...result];
|
|
11
|
+
return result === void 0 ? void 0 : result === null ? [] : typeof result === "string" ? [result] : [...result];
|
|
12
12
|
}
|
|
13
13
|
/** How image (and file) paths are resolved; by default they are used as written. */
|
|
14
14
|
const imageResolver = Facet.define({ combine: (values) => values[0] ?? ((src) => src) });
|
|
15
|
+
/** Asks the editor to resolve its images again. */
|
|
16
|
+
const imagesChanged = StateEffect.define();
|
|
17
|
+
/** Resolves the images again, e.g. when files the resolver was waiting for have loaded. */
|
|
18
|
+
function refreshImages(view) {
|
|
19
|
+
view.dispatch({ effects: imagesChanged.of(null) });
|
|
20
|
+
}
|
|
15
21
|
//#endregion
|
|
16
22
|
//#region packages/codemirror/src/links.ts
|
|
17
23
|
/** In a browser: web addresses and paths (resolved like images) open in a new tab. */
|
|
18
24
|
const openInBrowser = (target, view) => {
|
|
19
|
-
const url = target.kind === "web" ? target.url : resolvedUrls(view.state.facet(imageResolver), target.url)[0];
|
|
25
|
+
const url = target.kind === "web" ? target.url : resolvedUrls(view.state.facet(imageResolver), target.url)?.[0];
|
|
20
26
|
if (url) window.open(url, "_blank", "noopener,noreferrer");
|
|
21
27
|
};
|
|
22
28
|
/** How links are opened. */
|
|
@@ -252,10 +258,12 @@ var MarkdownDecorations = class {
|
|
|
252
258
|
let deco = this.cache.get(key);
|
|
253
259
|
if (!deco) {
|
|
254
260
|
const linked = styles.includes("link") || styles.includes("url");
|
|
261
|
+
const look = resolveLook([], styles, this.theme);
|
|
262
|
+
const keepLine = look.monospace !== void 0 || look.fontScale !== void 0;
|
|
255
263
|
deco = Decoration.mark({
|
|
256
264
|
class: styles.map((s) => `sm-${s}`).join(" "),
|
|
257
265
|
attributes: {
|
|
258
|
-
style: lookCss(
|
|
266
|
+
style: lookCss(look, this.theme) + (keepLine ? "; line-height: 0" : ""),
|
|
259
267
|
...linked ? { title: `${followKeyName}+Click to open` } : {}
|
|
260
268
|
}
|
|
261
269
|
});
|
|
@@ -620,9 +628,10 @@ const heightHints = StateField.define({
|
|
|
620
628
|
},
|
|
621
629
|
provide: (field) => EditorView.decorations.from(field)
|
|
622
630
|
});
|
|
631
|
+
const hintTheme = EditorView.baseTheme({ ".sm-height-hint + .cm-widgetBuffer": { verticalAlign: "top" } });
|
|
623
632
|
/** Better height estimates for headings and wrapping lines that are not drawn yet. */
|
|
624
633
|
function lineHeightHints() {
|
|
625
|
-
return heightHints;
|
|
634
|
+
return [heightHints, hintTheme];
|
|
626
635
|
}
|
|
627
636
|
//#endregion
|
|
628
637
|
//#region packages/codemirror/src/previews.ts
|
|
@@ -684,7 +693,15 @@ function imageRef(image, resolve) {
|
|
|
684
693
|
alt: image.alt,
|
|
685
694
|
problem: `No definition for ${image.raw}`
|
|
686
695
|
};
|
|
687
|
-
const
|
|
696
|
+
const urls = resolvedUrls(resolve, image.src);
|
|
697
|
+
if (urls === void 0) return {
|
|
698
|
+
raw: image.raw,
|
|
699
|
+
src: null,
|
|
700
|
+
alt: image.alt,
|
|
701
|
+
problem: `Loading ${image.raw}…`,
|
|
702
|
+
loading: true
|
|
703
|
+
};
|
|
704
|
+
const [src, ...fallbacks] = urls;
|
|
688
705
|
if (src === void 0) return {
|
|
689
706
|
raw: image.raw,
|
|
690
707
|
src: null,
|
|
@@ -729,14 +746,14 @@ var ImageWidget = class extends WidgetType {
|
|
|
729
746
|
if (--waiting === 0) rememberHeight(view, this.key, dom);
|
|
730
747
|
};
|
|
731
748
|
for (const image of this.images) {
|
|
732
|
-
const problem = (text) => {
|
|
749
|
+
const problem = (text, className = "sm-image-error") => {
|
|
733
750
|
const span = document.createElement("span");
|
|
734
|
-
span.className =
|
|
751
|
+
span.className = className;
|
|
735
752
|
span.textContent = text;
|
|
736
753
|
return span;
|
|
737
754
|
};
|
|
738
755
|
if (image.src === null) {
|
|
739
|
-
dom.appendChild(problem(image.problem ?? `Can't load ${image.raw}
|
|
756
|
+
dom.appendChild(problem(image.problem ?? `Can't load ${image.raw}`, image.loading ? "sm-image-loading" : "sm-image-error"));
|
|
740
757
|
continue;
|
|
741
758
|
}
|
|
742
759
|
waiting++;
|
|
@@ -798,7 +815,7 @@ function blockPreviews(state) {
|
|
|
798
815
|
const blockPreviewField = StateField.define({
|
|
799
816
|
create: blockPreviews,
|
|
800
817
|
update(previews, tr) {
|
|
801
|
-
return tr.docChanged || syntaxTree(tr.state) !== syntaxTree(tr.startState) || tr.state.facet(imageResolver) !== tr.startState.facet(imageResolver) || tr.effects.some((effect) => effect.is(refreshEstimates)) ? blockPreviews(tr.state) : previews;
|
|
818
|
+
return tr.docChanged || syntaxTree(tr.state) !== syntaxTree(tr.startState) || tr.state.facet(imageResolver) !== tr.startState.facet(imageResolver) || tr.effects.some((effect) => effect.is(refreshEstimates) || effect.is(imagesChanged)) ? blockPreviews(tr.state) : previews;
|
|
802
819
|
},
|
|
803
820
|
provide: (field) => EditorView.decorations.from(field)
|
|
804
821
|
});
|
|
@@ -860,6 +877,10 @@ const previewTheme = EditorView.theme({
|
|
|
860
877
|
color: "#cf222e",
|
|
861
878
|
fontSize: "0.9em"
|
|
862
879
|
},
|
|
880
|
+
".sm-image-loading": {
|
|
881
|
+
color: "#818b98",
|
|
882
|
+
fontSize: "0.9em"
|
|
883
|
+
},
|
|
863
884
|
".sm-math-preview": {
|
|
864
885
|
textAlign: "center",
|
|
865
886
|
padding: previewSpacing,
|
|
@@ -1140,4 +1161,4 @@ function createEditor(parent, options = {}) {
|
|
|
1140
1161
|
});
|
|
1141
1162
|
}
|
|
1142
1163
|
//#endregion
|
|
1143
|
-
export { createEditor, followLink, imageResolver, insertRowBelow, keepLineSeparator, linkOpener, links, lookCss, markdownDecorations, markdownTheme, nextCell, previews, previousCell, simpleMark, tableEditing };
|
|
1164
|
+
export { createEditor, followLink, imageResolver, insertRowBelow, keepLineSeparator, linkOpener, links, lookCss, markdownDecorations, markdownTheme, nextCell, previews, previousCell, refreshImages, simpleMark, tableEditing };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simple-mark/codemirror",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "CodeMirror 6 editor that styles Markdown without hiding its syntax.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@codemirror/state": "^6.7.6",
|
|
29
29
|
"@codemirror/view": "^6.43.15",
|
|
30
30
|
"@lezer/common": "^1.5.3",
|
|
31
|
-
"@simple-mark/math": "^0.3.
|
|
32
|
-
"@simple-mark/model": "^0.3.
|
|
31
|
+
"@simple-mark/math": "^0.3.4",
|
|
32
|
+
"@simple-mark/model": "^0.3.4"
|
|
33
33
|
}
|
|
34
34
|
}
|