Skip to content

Commit

Permalink
feat(Script): create a worse, custom Markdown-ish parser
Browse files Browse the repository at this point in the history
It's worse, but it treats all newlines as paragraphs, which is what we want.
  • Loading branch information
jstarpl committed Dec 6, 2023
1 parent 11580d6 commit e337c36
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 593 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
5 changes: 1 addition & 4 deletions packages/apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@
"@sofie-prompter-editor/shared-model": "0.0.0",
"bootstrap": "^5.3.2",
"eventemitter3": "^5.0.1",
"mdast-util-directive": "^3.0.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-to-markdown": "^2.1.0",
"micromark-extension-directive": "^3.0.0",
"mobx": "^6.10.2",
"mobx-react-lite": "^4.0.5",
"prosemirror-commands": "^1.5.2",
Expand All @@ -55,6 +51,7 @@
"react": "^18.2.0",
"react-bootstrap": "^2.9.1",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-helmet-async": "^1.3.0",
"react-router-dom": "^6.18.0",
"socket.io-client": "^4.7.2",
Expand Down
8 changes: 1 addition & 7 deletions packages/apps/client/src/ScriptEditor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ export function Editor({
// }
// }, [])

useEffect(() => {
const test = 'Raz dwa trzy **cztery pięć** sześć. ABC :reverse[Siedem osiem] dziewięć.'
const data = fromMarkdown(test)
console.log(data)
}, [])

useEffect(() => {
if (!containerEl.current) return

Expand All @@ -62,7 +56,7 @@ export function Editor({
[
schema.node(schema.nodes.lineTitle, undefined, [schema.text('Line title')]),
...fromMarkdown(
'Raz _dwa **trzy**_. :reverse[Cztery.]\n\nPięć _sześć_ siedem. \nRaz\n\n\n\n\n Some more :reverse[Markdown **Here**]'
'Raz _dwa **trzy**_. ~Cztery.~\n\nPięć _sześć_ siedem.\nRaz\n\n\n\n\n Some more ~Markdown **Here**~'
),
]
),
Expand Down
144 changes: 144 additions & 0 deletions packages/apps/client/src/lib/markdownishParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { assertType } from 'packages/shared/lib/dist'

interface NodeBase {
type: string
}

interface ParentNodeBase extends NodeBase {
children: Node[]
}

interface RootNode extends ParentNodeBase {
type: 'root'
}

interface ParagraphNode extends ParentNodeBase {
type: 'paragraph'
}

interface TextNode extends NodeBase {
type: 'text'
value: string
}

interface StrongNode extends ParentNodeBase {
type: 'strong'
code: string
}

interface EmphasisNode extends ParentNodeBase {
type: 'emphasis'
code: string
}

interface ReverseNode extends ParentNodeBase {
type: 'reverse'
code: string
}

export type Node = RootNode | ParagraphNode | TextNode | StrongNode | EmphasisNode | ReverseNode

export function astFromMarkdownish(text: string): RootNode {
const document: RootNode = {
type: 'root',
children: [],
}
const stack: ParentNodeBase[] = []
let cursor: ParentNodeBase | null = null
let buffer = ''

let i = 0

function flushBuffer() {
if (buffer === '') return
if (cursor === null) throw new Error('cursor === null assertion')

cursor.children.push({
type: 'text',
value: buffer,
})
buffer = ''
}

function paragraphStart() {
const newParagraph: ParagraphNode = {
type: 'paragraph',
children: [],
}
document.children.push(newParagraph)
cursor = newParagraph
stack.length = 0
stack.push(cursor)
}

function paragraphEnd() {
if (buffer === '') return
if (cursor === null) throw new Error('cursor === null assertion')

flushBuffer()
cursor = null
}

function peek() {
return text[i + 1]
}

function emphasisOrStrong(char: string) {
if (cursor === null) throw new Error('cursor === null assertion')
if ((cursor.type === 'emphasis' || cursor.type === 'strong') && 'code' in cursor) {
if (cursor.code === char) {
if (peek() === char) {
i++
}

flushBuffer()
stack.pop()
cursor = stack[stack.length - 1]
return
}
}

flushBuffer()

let type: 'emphasis' | 'strong' = 'emphasis'

if (peek() === char) {
type = 'strong'
i++
}

const emphasisOrStrong: EmphasisNode | StrongNode = {
type,
children: [],
code: char,
}
cursor.children.push(emphasisOrStrong)
stack.push(emphasisOrStrong)
cursor = emphasisOrStrong
}

if (text.length > 0) {
paragraphStart()
}

for (i = 0; i < text.length; i++) {
const char = text[i]
switch (char) {
case '\n':
paragraphEnd()
continue
case '*':
case '_':
emphasisOrStrong(char)
continue
}
if (cursor === null) paragraphStart()
buffer += char
}

paragraphEnd()

console.log(document)

return document
}
12 changes: 0 additions & 12 deletions packages/apps/client/src/lib/mdExtensions/everyLineAParagraph.ts

This file was deleted.

59 changes: 5 additions & 54 deletions packages/apps/client/src/lib/prosemirrorDoc.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,24 @@
import { fromMarkdown as mdAstFromMarkdown } from 'mdast-util-from-markdown'
import { toMarkdown as mdAstToMarkdown } from 'mdast-util-to-markdown'
import type { Node as MdAstNode, Parent as MdAstParent, Literal as MdAstLiteral } from 'mdast'
import { Node as ProsemirrorNode } from 'prosemirror-model'
import { directive } from 'micromark-extension-directive'
import { schema } from '../ScriptEditor/scriptSchema'
import { directiveFromMarkdown, directiveToMarkdown } from 'mdast-util-directive'
import { everyLineAParagraph } from './mdExtensions/everyLineAParagraph'
import { astFromMarkdownish, Node as MdAstNode } from './markdownishParser'

export function fromMarkdown(text: string): ProsemirrorNode[] {
const ast = mdAstFromMarkdown(text, 'utf-8', {
extensions: [directive()],
mdastExtensions: [everyLineAParagraph(), directiveFromMarkdown()],
})
const ast = astFromMarkdownish(text)

return traverseMdAstNodes(ast.children)
}

export function toMarkdown(doc: ProsemirrorNode[]): string {
return mdAstToMarkdown(
{
type: 'root',
children: [],
},
{
extensions: [directiveToMarkdown()],
}
)
}

function mdastToEditorSchemaNode(node: MdAstNode, children?: ProsemirrorNode[]): ProsemirrorNode[] {
if (node.type === 'paragraph') {
return [schema.node(schema.nodes.paragraph, undefined, children)]
} else if (isLeafDirective(node) && node.name === 'emptyPara') {
return [schema.node(schema.nodes.paragraph, undefined, [])]
} else if (node.type === 'text' && isLiteral(node)) {
} else if (node.type === 'text') {
return [schema.text(node.value)]
} else if (node.type === 'strong' && children) {
return children.map((child) => child.mark([...child.marks, schema.mark(schema.marks.bold)]))
} else if (node.type === 'emphasis' && children) {
return children.map((child) => child.mark([...child.marks, schema.mark(schema.marks.italic)]))
} else if (isTextDirective(node) && node.name === 'reverse' && children) {
} else if (node.type === 'reverse' && children) {
return children.map((child) => child.mark([...child.marks, schema.mark(schema.marks.reverse)]))
} else if (node.type === 'break') {
return [schema.text('\n')]
} else {
console.warn(node)
return [schema.text('[UNKNOWN]')]
Expand All @@ -53,36 +29,11 @@ function traverseMdAstNodes(nodes: MdAstNode[]): ProsemirrorNode[] {
const result: ProsemirrorNode[] = []
for (const childNode of nodes) {
let children: ProsemirrorNode[] = []
if (isParent(childNode)) {
if ('children' in childNode) {
children = traverseMdAstNodes(childNode.children)
}
result.push(...mdastToEditorSchemaNode(childNode, children))
}

return result
}

function isParent(node: MdAstNode): node is MdAstParent {
if ('children' in node && Array.isArray(node.children)) return true
return false
}

function isLiteral(node: MdAstNode): node is MdAstLiteral {
if ('value' in node) return true
return false
}

function isTextDirective(node: MdAstNode): node is MdAstTextDirective {
if (node.type === 'textDirective' && 'name' in node) return true
return false
}

function isLeafDirective(node: MdAstNode): node is MdAstTextDirective {
if (node.type === 'leafDirective' && 'name' in node) return true
return false
}

interface MdAstTextDirective extends MdAstNode {
name: string
attributes: Record<string, string>
}
2 changes: 2 additions & 0 deletions packages/shared/model/src/model/ViewPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface ViewPort {

/** Current position of the viewport */
position: ViewPortPosition

// last controller message?
}
/** Defines a position of the viewport */
export interface ViewPortPosition {
Expand Down
Loading

0 comments on commit e337c36

Please sign in to comment.