Skip to content

Commit

Permalink
feat: working on react package
Browse files Browse the repository at this point in the history
  • Loading branch information
Saul-Mirone committed Jun 14, 2021
1 parent f614070 commit bb3ce6d
Show file tree
Hide file tree
Showing 17 changed files with 344 additions and 21 deletions.
3 changes: 2 additions & 1 deletion gh-pages/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';
import { markdownPlugin } from './markdown-plugin';

export default defineConfig({
Expand All @@ -22,5 +23,5 @@ export default defineConfig({
'prosemirror-gapcursor',
],
},
plugins: [markdownPlugin()],
plugins: [markdownPlugin(), reactRefresh()],
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@commitlint/cli": "^12.1.1",
"@commitlint/config-conventional": "^12.1.1",
"@milkdown/core": "workspace:*",
"@milkdown/react": "workspace:*",
"@milkdown/utils": "workspace:*",
"@milkdown/plugin-math": "workspace:*",
"@milkdown/plugin-prism": "workspace:*",
Expand All @@ -45,6 +46,7 @@
"@types/prosemirror-view": "^1.17.1",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"@vitejs/plugin-react-refresh": "^1.3.3",
"autoprefixer": "^10.2.5",
"eslint": "^7.21.0",
"eslint-config-prettier": "^8.3.0",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './loader';
export * from './parser';
export * from './serializer';
export * from './constant';
export * from './utility';
2 changes: 1 addition & 1 deletion packages/plugin-math/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"tslib": "^2.2.0"
},
"devDependencies": {
"@milkdown/core": "*",
"@milkdown/core": "workspace:*",
"concurrently": "^6.0.2"
}
}
16 changes: 8 additions & 8 deletions packages/plugin-math/src/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import type { InputRule } from 'prosemirror-inputrules';
import type { NodeSpec, NodeType } from 'prosemirror-model';

export class MathInline extends Node {
id = 'math_inline';
schema: NodeSpec = {
override id = 'math_inline';
override schema: NodeSpec = {
group: 'inline math',
content: 'text*',
inline: true,
atom: true,
parseDOM: [{ tag: 'math-inline' }],
toDOM: () => ['math-inline', { class: 'math-node' }, 0],
};
parser = {
override parser = {
block: this.id,
isAtom: true,
};
serializer: SerializerNode = (state, node) => {
override serializer: SerializerNode = (state, node) => {
state.write('$');
state.renderContent(node);
state.write('$');
Expand All @@ -33,20 +33,20 @@ export class MathInline extends Node {
}

export class MathDisplay extends Node {
id = 'math_display';
schema: NodeSpec = {
override id = 'math_display';
override schema: NodeSpec = {
group: 'block math',
content: 'text*',
atom: true,
code: true,
parseDOM: [{ tag: 'math-display' }],
toDOM: () => ['math-display', { class: 'math-node' }, 0],
};
parser = {
override parser = {
block: 'math_block',
isAtom: true,
};
serializer: SerializerNode = (state, node) => {
override serializer: SerializerNode = (state, node) => {
state.write('$$').ensureNewLine().renderContent(node).ensureNewLine().write('$$').closeBlock(node);
};
override inputRules = (nodeType: NodeType): InputRule[] => [
Expand Down
6 changes: 5 additions & 1 deletion packages/preset-commonmark/src/node/paragraph.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { NodeSpec } from 'prosemirror-model';
import { SerializerNode } from '@milkdown/core';
import { SerializerNode, NodeViewFactory } from '@milkdown/core';
import { CommonNode } from '../utility/base';

export class Paragraph extends CommonNode {
Expand All @@ -16,4 +16,8 @@ export class Paragraph extends CommonNode {
override readonly serializer: SerializerNode = (state, node) => {
state.renderInline(node).closeBlock(node);
};
override readonly view: NodeViewFactory = (...args) => {
console.log(args);
return null as any;
};
}
12 changes: 12 additions & 0 deletions packages/react/app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.ts"></script>
</body>
</html>
69 changes: 69 additions & 0 deletions packages/react/app/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Editor } from '@milkdown/core';
import { commonmark } from '@milkdown/preset-commonmark';

import '@milkdown/theme-nord/lib/theme.css';

import './style.css';

const markdown = `
# Milkdown Test
## Blockquote
> Milkdown is an editor.
## Marks Paragraph
Hello, ***milkdown* nice \`to\` meet *you***!
There should be a line break before this.
---
## Image and Link
**Of course you can add image! ![cat](https://th.bing.com/th/id/OIP.EiYMXYhAnpsXnVmwJAq1jAHaEo?pid=ImgDet&rs=1 "kitty")**
Your *[link is here](https://bing.com "bing")*, have a look.
![Alt text][id]
[id]: https://th.bing.com/th/id/OIP.EiYMXYhAnpsXnVmwJAq1jAHaEo?pid=ImgDet&rs=1 "The Cat"
## Lists
* list item 1
1. is this the real life
2. is this just fantasy
* list item 2
* sub list item 1
some explain
* sub list item 2
* list item 3
## Code
\`\`\`javascript
const milkdown = new Milkdown();
milkdown.create();
\`\`\`
---
Now you can play!
`;

const root = document.getElementById('app');

if (!root) throw new Error();

new Editor({
root,
defaultValue: markdown,
listener: {
// markdown: [(x) => console.log(x())],
},
})
.use(commonmark)
.create();
3 changes: 3 additions & 0 deletions packages/react/app/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
margin: 0;
}
32 changes: 32 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@milkdown/react",
"version": "4.1.2",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "vite",
"watch": "tsc -w",
"test": "jest",
"tsc": "tsc --noEmit",
"build": "tsc"
},
"files": [
"lib"
],
"dependencies": {
"tslib": "^2.2.0"
},
"peerDependencies": {
"@milkdown/core": "*",
"react": "*",
"react-dom": "*"
},
"devDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"@milkdown/core": "*",
"react": "*",
"react-dom": "*"
}
}
15 changes: 15 additions & 0 deletions packages/react/src/Portals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';

export type Renderer = {
reactElement: React.ReactNode;
element: HTMLElement;
};

export const Portals: React.FC<{ renderers: Record<string, Renderer> }> = ({ renderers }) => (
<>
{Object.entries(renderers).map(([key, renderer]) =>
ReactDOM.createPortal(renderer.reactElement, renderer.element, key),
)}
</>
);
69 changes: 69 additions & 0 deletions packages/react/src/ReactNodeView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Node as ProsemirrorNode } from 'prosemirror-model';
import { NodeView, Decoration } from 'prosemirror-view';

export function id() {
return [1e7, -1e3, -4e3, -8e3, -1e11]
.map((x) => x.toString())
.join('')
.replace(/[018]/g, (c) =>
(Number(c) ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (Number(c) / 4)))).toString(16),
);
}

abstract class NodeViewBase implements NodeView {
abstract get dom(): Node | null;
abstract get contentDOM(): Node | null;

abstract update?: Required<NodeView>['update'];

abstract destroy?: Required<NodeView>['destroy'];
}

export class ReactNodeView extends NodeViewBase {
override get dom(): Node | null {
throw new Error('To be implemented');
}
override get contentDOM(): Node | null {
if (this.#node.isLeaf) return null;

return this.#contentDOMElement;
}

#node: ProsemirrorNode;
#decorations: Decoration[];
#contentDOMElement: HTMLElement | null;
#getPos: () => number;

constructor(node: ProsemirrorNode, decorations: Decoration[], getPos: () => number) {
super();
this.#node = node;
this.#decorations = decorations;
this.#getPos = getPos;

// TODO: remove HACK
this.#getPos;

this.#contentDOMElement = this.#node.isLeaf
? null
: document.createElement(this.#node.isInline ? 'span' : 'div');
}

override update = (node: ProsemirrorNode, decorations: Decoration[]) => {
if (node.type !== this.#node.type) {
return false;
}

if (node === this.#node && this.#decorations === decorations) {
return true;
}

this.#node = node;
this.#decorations = decorations;

return true;
};

override destroy = () => {
this.#contentDOMElement = null;
};
}
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ReactNodeView';
9 changes: 9 additions & 0 deletions packages/react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "lib",
"jsx": "react"
},
"include": ["src"]
}
21 changes: 21 additions & 0 deletions packages/react/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';

export default defineConfig({
root: 'app',
optimizeDeps: {
include: [
'prosemirror-model',
'prosemirror-view',
'prosemirror-state',
'prosemirror-commands',
'prosemirror-inputrules',
'prosemirror-keymap',
'prosemirror-schema-list',
'prosemirror-history',
'prosemirror-transform',
'prosemirror-gapcursor',
],
},
plugins: [reactRefresh()],
});
Loading

0 comments on commit bb3ce6d

Please sign in to comment.