Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@
}
},
"peerDependencies": {
"@diplodoc/cut-extension": "^0.5.0 || ^0.6.1 || ^0.7.1",
"@diplodoc/cut-extension": "^0.5.0 || ^0.6.1 || ^0.7.1 || ^1.0.0",
"@diplodoc/file-extension": "^0.2.1",
"@diplodoc/folding-headings-extension": "^0.1.0",
"@diplodoc/html-extension": "^2.3.2",
Expand Down
8 changes: 7 additions & 1 deletion src/extensions/yfm/YfmCut/YfmCutSpecs/const.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {nodeTypeFactory} from '../../../../utils/schema';
import {nodeTypeFactory} from 'src/utils/schema';

export enum CutNode {
Cut = 'yfm_cut',
Expand All @@ -14,3 +14,9 @@ export enum CutAttr {
export const cutType = nodeTypeFactory(CutNode.Cut);
export const cutTitleType = nodeTypeFactory(CutNode.CutTitle);
export const cutContentType = nodeTypeFactory(CutNode.CutContent);

export const YfmCutClassName = {
Cut: 'yfm-cut',
Title: 'yfm-cut-title',
Content: 'yfm-cut-content',
} as const;
4 changes: 2 additions & 2 deletions src/extensions/yfm/YfmCut/YfmCutSpecs/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {transform as yfmCut} from '@diplodoc/cut-extension';

import type {ExtensionAuto, ExtensionNodeSpec} from '../../../../core';
import type {ExtensionAuto, ExtensionNodeSpec} from '#core';

import {CutNode} from './const';
import {parserTokens} from './parser';
import {type YfmCutSchemaOptions, getSchemaSpecs} from './schema';
import {getSerializerTokens} from './serializer';

export {CutAttr, CutNode, cutType, cutTitleType, cutContentType} from './const';
export {CutAttr, CutNode, cutType, cutTitleType, cutContentType, YfmCutClassName} from './const';

declare global {
namespace MarkdownEditor {
Expand Down
19 changes: 9 additions & 10 deletions src/extensions/yfm/YfmCut/YfmCutSpecs/schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type {NodeSpec} from 'prosemirror-model';
import type {NodeSpec} from '#pm/model';
import type {PlaceholderOptions} from 'src/utils/placeholder';

import type {PlaceholderOptions} from '../../../../utils/placeholder';

import {CutAttr, CutNode} from './const';
import {CutAttr, CutNode, YfmCutClassName} from './const';

export type YfmCutSchemaOptions = {
/**
Expand All @@ -25,12 +24,12 @@ export const getSchemaSpecs = (
placeholder?: PlaceholderOptions,
): Record<CutNode, NodeSpec> => ({
[CutNode.Cut]: {
attrs: {class: {default: 'yfm-cut'}, [CutAttr.Markup]: {default: null}},
attrs: {class: {default: YfmCutClassName.Cut}, [CutAttr.Markup]: {default: null}},
content: `${CutNode.CutTitle} ${CutNode.CutContent}`,
group: 'block yfm-cut',
parseDOM: [
{
tag: '.yfm-cut',
tag: `.${YfmCutClassName.Cut}`,
getAttrs: (node) => ({[CutAttr.Markup]: node.getAttribute(CutAttr.Markup)}),
},
],
Expand All @@ -44,10 +43,10 @@ export const getSchemaSpecs = (
},

[CutNode.CutTitle]: {
attrs: {class: {default: 'yfm-cut-title'}},
attrs: {class: {default: YfmCutClassName.Title}},
content: 'inline*',
group: 'block yfm-cut',
parseDOM: [{tag: '.yfm-cut-title'}],
parseDOM: [{tag: `.${YfmCutClassName.Title}`}],
toDOM(node) {
return ['div', node.attrs, 0];
},
Expand All @@ -65,10 +64,10 @@ export const getSchemaSpecs = (
},

[CutNode.CutContent]: {
attrs: {class: {default: 'yfm-cut-content'}},
attrs: {class: {default: YfmCutClassName.Content}},
content: '(block | paragraph)+',
group: 'block yfm-cut',
parseDOM: [{tag: '.yfm-cut-content'}],
parseDOM: [{tag: `.${YfmCutClassName.Content}`}],
toDOM(node) {
return ['div', node.attrs, 0];
},
Expand Down
14 changes: 7 additions & 7 deletions src/extensions/yfm/YfmCut/actions/toYfmCut.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type {Fragment, Node, Schema} from 'prosemirror-model';
import {type Command, TextSelection} from 'prosemirror-state';
// @ts-ignore // TODO: fix cjs build
import {findParentNodeClosestToPos} from 'prosemirror-utils';
import type {ActionSpec} from '#core';
import type {Fragment, Node, Schema} from '#pm/model';
import {type Command, TextSelection} from '#pm/state';
import {findParentNodeClosestToPos} from '#pm/utils';

import type {ActionSpec} from '../../../../core';
import {cutContentType, cutTitleType, cutType} from '../const';
import {YfmCutClassName, cutContentType, cutTitleType, cutType} from '../const';

const createYfmCutNode = (schema: Schema) => (content?: Node | Node[] | Fragment) => {
return cutType(schema).create({class: 'yfm-cut open'}, [
const className = `${YfmCutClassName.Cut} ${YfmCutClassName.Open}` as const;
return cutType(schema).create({class: className}, [
cutTitleType(schema).create(null),
cutContentType(schema).create(null, content),
]);
Expand Down
11 changes: 10 additions & 1 deletion src/extensions/yfm/YfmCut/const.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export {CutNode, cutType, cutTitleType, cutContentType} from './YfmCutSpecs';
import {YfmCutClassName as YfmCutClassNameSpecs} from './YfmCutSpecs/const';

export {CutNode, cutType, cutTitleType, cutContentType} from './YfmCutSpecs/const';

export const YfmCutClassName = {
...YfmCutClassNameSpecs,
TitleInner: 'g-md-yfm-cut-title-inner',
Open: 'yfm-cut-open',
Active: 'yfm-cut-active',
} as const;
3 changes: 0 additions & 3 deletions src/extensions/yfm/YfmCut/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,4 @@
outline: 0;
}
}
.yfm-cut.open > .yfm-cut-title:before {
transform: translateY(-50%);
}
}
34 changes: 21 additions & 13 deletions src/extensions/yfm/YfmCut/nodeviews/yfm-cut-title.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
.yfm-cut-title .g-md-yfm-cut-title-inner {
cursor: text;
}
.ProseMirror.yfm {
.yfm-cut-title > .g-md-yfm-cut-title-inner {
cursor: text;
}

// FIXME: Restore the cut-extension mapping after the fix:
// when using <details> and <summary> tags, the click does
// not work correctly on the placeholder
// FIXME: Restore the cut-extension mapping after the fix:
// when using <details> and <summary> tags, the click does
// not work correctly on the placeholder

.yfm-cut-content {
display: none;
overflow: hidden;
.yfm-cut-content {
display: none;
overflow: hidden;

transition: height 0.3s ease-in-out;
}
transition: height 0.3s ease-in-out;
}

.yfm-cut.yfm-cut-open > {
.yfm-cut-title:before {
transform: translateY(-50%);
}

.open > .yfm-cut-content {
display: revert;
.yfm-cut-content {
display: revert;
}
}
}
44 changes: 33 additions & 11 deletions src/extensions/yfm/YfmCut/nodeviews/yfm-cut-title.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type {Node} from 'prosemirror-model';
import type {NodeView} from 'prosemirror-view';
import type {Node} from '#pm/model';
import type {NodeView} from '#pm/view';

import {YfmCutClassName} from '../const';

import './yfm-cut-title.scss';

Expand All @@ -13,20 +15,40 @@ export class YfmCutTitleNodeView implements NodeView {
this.node = node;

this.dom = document.createElement('div');
this.dom.classList.add('yfm-cut-title');
this.dom.replaceChildren((this.contentDOM = document.createElement('div')));
this.contentDOM.classList.add('g-md-yfm-cut-title-inner');
this.contentDOM.addEventListener('click', (e) => {
// ignore clicking on the title content
// you can open/close yfm-cut by clicking on the arrow icon
e.stopPropagation();
e.preventDefault();
});
this.dom.classList.add(YfmCutClassName.Title);
this.dom.addEventListener('click', this._onTitleClick);

this.contentDOM = this.dom.appendChild(document.createElement('div'));
this.contentDOM.classList.add(YfmCutClassName.TitleInner);
this.contentDOM.addEventListener('click', this._onTitleInnerClick);
}

update(node: Node): boolean {
if (this.node.type !== node.type) return false;
this.node = node;
return true;
}

destroy() {
this.dom.removeEventListener('click', this._onTitleClick);
this.contentDOM.removeEventListener('click', this._onTitleInnerClick);
}

private _onTitleClick = (e: MouseEvent) => {
const {currentTarget} = e;
if (currentTarget instanceof HTMLElement) {
const parent = currentTarget.parentElement;
if (parent?.classList.contains(YfmCutClassName.Cut)) {
// TODO: toggle open classname via prosemirror decoration
parent.classList.toggle(YfmCutClassName.Open);
}
}
};

private _onTitleInnerClick = (e: MouseEvent) => {
// ignore clicking on the title content
// you can open/close yfm-cut by clicking on the arrow icon
e.stopPropagation();
e.preventDefault();
};
}
17 changes: 7 additions & 10 deletions src/extensions/yfm/YfmCut/plugins/active.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import type {NodeType, ResolvedPos} from 'prosemirror-model';
import {Plugin} from 'prosemirror-state';
// @ts-ignore // TODO: fix cjs build
import type {NodeWithPos} from 'prosemirror-utils';
import {Decoration, DecorationSet} from 'prosemirror-view';
import type {NodeType, ResolvedPos} from '#pm/model';
import {Plugin} from '#pm/state';
import type {NodeWithPos} from '#pm/utils';
import {Decoration, DecorationSet} from '#pm/view';
import {isNodeSelection, isTextSelection} from 'src/utils/selection';

import {isNodeSelection, isTextSelection} from '../../../../utils/selection';
import {cutType} from '../const';

const YFM_CUT_ACTIVE_CLASSNAME = 'yfm-cut-active';
import {YfmCutClassName, cutType} from '../const';

export const cutActivePlugin = () => {
return new Plugin({
Expand All @@ -20,7 +17,7 @@ export const cutActivePlugin = () => {
const createDeco = ({pos, node}: NodeWithPos) => {
decos.push(
Decoration.node(pos, pos + node.nodeSize, {
class: YFM_CUT_ACTIVE_CLASSNAME,
class: YfmCutClassName.Active,
}),
);
};
Expand Down
22 changes: 11 additions & 11 deletions src/extensions/yfm/YfmCut/plugins/auto-open.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type {ResolvedPos} from 'prosemirror-model';
import {Plugin, PluginKey, type PluginView} from 'prosemirror-state';
// @ts-ignore // TODO: fix cjs build
import {findDomRefAtPos} from 'prosemirror-utils';
import type {EditorView} from 'prosemirror-view';
import type {ResolvedPos} from '#pm/model';
import {Plugin, PluginKey, type PluginView} from '#pm/state';
import {findDomRefAtPos} from '#pm/utils';
import type {EditorView} from '#pm/view';
import {throttle} from 'src/lodash';
import {isTextSelection} from 'src/utils/selection';

import {throttle} from '../../../../lodash';
import {isTextSelection} from '../../../../utils/selection';
import {cutContentType, cutType} from '../const';
import {YfmCutClassName, cutContentType, cutType} from '../const';

const key = new PluginKey('yfm-cut-auto-open');

Expand Down Expand Up @@ -44,7 +43,7 @@ function openParentYfmCuts($pos: ResolvedPos, domAtPos: EditorView['domAtPos']):
if ($pos.node(depth).type === cutContentType(schema)) {
if ($pos.node(depth - 1).type === cutType(schema)) {
const {node: cutDomNode} = domAtPos($pos.start(depth - 1), 0);
(cutDomNode as Element).classList.add('open');
(cutDomNode as Element).classList.add(YfmCutClassName.Open);
depth--;
}
}
Expand All @@ -53,7 +52,8 @@ function openParentYfmCuts($pos: ResolvedPos, domAtPos: EditorView['domAtPos']):
}

class CutAutoOpenOnDragOver implements PluginView {
private static readonly YFM_CUT_SELECTOR = '.yfm-cut:not(.open)';
private static readonly YFM_CUT_SELECTOR =
`.${YfmCutClassName.Cut}:not(.${YfmCutClassName.Open})` as const;
private static readonly OPEN_TIMEOUT = 500; //ms
private static readonly THROTTLE_WAIT = 50; //ms

Expand Down Expand Up @@ -104,7 +104,7 @@ class CutAutoOpenOnDragOver implements PluginView {

private _openCut() {
if (this._editorView.dragging) {
this._cutElem?.classList.add('open');
this._cutElem?.classList.add(YfmCutClassName.Open);
}
this._clear();
}
Expand Down
Loading