Skip to content

Commit

Permalink
Merge branch 'release/v0.12.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
holtwick committed Jan 4, 2024
2 parents 08173de + 46e0ec8 commit 74dca5c
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 11 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zeed-dom",
"type": "module",
"version": "0.12.5",
"version": "0.12.6",
"description": "🌱 Lightweight offline DOM",
"author": {
"name": "Dirk Holtwick",
Expand Down
87 changes: 87 additions & 0 deletions src/serialize-markdown.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// (C)opyright 2021-07-20 Dirk Holtwick, holtwick.it. All rights reserved.

import { serializeMarkdown } from './serialize-markdown'
import { serializePlaintext } from './serialize-plaintext'
import { createHTMLDocument, h } from './vdom'

const _keepH = h

describe('serialize', () => {
it('should create plaintext', () => {
const document = createHTMLDocument()
document.head?.appendChild(
<fragment>
<link rel="alternate" hrefLang="de" href="https://holtwick.de/de/" />
<meta name="twitter:site" content="@holtwick" />
</fragment>,
)
document.body?.appendChild(
<fragment>
<h1>Hello</h1>
<p>
This is a
{' '}
<b>sample</b>
. &gt; And a link
{' '}
<a href="example">example</a>
.
</p>
<p>
Some lines
{' '}
<br />
{' '}
line
{' '}
<br />
{' '}
line
{' '}
</p>
<ol>
<li>One</li>
<li>Two</li>
</ol>
<pre>
<p>Do nothing</p>
</pre>
</fragment>,
)

const md = serializeMarkdown(document.documentElement)
expect(md).toMatchInlineSnapshot(`
"# Hello

This is a **sample**. > And a link [example](example).

Some lines
line
line

- One
- Two

Do nothing
"
`)

const txt = serializePlaintext(document.documentElement)
expect(txt).toMatchInlineSnapshot(`
"Hello

This is a sample. > And a link example.

Some lines
line
line

One

Two

Do nothing
"
`)
})
})
51 changes: 51 additions & 0 deletions src/serialize-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { VElement, VNode } from './vdom'
import { isVElement } from './vdom'

interface SerializeContext {
level: number
count: 0
mode?: 'ol' | 'ul'
}

function serialize(node: VNode | VElement, context: SerializeContext = {
level: 0,
count: 0,
}): string {
if (isVElement(node)) {
const tag: string = node.tagName.toLowerCase()

const handleChildren = (ctx?: Partial<SerializeContext>): string => node.children.map(c => serialize(c, { ...context, ...ctx })).join('')

const rules: Record<string, () => string> = {
b: () => `**${handleChildren()}**`,
i: () => `*${handleChildren()}*`,
u: () => `_${handleChildren()}_`,
strike: () => `~~${handleChildren()}~~`,
li: () => `- ${handleChildren()}\n`,
br: () => `${handleChildren()}\n`,
ol: () => `\n\n${handleChildren({ level: context.level + 1 })}\n\n`,
ul: () => `\n\n${handleChildren({ level: context.level + 1 })}\n\n`,
p: () => `\n\n${handleChildren()}\n\n`,
div: () => `\n\n${handleChildren()}\n\n`,
h1: () => `\n\n# ${handleChildren()}\n\n`,
h2: () => `\n\n## ${handleChildren()}\n\n`,
h3: () => `\n\n### ${handleChildren()}\n\n`,
h4: () => `\n\n#### ${handleChildren()}\n\n`,
h5: () => `\n\n##### ${handleChildren()}\n\n`,
h6: () => `\n\n###### ${handleChildren()}\n\n`,
a: () => `[${handleChildren()}](${node.getAttribute('href')})`,
}

const fn = rules[tag]

if (fn)
return fn()
else
return handleChildren()
}
return node.textContent ?? ''
}

export function serializeMarkdown(node: VNode): string {
return `${serialize(node).replace(/\n\n+/gim, '\n\n').trim()}\n`
}
43 changes: 43 additions & 0 deletions src/serialize-plaintext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { SELECTOR_BLOCK_ELEMENTS } from './tidy'
import type { VElement, VNode } from './vdom'
import { isVElement } from './vdom'

interface SerializeContext {
level: number
count: 0
mode?: 'ol' | 'ul'
}

function serialize(node: VNode | VElement, context: SerializeContext = {
level: 0,
count: 0,
}): string {
if (isVElement(node)) {
const tag: string = node.tagName.toLowerCase()

const handleChildren = (ctx?: Partial<SerializeContext>): string => node.children.map(c => serialize(c, { ...context, ...ctx })).join('')

const rules: Record<string, () => string> = {
br: () => `${handleChildren()}\n`,
title: () => '',
script: () => '',
style: () => '',
}

SELECTOR_BLOCK_ELEMENTS.split(',').forEach((tag) => {
rules[tag] = () => `\n\n${handleChildren().trim()}\n\n`
})

const fn = rules[tag]

if (fn)
return fn()
else
return handleChildren()
}
return node.textContent ?? ''
}

export function serializePlaintext(node: VNode): string {
return `${serialize(node).replace(/\n\n+/gim, '\n\n').trim()}\n`
}
5 changes: 2 additions & 3 deletions src/tidy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import type { VDocument } from './vdom'
import { VNode, VTextNode } from './vdom'

const SELECTOR_BLOCK_ELEMENTS
= 'meta,link,script,p,h1,h2,h3,h4,h5,h6,blockquote,div,ul,ol,li,article,section,footer,head,body,title,nav,section,article,hr,form'
const TAGS_KEEP_CONTENT = ['PRE', 'CODE', 'SCRIPT', 'STYLE', 'TT']
export const SELECTOR_BLOCK_ELEMENTS = 'meta,link,script,p,h1,h2,h3,h4,h5,h6,blockquote,div,ul,ol,li,article,section,footer,head,body,title,nav,section,article,hr,form'
export const TAGS_KEEP_CONTENT = ['PRE', 'CODE', 'SCRIPT', 'STYLE', 'TT']

function level(element: VNode): string {
let indent = ''
Expand Down
21 changes: 14 additions & 7 deletions src/vdom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ export class VNode {
this._childNodes.push(new VTextNode(text))
}
catch (err) {
console.error(
`The data ${node} to be added to ${this.render()} is problematic: ${err}`,
)
console.error(`The data ${node} to be added to ${this.render()} is problematic: ${err}`)
}
}
this._fixChildNodesParent()
Expand Down Expand Up @@ -255,10 +253,7 @@ export class VNode {
}

get ownerDocument() {
if (
this.nodeType === VNode.DOCUMENT_NODE
|| this.nodeType === VNode.DOCUMENT_FRAGMENT_NODE
)
if (this.nodeType === VNode.DOCUMENT_NODE || this.nodeType === VNode.DOCUMENT_FRAGMENT_NODE)
return this

return this?._parentNode?.ownerDocument
Expand Down Expand Up @@ -708,3 +703,15 @@ export function createHTMLDocument(): VHTMLDocument {

export const document = createDocument()
export const h = hFactory({ document })

export function isVElement(n: VNode): n is VElement {
return n.nodeType === VNode.ELEMENT_NODE
}

export function isVTextElement(n: VNode): n is VTextNode {
return n.nodeType === VNode.TEXT_NODE
}

export function isVDocument(n: VNode): n is VDocument {
return n.nodeType === VNode.DOCUMENT_NODE
}

0 comments on commit 74dca5c

Please sign in to comment.