@meowdown/core 0.72.0 → 0.73.0
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/dist/index.d.ts +26 -6
- package/dist/index.js +118 -15
- package/dist/style.css +234 -73
- package/package.json +13 -14
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { EditorView } from "@prosekit/pm/view";
|
|
|
7
7
|
import { EditorNode, Mark, ProseMirrorNode } from "@prosekit/pm/model";
|
|
8
8
|
import { ListAttrs } from "@prosekit/extensions/list";
|
|
9
9
|
import { HorizontalRuleExtension } from "@prosekit/extensions/horizontal-rule";
|
|
10
|
-
import { Resolver } from "@
|
|
10
|
+
import { Resolver, XPostMediaClickEvent } from "@meowdown/embed/x";
|
|
11
11
|
import { render } from "katex";
|
|
12
12
|
import { XPost, YouTubeVideo } from "@post-embed/types";
|
|
13
13
|
import { VirtualElement } from "@floating-ui/dom";
|
|
@@ -656,6 +656,11 @@ interface ImageClickPayload {
|
|
|
656
656
|
* from it; a touch surface delivers the `touchend` instead of a click.
|
|
657
657
|
*/
|
|
658
658
|
event: MouseEvent | TouchEvent | KeyboardEvent;
|
|
659
|
+
/**
|
|
660
|
+
* The rendered `<img>` of a click or tap, for example to zoom a lightbox
|
|
661
|
+
* from. A key press has none.
|
|
662
|
+
*/
|
|
663
|
+
element?: HTMLImageElement | undefined;
|
|
659
664
|
/**
|
|
660
665
|
* Whether the platform's mod key (`Command` on Apple, `Ctrl` elsewhere) was held
|
|
661
666
|
* beyond the gesture that triggered the activation.
|
|
@@ -823,7 +828,7 @@ interface ImageOptions {
|
|
|
823
828
|
mediaUrlProtocols?: string[];
|
|
824
829
|
/**
|
|
825
830
|
* Resolve the data behind a YouTube video URL, rendered as a
|
|
826
|
-
* `
|
|
831
|
+
* `meowdown-embed-youtube` card. Defaults to `defaultResolveYouTubeVideo`,
|
|
827
832
|
* which reads YouTube's oEmbed endpoint.
|
|
828
833
|
*/
|
|
829
834
|
resolveYouTubeVideo?: YouTubeVideoResolver;
|
|
@@ -1070,10 +1075,25 @@ export declare function inlineTextToMarkChunksWithContext(marks: TypedMarkBuilde
|
|
|
1070
1075
|
*/
|
|
1071
1076
|
type MarkMode = 'hide' | 'focus' | 'show';
|
|
1072
1077
|
//#endregion
|
|
1078
|
+
//#region src/extensions/x-post-media-click.d.ts
|
|
1079
|
+
/**
|
|
1080
|
+
* Receives the `meowdown-embed-media-click` event of an X post card. Its
|
|
1081
|
+
* `detail` holds the activated photo or video, its sibling items, and the
|
|
1082
|
+
* rendered thumbnail element. Call `event.preventDefault()` to cancel the
|
|
1083
|
+
* card's own default (open the photo URL, play the video in place).
|
|
1084
|
+
*/
|
|
1085
|
+
type XPostMediaClickHandler = (event: XPostMediaClickEvent) => void;
|
|
1086
|
+
/**
|
|
1087
|
+
* Call `onClick` when the user activates a photo or video inside an X post
|
|
1088
|
+
* card.
|
|
1089
|
+
*/
|
|
1090
|
+
export declare function defineXPostMediaClickHandler(getOnClick?: (state: EditorState) => XPostMediaClickHandler | undefined): PlainExtension;
|
|
1091
|
+
//#endregion
|
|
1073
1092
|
//#region src/extensions/editor-config-types.d.ts
|
|
1074
1093
|
interface EditorConfig extends InlineMarkOptions, FollowLinkHandlers, FilePasteOptions, FileViewOptions, ImageOptions {
|
|
1075
1094
|
markMode?: MarkMode;
|
|
1076
1095
|
onExitBoundary?: ExitBoundaryHandler;
|
|
1096
|
+
onXPostMediaClick?: XPostMediaClickHandler;
|
|
1077
1097
|
embedPaste?: boolean;
|
|
1078
1098
|
linkPaste?: boolean;
|
|
1079
1099
|
bulletAfterHeading?: boolean;
|
|
@@ -1162,7 +1182,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
|
|
|
1162
1182
|
fenceLength?: number | null;
|
|
1163
1183
|
};
|
|
1164
1184
|
};
|
|
1165
|
-
}>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, MeowdownHorizontalRuleExtension, import("@prosekit/core").Extension<{
|
|
1185
|
+
}>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, MeowdownHorizontalRuleExtension, import("@prosekit/core").Extension<{
|
|
1166
1186
|
Nodes: {
|
|
1167
1187
|
htmlComment: MeowdownHTMLCommentAttrs;
|
|
1168
1188
|
};
|
|
@@ -1226,7 +1246,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
|
|
|
1226
1246
|
Marks: {
|
|
1227
1247
|
mdPack: MdPackAttrs;
|
|
1228
1248
|
};
|
|
1229
|
-
}>]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<import("@prosekit/core").ExtensionTyping<any, any, any>>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Union<readonly [import("@prosekit/core").Extension<{
|
|
1249
|
+
}>]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<import("@prosekit/core").ExtensionTyping<any, any, any>>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Union<readonly [import("@prosekit/core").Extension<{
|
|
1230
1250
|
Commands: {
|
|
1231
1251
|
insertSoftBreak: [];
|
|
1232
1252
|
};
|
|
@@ -1409,7 +1429,7 @@ export declare const EDITOR_KEY_BINDINGS: {
|
|
|
1409
1429
|
readonly 'Mod-5': "Heading 5";
|
|
1410
1430
|
readonly 'Mod-6': "Heading 6";
|
|
1411
1431
|
readonly 'Mod-.': "Fold or unfold a bullet";
|
|
1412
|
-
readonly 'Shift-Enter': "Insert a line break";
|
|
1432
|
+
readonly 'Shift-Enter': "Insert a line break, or leave a code block from its end";
|
|
1413
1433
|
readonly 'Mod-Enter': "Follow the link under the caret, or cycle a checkbox task";
|
|
1414
1434
|
readonly 'Mod-Shift-Enter': "Cycle a circle checkbox task";
|
|
1415
1435
|
readonly 'Mod-Shift-7': "Ordered list";
|
|
@@ -1639,4 +1659,4 @@ export declare function getSelectedText(state: EditorState): string;
|
|
|
1639
1659
|
*/
|
|
1640
1660
|
export declare function getVirtualElementFromRange(view: EditorView, range: PositionRange): VirtualElement;
|
|
1641
1661
|
//#endregion
|
|
1642
|
-
export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, type EditorConfig, type EditorExtension, type EditorExtensionOptions, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, type PostEmbedSnapshot, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type RoundTripFidelity, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, type WikilinkOptions, type WikilinkPayload, type WikilinkResolution, type WikilinkResolver, type XPostResolver, type YouTubeVideoResolver, defineCodeBlockPreviewPlugin, definePlaceholder, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
|
|
1662
|
+
export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, type EditorConfig, type EditorExtension, type EditorExtensionOptions, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, type PostEmbedSnapshot, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type RoundTripFidelity, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, type WikilinkOptions, type WikilinkPayload, type WikilinkResolution, type WikilinkResolver, type XPostMediaClickHandler, type XPostResolver, type YouTubeVideoResolver, defineCodeBlockPreviewPlugin, definePlaceholder, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Priority, Priority as Priority$1, createMarkBuilders, createNodeBuilders, defineBaseCommands, defineBaseKeymap, defineClipboardSerializer, defineCommands, defineHistory, defineKeymap, defineMarkSpec, defineMarkView, defineNodeAttr, defineNodeSpec, definePlugin, findMarkRange, getMarkRange, getMarkType, getNodeType, isAllSelection, isApple, isAtBlockStart, isNodeSelection, isTextSelection, setBlockType, toggleNode, union, unsetBlockType, withPriority, withPriority as withPriority$1, withSkipCodeBlock } from "@prosekit/core";
|
|
1
|
+
import { Priority, Priority as Priority$1, createMarkBuilders, createNodeBuilders, defaultBlockAt, defineBaseCommands, defineBaseKeymap, defineClipboardSerializer, defineCommands, defineHistory, defineKeymap, defineMarkSpec, defineMarkView, defineNodeAttr, defineNodeSpec, definePlugin, findMarkRange, getMarkRange, getMarkType, getNodeType, isAllSelection, isApple, isAtBlockStart, isNodeSelection, isTextSelection, setBlockType, toggleNode, union, unsetBlockType, withPriority, withPriority as withPriority$1, withSkipCodeBlock } from "@prosekit/core";
|
|
2
2
|
import { defineCodeBlock, defineCodeBlockHighlight, defineCodeBlockPreviewPlugin, isCodeBlockPreviewHiddenDecoration } from "@prosekit/extensions/code-block";
|
|
3
3
|
import { definePlaceholder, definePlaceholder as definePlaceholder$1 } from "@prosekit/extensions/placeholder";
|
|
4
4
|
import { NodeSelection, Plugin, PluginKey, Selection, TextSelection } from "@prosekit/pm/state";
|
|
@@ -34,8 +34,8 @@ import { defineListCommands, defineListDropIndicator, defineListKeymap, defineLi
|
|
|
34
34
|
import { chainCommands, lift, newlineInCode, splitBlock } from "@prosekit/pm/commands";
|
|
35
35
|
import { closeHistory } from "@prosekit/pm/history";
|
|
36
36
|
import { defineHorizontalRule } from "@prosekit/extensions/horizontal-rule";
|
|
37
|
-
import { registerXPost } from "@
|
|
38
|
-
import { registerYouTubeVideo } from "@
|
|
37
|
+
import { X_POST_MEDIA_CLICK, registerXPost } from "@meowdown/embed/x";
|
|
38
|
+
import { registerYouTubeVideo } from "@meowdown/embed/youtube";
|
|
39
39
|
import { registerResizableHandleElement, registerResizableRootElement } from "@prosekit/web/resizable";
|
|
40
40
|
import { fromSyndication } from "@post-embed/exporter/x/syndication";
|
|
41
41
|
import { XPostSchema, YouTubeVideoSchema } from "@post-embed/schema";
|
|
@@ -602,6 +602,41 @@ function defineBulletAfterHeading(enabled) {
|
|
|
602
602
|
} }), Priority$1.high);
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
+
//#endregion
|
|
606
|
+
//#region src/extensions/click-below.ts
|
|
607
|
+
const clickBelowKey = new PluginKey("meowdown-click-below");
|
|
608
|
+
function acceptsCaretAtEnd(node) {
|
|
609
|
+
return node.isTextblock && !node.type.spec.code;
|
|
610
|
+
}
|
|
611
|
+
function handleMouseDown(view, event) {
|
|
612
|
+
if (event.target !== view.dom) return false;
|
|
613
|
+
if (event.button !== 0 || !view.editable) return false;
|
|
614
|
+
const { doc } = view.state;
|
|
615
|
+
const lastBlock = doc.lastChild;
|
|
616
|
+
if (!lastBlock || acceptsCaretAtEnd(lastBlock)) return false;
|
|
617
|
+
const lastBlockDOM = view.nodeDOM(doc.content.size - lastBlock.nodeSize);
|
|
618
|
+
if (!(lastBlockDOM instanceof HTMLElement)) return false;
|
|
619
|
+
if (event.clientY <= lastBlockDOM.getBoundingClientRect().bottom) return false;
|
|
620
|
+
const block = defaultBlockAt(doc.contentMatchAt(doc.childCount))?.createAndFill();
|
|
621
|
+
if (!block) return false;
|
|
622
|
+
event.preventDefault();
|
|
623
|
+
const end = doc.content.size;
|
|
624
|
+
const tr = view.state.tr.insert(end, block);
|
|
625
|
+
view.dispatch(tr.setSelection(TextSelection.create(tr.doc, end + 1)).scrollIntoView());
|
|
626
|
+
view.focus();
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* A press below the last block appends an empty paragraph and puts the caret
|
|
631
|
+
* in it, when that block would otherwise keep the caret inside itself.
|
|
632
|
+
*/
|
|
633
|
+
function defineClickBelow() {
|
|
634
|
+
return definePlugin(new Plugin({
|
|
635
|
+
key: clickBelowKey,
|
|
636
|
+
props: { handleDOMEvents: { mousedown: handleMouseDown } }
|
|
637
|
+
}));
|
|
638
|
+
}
|
|
639
|
+
|
|
605
640
|
//#endregion
|
|
606
641
|
//#region src/converters/html-to-md.ts
|
|
607
642
|
/**
|
|
@@ -2222,6 +2257,38 @@ function getCodeTokens(code, language) {
|
|
|
2222
2257
|
return loadLanguageSupport(trimmed).then((loaded) => loaded ? tokenize(code, loaded) : []);
|
|
2223
2258
|
}
|
|
2224
2259
|
|
|
2260
|
+
//#endregion
|
|
2261
|
+
//#region src/extensions/code-block-exit.ts
|
|
2262
|
+
/**
|
|
2263
|
+
* With the caret at the end of a code block, move it into the block below when
|
|
2264
|
+
* that block is an empty paragraph, and into a new default block otherwise.
|
|
2265
|
+
*/
|
|
2266
|
+
const exitCodeBlockAtEnd = (state, dispatch) => {
|
|
2267
|
+
const { $head, empty } = state.selection;
|
|
2268
|
+
if (!empty) return false;
|
|
2269
|
+
const codeBlock = $head.parent;
|
|
2270
|
+
if (!codeBlock.type.spec.code || $head.parentOffset !== codeBlock.content.size) return false;
|
|
2271
|
+
const container = $head.node(-1);
|
|
2272
|
+
const indexAfter = $head.indexAfter(-1);
|
|
2273
|
+
const after = $head.after();
|
|
2274
|
+
const next = container.maybeChild(indexAfter);
|
|
2275
|
+
if (next && isNodeOfType(next, "paragraph") && next.content.size === 0) {
|
|
2276
|
+
dispatch?.(state.tr.setSelection(TextSelection.create(state.doc, after + 1)).scrollIntoView());
|
|
2277
|
+
return true;
|
|
2278
|
+
}
|
|
2279
|
+
const type = defaultBlockAt(container.contentMatchAt(indexAfter));
|
|
2280
|
+
const block = type?.createAndFill();
|
|
2281
|
+
if (!type || !block || !container.canReplaceWith(indexAfter, indexAfter, type)) return false;
|
|
2282
|
+
if (dispatch) {
|
|
2283
|
+
const tr = state.tr.insert(after, block);
|
|
2284
|
+
dispatch(tr.setSelection(TextSelection.create(tr.doc, after + 1)).scrollIntoView());
|
|
2285
|
+
}
|
|
2286
|
+
return true;
|
|
2287
|
+
};
|
|
2288
|
+
function defineCodeBlockExitKeymap() {
|
|
2289
|
+
return defineKeymap({ "Mod-Enter": exitCodeBlockAtEnd });
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2225
2292
|
//#endregion
|
|
2226
2293
|
//#region src/extensions/code-block.ts
|
|
2227
2294
|
function defineFenceStyleAttr() {
|
|
@@ -2279,7 +2346,7 @@ function defineDollarFenceEnterRule() {
|
|
|
2279
2346
|
});
|
|
2280
2347
|
}
|
|
2281
2348
|
function defineCodeBlock$1() {
|
|
2282
|
-
return union(defineCodeBlock(), defineFenceStyleAttr(), defineFenceLengthAttr(), defineTildeFenceInputRule(), defineTildeFenceEnterRule(), defineDollarFenceEnterRule());
|
|
2349
|
+
return union(defineCodeBlock(), defineFenceStyleAttr(), defineFenceLengthAttr(), defineTildeFenceInputRule(), defineTildeFenceEnterRule(), defineDollarFenceEnterRule(), defineCodeBlockExitKeymap());
|
|
2283
2350
|
}
|
|
2284
2351
|
|
|
2285
2352
|
//#endregion
|
|
@@ -3037,6 +3104,9 @@ function getClosestImagePreview(target) {
|
|
|
3037
3104
|
if (!preview || preview.dataset.postEmbed != null) return;
|
|
3038
3105
|
return preview;
|
|
3039
3106
|
}
|
|
3107
|
+
function getPreviewImage(preview) {
|
|
3108
|
+
return preview.querySelector("img") ?? void 0;
|
|
3109
|
+
}
|
|
3040
3110
|
function findImageAt(state, pos) {
|
|
3041
3111
|
const range = getMarkRangeAt(state, pos, "mdImage");
|
|
3042
3112
|
if (!range) return;
|
|
@@ -3097,6 +3167,7 @@ function defineImageClickHandler(getOnClick) {
|
|
|
3097
3167
|
src: hit.src,
|
|
3098
3168
|
alt: hit.alt,
|
|
3099
3169
|
event,
|
|
3170
|
+
element: getPreviewImage(preview),
|
|
3100
3171
|
mod: isModEvent(event)
|
|
3101
3172
|
});
|
|
3102
3173
|
return true;
|
|
@@ -3149,6 +3220,7 @@ function defineImageClickHandler(getOnClick) {
|
|
|
3149
3220
|
src: hit.src,
|
|
3150
3221
|
alt: hit.alt,
|
|
3151
3222
|
event,
|
|
3223
|
+
element: getPreviewImage(preview),
|
|
3152
3224
|
mod: isModEvent(event)
|
|
3153
3225
|
});
|
|
3154
3226
|
return true;
|
|
@@ -3526,6 +3598,16 @@ function defineHTMLComment() {
|
|
|
3526
3598
|
});
|
|
3527
3599
|
}
|
|
3528
3600
|
|
|
3601
|
+
//#endregion
|
|
3602
|
+
//#region src/utils/to-positive-number.ts
|
|
3603
|
+
/**
|
|
3604
|
+
* The value rounded to an integer, or nothing unless it is a finite number
|
|
3605
|
+
* above zero.
|
|
3606
|
+
*/
|
|
3607
|
+
function toPositiveNumber(value) {
|
|
3608
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
|
|
3609
|
+
}
|
|
3610
|
+
|
|
3529
3611
|
//#endregion
|
|
3530
3612
|
//#region src/extensions/magic-comment.ts
|
|
3531
3613
|
const MAGIC_COMMENT_RE = /^<!--\s*(\{[\s\S]*?\})\s*-->/;
|
|
@@ -3556,9 +3638,6 @@ function parseMagicComment(comment) {
|
|
|
3556
3638
|
snapshot
|
|
3557
3639
|
};
|
|
3558
3640
|
}
|
|
3559
|
-
function toPositiveNumber(value) {
|
|
3560
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
|
|
3561
|
-
}
|
|
3562
3641
|
/**
|
|
3563
3642
|
* The canonical comment meowdown writes for the metadata. `--` inside a JSON
|
|
3564
3643
|
* string becomes `--`: the inline comment rule of `@lezer/markdown`
|
|
@@ -3606,7 +3685,12 @@ const defaultResolveXPost = cached(async (url) => {
|
|
|
3606
3685
|
const response = await fetch(X_POST_API + id);
|
|
3607
3686
|
if (!response.ok) return;
|
|
3608
3687
|
const json = await response.json();
|
|
3609
|
-
|
|
3688
|
+
const result = fromSyndication(json.data);
|
|
3689
|
+
if (result.issues) {
|
|
3690
|
+
console.warn(`[meowdown] Invalid X post data for ${url}:`, result.issues);
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
return result.value;
|
|
3610
3694
|
});
|
|
3611
3695
|
const YOUTUBE_OEMBED_API = "https://www.youtube.com/oembed?format=json&url=";
|
|
3612
3696
|
const defaultResolveYouTubeVideo = cached(async (url) => {
|
|
@@ -3897,14 +3981,14 @@ var ImageMarkView = class {
|
|
|
3897
3981
|
const saved = this.#attrs.snapshot == null ? void 0 : parsePostEmbedSnapshot(this.#attrs.snapshot);
|
|
3898
3982
|
if (kind === "x-post") {
|
|
3899
3983
|
registerXPost();
|
|
3900
|
-
const element = document.createElement("
|
|
3984
|
+
const element = document.createElement("meowdown-embed-x");
|
|
3901
3985
|
element.mediaUrlProtocols = this.#mediaUrlProtocols ?? null;
|
|
3902
3986
|
element.resolver = this.#resolveXPost;
|
|
3903
3987
|
element.url = src;
|
|
3904
3988
|
return element;
|
|
3905
3989
|
}
|
|
3906
3990
|
registerYouTubeVideo();
|
|
3907
|
-
const element = document.createElement("
|
|
3991
|
+
const element = document.createElement("meowdown-embed-youtube");
|
|
3908
3992
|
element.playback = "inline";
|
|
3909
3993
|
element.data = saved?.kind === "youtube-video" ? saved.data : null;
|
|
3910
3994
|
element.resolver = this.#persisting(kind, this.#resolveYouTubeVideo);
|
|
@@ -7288,7 +7372,7 @@ function insertSoftBreak() {
|
|
|
7288
7372
|
return softBreakCommand;
|
|
7289
7373
|
}
|
|
7290
7374
|
function defineSoftBreak() {
|
|
7291
|
-
return union(defineCommands({ insertSoftBreak }), defineKeymap({ "Shift-Enter": softBreakCommand }));
|
|
7375
|
+
return union(defineCommands({ insertSoftBreak }), defineKeymap({ "Shift-Enter": chainCommands(exitCodeBlockAtEnd, softBreakCommand) }));
|
|
7292
7376
|
}
|
|
7293
7377
|
|
|
7294
7378
|
//#endregion
|
|
@@ -7532,10 +7616,29 @@ function defineWikilink() {
|
|
|
7532
7616
|
});
|
|
7533
7617
|
}
|
|
7534
7618
|
|
|
7619
|
+
//#endregion
|
|
7620
|
+
//#region src/extensions/x-post-media-click.ts
|
|
7621
|
+
const xPostMediaClickKey = new PluginKey("meowdown-x-post-media-click");
|
|
7622
|
+
/**
|
|
7623
|
+
* Call `onClick` when the user activates a photo or video inside an X post
|
|
7624
|
+
* card.
|
|
7625
|
+
*/
|
|
7626
|
+
function defineXPostMediaClickHandler(getOnClick) {
|
|
7627
|
+
return definePlugin(new Plugin({
|
|
7628
|
+
key: xPostMediaClickKey,
|
|
7629
|
+
props: { handleDOMEvents: { [X_POST_MEDIA_CLICK]: (view, event) => {
|
|
7630
|
+
const handler = getOnClick?.(view.state);
|
|
7631
|
+
if (!handler) return false;
|
|
7632
|
+
handler(event);
|
|
7633
|
+
return event.defaultPrevented;
|
|
7634
|
+
} } }
|
|
7635
|
+
}));
|
|
7636
|
+
}
|
|
7637
|
+
|
|
7535
7638
|
//#endregion
|
|
7536
7639
|
//#region src/extensions/extension.ts
|
|
7537
7640
|
function defineEditorExtensionImpl(options) {
|
|
7538
|
-
return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock$1(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineEditorConfig(options), defineImage(getEditorConfig), defineFileView(getEditorConfig), defineModClickPrevention(), defineFileClickHandler((state) => getEditorConfig(state).onFileClick), defineImageClickHandler((state) => getEditorConfig(state).onImageClick), defineWikilinkClickHandler((state) => getEditorConfig(state).onWikilinkClick), defineTagClickHandler((state) => getEditorConfig(state).onTagClick), defineLinkClickHandler((state) => getEditorConfig(state).onLinkClick), defineFollowLinkHandler(getEditorConfig), defineExitBoundaryHandler((state) => getEditorConfig(state).onExitBoundary), defineFilePaste(getEditorConfig), defineEmbedPaste((state) => !!getEditorConfig(state).embedPaste), defineLinkPaste((state) => !!getEditorConfig(state).linkPaste), defineBulletAfterHeading((state) => !!getEditorConfig(state).bulletAfterHeading), defineSubstitution((state) => !!getEditorConfig(state).substitution), defineWikilinkTrigger((state) => !!getEditorConfig(state).wikilinkEnabled), definePlaceholder$1({
|
|
7641
|
+
return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock$1(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineEditorConfig(options), defineImage(getEditorConfig), defineFileView(getEditorConfig), defineModClickPrevention(), defineFileClickHandler((state) => getEditorConfig(state).onFileClick), defineImageClickHandler((state) => getEditorConfig(state).onImageClick), defineXPostMediaClickHandler((state) => getEditorConfig(state).onXPostMediaClick), defineWikilinkClickHandler((state) => getEditorConfig(state).onWikilinkClick), defineTagClickHandler((state) => getEditorConfig(state).onTagClick), defineLinkClickHandler((state) => getEditorConfig(state).onLinkClick), defineFollowLinkHandler(getEditorConfig), defineExitBoundaryHandler((state) => getEditorConfig(state).onExitBoundary), defineFilePaste(getEditorConfig), defineEmbedPaste((state) => !!getEditorConfig(state).embedPaste), defineLinkPaste((state) => !!getEditorConfig(state).linkPaste), defineBulletAfterHeading((state) => !!getEditorConfig(state).bulletAfterHeading), defineSubstitution((state) => !!getEditorConfig(state).substitution), defineWikilinkTrigger((state) => !!getEditorConfig(state).wikilinkEnabled), definePlaceholder$1({
|
|
7539
7642
|
placeholder: (state) => {
|
|
7540
7643
|
const placeholder = getEditorConfig(state).placeholder;
|
|
7541
7644
|
return typeof placeholder === "function" ? placeholder(state) : placeholder ?? "";
|
|
@@ -7547,7 +7650,7 @@ function defineEditorExtensionImpl(options) {
|
|
|
7547
7650
|
if (editorClassName) attributes.class += ` ${editorClassName}`;
|
|
7548
7651
|
if (spellCheck != null) attributes.spellcheck = String(spellCheck);
|
|
7549
7652
|
return attributes;
|
|
7550
|
-
}), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineEscapeCollapse(), defineSoftBreak(), defineMoveBlock(), defineSelectDocBoundary(), defineInlineMarkPlugin(getEditorConfig), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(getMarkMode), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineSystemSubstitutionGuard(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
|
|
7653
|
+
}), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineClickBelow(), defineEscapeCollapse(), defineSoftBreak(), defineMoveBlock(), defineSelectDocBoundary(), defineInlineMarkPlugin(getEditorConfig), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(getMarkMode), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineSystemSubstitutionGuard(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
|
|
7551
7654
|
name,
|
|
7552
7655
|
modes: [
|
|
7553
7656
|
"hide",
|
|
@@ -8340,7 +8443,7 @@ const EDITOR_KEY_BINDINGS = {
|
|
|
8340
8443
|
"Mod-5": "Heading 5",
|
|
8341
8444
|
"Mod-6": "Heading 6",
|
|
8342
8445
|
"Mod-.": "Fold or unfold a bullet",
|
|
8343
|
-
"Shift-Enter": "Insert a line break",
|
|
8446
|
+
"Shift-Enter": "Insert a line break, or leave a code block from its end",
|
|
8344
8447
|
"Mod-Enter": "Follow the link under the caret, or cycle a checkbox task",
|
|
8345
8448
|
"Mod-Shift-Enter": "Cycle a circle checkbox task",
|
|
8346
8449
|
"Mod-Shift-7": "Ordered list",
|
|
@@ -8920,4 +9023,4 @@ function getVirtualElementFromRange(view, range) {
|
|
|
8920
9023
|
}
|
|
8921
9024
|
|
|
8922
9025
|
//#endregion
|
|
8923
|
-
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getEditorConfig, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, parsePostEmbedSnapshot, parseWikiEmbed, removeLink, renderMathInto, updateEditorConfig, updateLink, wikiEmbedBasename, withPriority };
|
|
9026
|
+
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, defineXPostMediaClickHandler, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getEditorConfig, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, parsePostEmbedSnapshot, parseWikiEmbed, removeLink, renderMathInto, updateEditorConfig, updateLink, wikiEmbedBasename, withPriority };
|
package/dist/style.css
CHANGED
|
@@ -148,63 +148,74 @@
|
|
|
148
148
|
display: none;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
@property --
|
|
151
|
+
@property --meowdown-embed-color {
|
|
152
152
|
syntax: "*";
|
|
153
153
|
inherits: true
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
@property --
|
|
156
|
+
@property --meowdown-embed-background {
|
|
157
157
|
syntax: "*";
|
|
158
158
|
inherits: true
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
@property --
|
|
161
|
+
@property --meowdown-embed-border-color {
|
|
162
162
|
syntax: "*";
|
|
163
163
|
inherits: true
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
@property --
|
|
166
|
+
@property --meowdown-embed-radius {
|
|
167
167
|
syntax: "*";
|
|
168
168
|
inherits: true
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
@property --
|
|
171
|
+
@property --meowdown-embed-padding {
|
|
172
172
|
syntax: "*";
|
|
173
173
|
inherits: true
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
@property --
|
|
176
|
+
@property --meowdown-embed-muted-color {
|
|
177
177
|
syntax: "*";
|
|
178
178
|
inherits: true
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
@property --
|
|
181
|
+
@property --meowdown-embed-link-color {
|
|
182
182
|
syntax: "*";
|
|
183
183
|
inherits: true
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
[data-
|
|
186
|
+
[data-meowdown-embed="x"] [data-root], [data-meowdown-embed="x"] [data-root] *, [data-meowdown-embed="x"] [data-root] :before, [data-meowdown-embed="x"] [data-root] :after {
|
|
187
187
|
all: revert;
|
|
188
188
|
box-sizing: border-box;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
[data-
|
|
192
|
-
--_hairline: var(--
|
|
193
|
-
--_muted: var(--
|
|
194
|
-
--_link: var(--
|
|
191
|
+
[data-meowdown-embed="x"] {
|
|
192
|
+
--_hairline: var(--meowdown-embed-border-color, color-mix(in srgb, currentColor 14%, transparent));
|
|
193
|
+
--_muted: var(--meowdown-embed-muted-color, color-mix(in srgb, currentColor 55%, transparent));
|
|
194
|
+
--_link: var(--meowdown-embed-link-color, #1d9bf0);
|
|
195
195
|
--_tint: color-mix(in srgb, currentColor 5%, transparent);
|
|
196
|
+
--_media-height: 7.5rem;
|
|
197
|
+
width: fit-content;
|
|
198
|
+
max-width: min(28rem, 100%);
|
|
196
199
|
font: inherit;
|
|
197
|
-
color: var(--
|
|
200
|
+
color: var(--meowdown-embed-color, inherit);
|
|
198
201
|
text-decoration-skip-ink: none;
|
|
199
202
|
display: block;
|
|
200
203
|
}
|
|
201
204
|
|
|
202
|
-
[data-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
+
[data-meowdown-embed="x"] [data-root]:before {
|
|
206
|
+
content: "";
|
|
207
|
+
width: calc(18rem - 2 * var(--meowdown-embed-padding, 1rem) - 2px);
|
|
208
|
+
max-width: 100%;
|
|
209
|
+
height: 0;
|
|
210
|
+
display: block;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
[data-meowdown-embed="x"] [data-root] {
|
|
214
|
+
color: var(--meowdown-embed-color, inherit);
|
|
215
|
+
background: var(--meowdown-embed-background, transparent);
|
|
205
216
|
border: 1px solid var(--_hairline);
|
|
206
|
-
border-radius: var(--
|
|
207
|
-
padding: var(--
|
|
217
|
+
border-radius: var(--meowdown-embed-radius, .75rem);
|
|
218
|
+
padding: var(--meowdown-embed-padding, 1rem);
|
|
208
219
|
letter-spacing: normal;
|
|
209
220
|
text-align: start;
|
|
210
221
|
text-transform: none;
|
|
@@ -266,7 +277,7 @@
|
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
& [data-avatar][data-shape="square"] {
|
|
269
|
-
border-radius: .
|
|
280
|
+
border-radius: .375rem;
|
|
270
281
|
}
|
|
271
282
|
|
|
272
283
|
& [data-avatar][data-shape="hexagon"] {
|
|
@@ -290,31 +301,53 @@
|
|
|
290
301
|
|
|
291
302
|
& [data-author-details] > bdi {
|
|
292
303
|
color: var(--_muted);
|
|
304
|
+
font-size: .9375em;
|
|
293
305
|
}
|
|
294
306
|
|
|
295
307
|
& [data-author-details] > bdi > a {
|
|
296
308
|
color: inherit;
|
|
297
309
|
}
|
|
298
310
|
|
|
311
|
+
& [data-date] {
|
|
312
|
+
white-space: nowrap;
|
|
313
|
+
color: var(--_muted);
|
|
314
|
+
flex: none;
|
|
315
|
+
align-self: flex-start;
|
|
316
|
+
padding-inline-start: .25rem;
|
|
317
|
+
font-size: .8125em;
|
|
318
|
+
line-height: 1.3rem;
|
|
319
|
+
display: block;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
& [data-date] > a {
|
|
323
|
+
color: inherit;
|
|
324
|
+
}
|
|
325
|
+
|
|
299
326
|
& [data-reply-to] {
|
|
300
327
|
color: var(--_muted);
|
|
301
328
|
margin-block-start: .625rem;
|
|
302
|
-
font-size: .
|
|
329
|
+
font-size: .875em;
|
|
303
330
|
display: block;
|
|
304
331
|
}
|
|
305
332
|
|
|
306
333
|
& [data-body] {
|
|
307
|
-
margin-block: .
|
|
334
|
+
margin-block: .75rem 0;
|
|
308
335
|
font-size: 1em;
|
|
309
336
|
line-height: 1.5;
|
|
310
337
|
display: block;
|
|
311
338
|
}
|
|
312
339
|
|
|
340
|
+
& [data-reply-to] + [data-body] {
|
|
341
|
+
margin-block-start: .375rem;
|
|
342
|
+
}
|
|
343
|
+
|
|
313
344
|
& [data-text] {
|
|
314
345
|
white-space: pre-wrap;
|
|
315
346
|
}
|
|
316
347
|
|
|
317
348
|
& [data-media] {
|
|
349
|
+
height: var(--_media-height);
|
|
350
|
+
max-width: calc(2 * var(--_media-height));
|
|
318
351
|
background: var(--_hairline);
|
|
319
352
|
border-radius: .5rem;
|
|
320
353
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
@@ -324,48 +357,113 @@
|
|
|
324
357
|
overflow: hidden;
|
|
325
358
|
}
|
|
326
359
|
|
|
327
|
-
& [data-media][data-count="1"] {
|
|
328
|
-
grid-template-columns: minmax(0, 1fr);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
360
|
& [data-media-item] {
|
|
332
361
|
min-width: 0;
|
|
333
362
|
display: block;
|
|
363
|
+
position: relative;
|
|
334
364
|
overflow: hidden;
|
|
335
365
|
}
|
|
336
366
|
|
|
367
|
+
& [data-media-item]:after {
|
|
368
|
+
content: "";
|
|
369
|
+
border-radius: inherit;
|
|
370
|
+
box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 10%, transparent);
|
|
371
|
+
pointer-events: none;
|
|
372
|
+
position: absolute;
|
|
373
|
+
inset: 0;
|
|
374
|
+
}
|
|
375
|
+
|
|
337
376
|
& [data-media-item] > a {
|
|
338
377
|
height: 100%;
|
|
339
378
|
display: block;
|
|
340
379
|
}
|
|
341
380
|
|
|
342
|
-
& [data-media-item]
|
|
343
|
-
object-fit: contain;
|
|
381
|
+
& [data-media-item] > [data-poster] {
|
|
344
382
|
background: var(--_tint);
|
|
345
383
|
width: 100%;
|
|
346
|
-
height:
|
|
347
|
-
|
|
348
|
-
|
|
384
|
+
height: 100%;
|
|
385
|
+
font: inherit;
|
|
386
|
+
color: inherit;
|
|
387
|
+
cursor: pointer;
|
|
388
|
+
border: 0;
|
|
389
|
+
padding: 0;
|
|
390
|
+
position: relative;
|
|
349
391
|
}
|
|
350
392
|
|
|
351
|
-
& [data-
|
|
352
|
-
|
|
393
|
+
& [data-play] {
|
|
394
|
+
background: #0009;
|
|
395
|
+
border-radius: 50%;
|
|
396
|
+
width: 2.25rem;
|
|
397
|
+
height: 2.25rem;
|
|
398
|
+
position: absolute;
|
|
399
|
+
inset: 50% auto auto 50%;
|
|
400
|
+
translate: -50% -50%;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
& [data-play]:after {
|
|
404
|
+
content: "";
|
|
405
|
+
border-block: .375rem solid #0000;
|
|
406
|
+
border-inline-start: .6rem solid #fff;
|
|
407
|
+
position: absolute;
|
|
408
|
+
inset: 50% auto auto 54%;
|
|
409
|
+
translate: -50% -50%;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
& [data-media-item] img, & [data-media-item] video {
|
|
353
413
|
object-fit: cover;
|
|
414
|
+
background: var(--_tint);
|
|
415
|
+
width: 100%;
|
|
354
416
|
height: 100%;
|
|
417
|
+
display: block;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
& [data-media-item][data-orientation="portrait"] :is(img, video) {
|
|
421
|
+
object-position: center 30%;
|
|
355
422
|
}
|
|
356
423
|
|
|
357
424
|
& [data-media][data-count="3"] [data-media-item]:first-child {
|
|
358
425
|
grid-row: span 2;
|
|
359
426
|
}
|
|
360
427
|
|
|
428
|
+
& [data-media]:is([data-count="1"], :has(video)) {
|
|
429
|
+
background: none;
|
|
430
|
+
border-radius: 0;
|
|
431
|
+
max-width: none;
|
|
432
|
+
height: auto;
|
|
433
|
+
display: block;
|
|
434
|
+
overflow: visible;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
& [data-media]:is([data-count="1"], :has(video)) > [data-media-item] {
|
|
438
|
+
width: calc(var(--_media-height) * (var(--_ratio, 16 / 9)));
|
|
439
|
+
max-width: 100%;
|
|
440
|
+
aspect-ratio: var(--_ratio, 16 / 9);
|
|
441
|
+
border-radius: .5rem;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
& [data-media]:has(video) > [data-media-item] + [data-media-item] {
|
|
445
|
+
margin-block-start: .375rem;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
& [data-media-item]:has( > video) {
|
|
449
|
+
--_media-height: 20rem;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
& [data-media-item]:has( > [data-media-error]:not([hidden])) {
|
|
453
|
+
aspect-ratio: auto;
|
|
454
|
+
width: auto;
|
|
455
|
+
}
|
|
456
|
+
|
|
361
457
|
& [data-media-unavailable], & [data-media-error] {
|
|
362
458
|
color: var(--_muted);
|
|
363
459
|
background: var(--_tint);
|
|
460
|
+
border-radius: .5rem;
|
|
364
461
|
padding: .75rem 1rem;
|
|
365
462
|
display: block;
|
|
366
463
|
}
|
|
367
464
|
|
|
368
465
|
& [data-quoted] {
|
|
466
|
+
--_media-height: 5rem;
|
|
369
467
|
border: 1px solid var(--_hairline);
|
|
370
468
|
border-radius: .5rem;
|
|
371
469
|
margin-block-start: .75rem;
|
|
@@ -373,59 +471,119 @@
|
|
|
373
471
|
display: block;
|
|
374
472
|
}
|
|
375
473
|
|
|
376
|
-
& [data-quoted] [data-author] {
|
|
377
|
-
gap: .5rem;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
474
|
& [data-quoted] [data-avatar] {
|
|
381
475
|
width: 1.375rem;
|
|
382
476
|
height: 1.375rem;
|
|
383
477
|
}
|
|
384
478
|
|
|
385
479
|
& [data-quoted] [data-author-details] {
|
|
386
|
-
flex-wrap: wrap;
|
|
387
480
|
align-items: baseline;
|
|
388
481
|
gap: 0 .35rem;
|
|
482
|
+
line-height: 1.375rem;
|
|
389
483
|
display: flex;
|
|
390
484
|
}
|
|
391
485
|
|
|
486
|
+
& [data-quoted] [data-author-name], & [data-quoted] [data-author-details] > bdi {
|
|
487
|
+
white-space: nowrap;
|
|
488
|
+
text-overflow: ellipsis;
|
|
489
|
+
min-width: 0;
|
|
490
|
+
display: block;
|
|
491
|
+
overflow: hidden;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
& [data-quoted] [data-author-name] {
|
|
495
|
+
flex: 0 auto;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
& [data-quoted] [data-author-details] > bdi {
|
|
499
|
+
flex: 0 100 auto;
|
|
500
|
+
min-width: 2.5rem;
|
|
501
|
+
font-size: .9375em;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
& [data-quoted] [data-date] {
|
|
505
|
+
align-self: center;
|
|
506
|
+
}
|
|
507
|
+
|
|
392
508
|
& [data-quoted] [data-body] {
|
|
393
|
-
|
|
509
|
+
-webkit-line-clamp: 3;
|
|
510
|
+
line-clamp: 3;
|
|
511
|
+
-webkit-box-orient: vertical;
|
|
512
|
+
margin-block-start: .25rem;
|
|
394
513
|
font-size: .9375em;
|
|
514
|
+
display: -webkit-box;
|
|
515
|
+
overflow: hidden;
|
|
395
516
|
}
|
|
396
517
|
|
|
397
518
|
& [data-quoted] [data-media] {
|
|
398
519
|
border-radius: .375rem;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
& [data-quoted] [data-footer] {
|
|
402
520
|
margin-block-start: .5rem;
|
|
403
|
-
font-size: .8125em;
|
|
404
521
|
}
|
|
405
522
|
|
|
406
|
-
& [data-
|
|
407
|
-
|
|
408
|
-
flex-wrap: wrap;
|
|
409
|
-
align-items: center;
|
|
410
|
-
gap: .25rem 0;
|
|
411
|
-
margin-block-start: .625rem;
|
|
412
|
-
font-size: .875em;
|
|
413
|
-
display: flex;
|
|
523
|
+
& [data-quoted] [data-play] {
|
|
524
|
+
scale: .75;
|
|
414
525
|
}
|
|
415
526
|
|
|
416
|
-
& [data-
|
|
417
|
-
|
|
527
|
+
& [data-quoted]:has( > [data-media]):not(:has( > [data-media] [data-poster], > [data-media] video)) {
|
|
528
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
529
|
+
grid-template-areas: "head head"
|
|
530
|
+
"body media"
|
|
531
|
+
"foot foot";
|
|
532
|
+
column-gap: .75rem;
|
|
533
|
+
display: grid;
|
|
534
|
+
|
|
535
|
+
& > [data-author] {
|
|
536
|
+
grid-area: head;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
& > [data-body] {
|
|
540
|
+
grid-area: body;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
& > [data-footer] {
|
|
544
|
+
grid-area: foot;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
& > [data-media] {
|
|
548
|
+
grid-area: media;
|
|
549
|
+
width: 4rem;
|
|
550
|
+
height: 4rem;
|
|
551
|
+
margin-block-start: .375rem;
|
|
552
|
+
display: block;
|
|
553
|
+
position: relative;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
& > [data-media] > [data-media-item] {
|
|
557
|
+
width: 100%;
|
|
558
|
+
height: 100%;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
& > [data-media] > [data-media-item]:nth-child(n+2) {
|
|
562
|
+
display: none;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
& > [data-media]:not([data-count="1"]):after {
|
|
566
|
+
content: attr(data-count);
|
|
567
|
+
text-align: center;
|
|
568
|
+
color: #fff;
|
|
569
|
+
pointer-events: none;
|
|
570
|
+
background: #0000009e;
|
|
571
|
+
border-radius: .625rem;
|
|
572
|
+
min-width: 1.25rem;
|
|
573
|
+
padding: 0 .3125rem;
|
|
574
|
+
font-size: .6875rem;
|
|
575
|
+
font-weight: 600;
|
|
576
|
+
line-height: 1.25rem;
|
|
577
|
+
position: absolute;
|
|
578
|
+
inset: auto .25rem .25rem auto;
|
|
579
|
+
}
|
|
418
580
|
}
|
|
419
581
|
|
|
420
|
-
& [data-footer]
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
width: 3px;
|
|
426
|
-
height: 3px;
|
|
427
|
-
margin-inline: .45rem;
|
|
428
|
-
display: inline-block;
|
|
582
|
+
& [data-footer] {
|
|
583
|
+
color: var(--_muted);
|
|
584
|
+
margin-block-start: .5rem;
|
|
585
|
+
font-size: .8125em;
|
|
586
|
+
display: block;
|
|
429
587
|
}
|
|
430
588
|
|
|
431
589
|
& [data-edited] {
|
|
@@ -437,16 +595,16 @@
|
|
|
437
595
|
}
|
|
438
596
|
}
|
|
439
597
|
|
|
440
|
-
@layer
|
|
441
|
-
:where([data-
|
|
442
|
-
--_hairline: var(--
|
|
443
|
-
--_muted: var(--
|
|
444
|
-
--_link: var(--
|
|
445
|
-
--_radius: var(--
|
|
446
|
-
--_page: var(--
|
|
598
|
+
@layer meowdown-embed {
|
|
599
|
+
:where([data-meowdown-embed="youtube"]) {
|
|
600
|
+
--_hairline: var(--meowdown-embed-border-color, color-mix(in srgb, currentColor 15%, transparent));
|
|
601
|
+
--_muted: var(--meowdown-embed-muted-color, color-mix(in srgb, currentColor 58%, transparent));
|
|
602
|
+
--_link: var(--meowdown-embed-link-color, #1d9bf0);
|
|
603
|
+
--_radius: var(--meowdown-embed-radius, 1rem);
|
|
604
|
+
--_page: var(--meowdown-embed-background, Canvas);
|
|
447
605
|
--_play: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 68 48'%3E%3Cpath d='M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55C3.97 2.33 2.27 4.81 1.48 7.74.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24S67.94 13.05 66.52 7.74z' fill='%23f00'/%3E%3Cpath d='M45 24 27 14v20z' fill='%23fff'/%3E%3C/svg%3E");
|
|
448
606
|
font: inherit;
|
|
449
|
-
color: var(--
|
|
607
|
+
color: var(--meowdown-embed-color, inherit);
|
|
450
608
|
display: block;
|
|
451
609
|
|
|
452
610
|
& :where([data-root]) {
|
|
@@ -551,7 +709,7 @@
|
|
|
551
709
|
& :where([data-fallback]) {
|
|
552
710
|
border: 1px solid var(--_hairline);
|
|
553
711
|
border-radius: var(--_radius);
|
|
554
|
-
padding: var(--
|
|
712
|
+
padding: var(--meowdown-embed-padding, 1rem);
|
|
555
713
|
}
|
|
556
714
|
|
|
557
715
|
& :where([data-fallback] [data-details]) {
|
|
@@ -1075,9 +1233,12 @@
|
|
|
1075
1233
|
padding: 2px 6px;
|
|
1076
1234
|
}
|
|
1077
1235
|
|
|
1078
|
-
.ProseMirror .md-image-view-preview
|
|
1236
|
+
.ProseMirror .md-image-view-preview meowdown-embed-x, .ProseMirror .md-image-view-preview meowdown-embed-youtube {
|
|
1079
1237
|
-webkit-user-select: text;
|
|
1080
1238
|
user-select: text;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
.ProseMirror .md-image-view-preview meowdown-embed-youtube {
|
|
1081
1242
|
max-width: 550px;
|
|
1082
1243
|
display: block;
|
|
1083
1244
|
}
|
|
@@ -1095,7 +1256,7 @@
|
|
|
1095
1256
|
height: auto !important;
|
|
1096
1257
|
}
|
|
1097
1258
|
|
|
1098
|
-
.ProseMirror .md-embed-resizable
|
|
1259
|
+
.ProseMirror .md-embed-resizable meowdown-embed-youtube {
|
|
1099
1260
|
width: 100%;
|
|
1100
1261
|
max-width: none;
|
|
1101
1262
|
}
|
|
@@ -1246,7 +1407,7 @@
|
|
|
1246
1407
|
}
|
|
1247
1408
|
|
|
1248
1409
|
& .md-image-view-preview[data-post-embed] {
|
|
1249
|
-
border-radius: var(--
|
|
1410
|
+
border-radius: var(--meowdown-embed-radius, .75rem);
|
|
1250
1411
|
overflow: visible;
|
|
1251
1412
|
}
|
|
1252
1413
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.73.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,15 +25,16 @@
|
|
|
25
25
|
"@codemirror/language-data": "^6.5.2",
|
|
26
26
|
"@floating-ui/dom": "^1.8.0",
|
|
27
27
|
"@lezer/highlight": "^1.2.3",
|
|
28
|
+
"@meowdown/embed": "^0.1.0",
|
|
29
|
+
"@meowdown/markdown": "^0.72.0",
|
|
28
30
|
"@ocavue/utils": "^1.8.0",
|
|
29
|
-
"@post-embed/
|
|
30
|
-
"@post-embed/
|
|
31
|
-
"@post-embed/
|
|
32
|
-
"@
|
|
33
|
-
"@prosekit/
|
|
34
|
-
"@prosekit/
|
|
35
|
-
"@prosekit/
|
|
36
|
-
"@prosekit/web": "^0.9.2",
|
|
31
|
+
"@post-embed/exporter": "^0.5.0",
|
|
32
|
+
"@post-embed/schema": "^0.5.2",
|
|
33
|
+
"@post-embed/types": "^0.5.0",
|
|
34
|
+
"@prosekit/core": "^0.13.3",
|
|
35
|
+
"@prosekit/extensions": "^0.18.3",
|
|
36
|
+
"@prosekit/pm": "^0.1.20",
|
|
37
|
+
"@prosekit/web": "^0.9.3",
|
|
37
38
|
"hast-util-to-mdast": "^10.1.2",
|
|
38
39
|
"katex": "^0.18.7",
|
|
39
40
|
"lru.min": "^1.1.5",
|
|
@@ -48,10 +49,10 @@
|
|
|
48
49
|
"remark-stringify": "^11.0.0",
|
|
49
50
|
"unicode-by-name": "^0.2.0",
|
|
50
51
|
"unified": "^11.0.5",
|
|
51
|
-
"valibot": "^1.5.0"
|
|
52
|
-
"@meowdown/markdown": "^0.72.0"
|
|
52
|
+
"valibot": "^1.5.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
+
"@meowdown/vitest": "0.0.0",
|
|
55
56
|
"@ocavue/tsconfig": "^0.7.1",
|
|
56
57
|
"@tsdown/css": "^0.23.0",
|
|
57
58
|
"@types/hast": "^3.0.5",
|
|
@@ -61,9 +62,7 @@
|
|
|
61
62
|
"dedent": "^1.7.2",
|
|
62
63
|
"diffable-html-snapshot": "^0.3.0",
|
|
63
64
|
"tsdown": "^0.23.0",
|
|
64
|
-
"vitest": "^5.0.1"
|
|
65
|
-
"vitest-browser-commands": "^0.4.1",
|
|
66
|
-
"@meowdown/vitest": "0.0.0"
|
|
65
|
+
"vitest": "^5.0.1"
|
|
67
66
|
},
|
|
68
67
|
"publishConfig": {
|
|
69
68
|
"access": "public"
|