Skip to content

Commit

Permalink
refactor: viewer meta info
Browse files Browse the repository at this point in the history
  • Loading branch information
pd4d10 committed Oct 4, 2023
1 parent 603c7ec commit 5649b2f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 58 deletions.
18 changes: 10 additions & 8 deletions packages/bytemd/src/editor-next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import './sidebar.js'
import './status.js'
import './toc.js'
import './toolbar.js'
import { BytemdEditorContext, EditorProps } from './types'
import { EditorProps } from './types'
import { Meta } from './viewer-next'
import { EditorView } from '@codemirror/view'
import { Element, Root } from 'hast'
import { LitElement, PropertyValueMap, css, html, nothing } from 'lit'
Expand All @@ -28,9 +29,8 @@ export class Editor extends LitElement {
@property({ state: true }) _activeTab: false | 'write' | 'preview' = false
@property({ state: true }) _fullscreen = false
@property({ state: true }) _sync = true
@property({ state: true }) _context: BytemdEditorContext | undefined
@property({ state: true }) _sidebar: 'help' | 'toc' | false = 'toc'
@property({ state: true }) _hast?: Root
@property({ state: true }) meta?: Meta

@property({ state: true }) editCalled = false
@property({ state: true }) previewCalled = false
Expand Down Expand Up @@ -58,14 +58,16 @@ export class Editor extends LitElement {
}

updateBlockPositions = throttle(() => {
if (!this.meta) return

const editEl = this._editor!.scrollDOM
const previewEl = this.renderRoot.querySelector('.preview')!
const body = this.renderRoot.querySelector<HTMLElement>('bytemd-viewer')!

this.editPs = []
this.previewPs = []

const leftNodes = this._hast!.children.filter(
const leftNodes = this.meta.hast.children.filter(
(v): v is Element => v.type === 'element',
)
const rightNodes = [...body.shadowRoot!.children].filter(
Expand Down Expand Up @@ -188,7 +190,6 @@ export class Editor extends LitElement {
_activeTab,
_fullscreen,
_sidebar,
_hast,
} = this
const mergedLocale = { ...en, ...locale }
const actions = getBuiltinActions(mergedLocale, plugins, uploadImages)
Expand All @@ -214,8 +215,8 @@ export class Editor extends LitElement {
<div class="preview" @scroll=${this.previewScroll}>
<bytemd-viewer
.value=${value}
@info=${(e: CustomEvent) => {
this._hast = e.detail.hast
@meta=${(e: CustomEvent) => {
this.meta = e.detail
}}
></bytemd-viewer>
</div>
Expand All @@ -233,7 +234,8 @@ export class Editor extends LitElement {
: _sidebar === 'toc'
? html`<bytemd-toc
.locale=${mergedLocale}
.hast=${_hast}
.currentBlockIndex=${this.currentBlockIndex}
.meta=${this.meta}
></bytemd-toc>`
: nothing}
</bytemd-sidebar>`
Expand Down
59 changes: 16 additions & 43 deletions packages/bytemd/src/toc.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,43 @@
import type { BytemdLocale } from './types'
import type { Root, Element } from 'hast'
import { Meta } from './viewer-next'
import { LitElement, css, html, nothing } from 'lit'
import { customElement, property } from 'lit/decorators.js'
import { classMap } from 'lit/directives/class-map.js'
import { styleMap } from 'lit/directives/style-map.js'
import { visit } from 'unist-util-visit'

function stringifyHeading(e: Element) {
let result = ''
visit(e, (node) => {
if (node.type === 'text') {
result += node.value
}
})
return result
}

@customElement('bytemd-toc')
export class Toc extends LitElement {
@property() hast?: Root
@property() meta?: Meta
@property() currentBlockIndex = 0
@property() locale: Partial<BytemdLocale> = {}

@property({ state: true }) items: { level: number; text: string }[] = []
@property({ state: true }) minLevel = 6
@property({ state: true }) currentHeadingIndex = 0

protected render(): unknown {
this.hast?.children
.filter((v): v is Element => v.type === 'element')
.forEach((node, index) => {
if (node.tagName[0] === 'h' && !!node.children.length) {
const i = Number(node.tagName[1])
this.minLevel = Math.min(this.minLevel, i)
this.items.push({
level: i,
text: stringifyHeading(node),
})
}

// console.log(currentBlockIndex, index);
if (this.currentBlockIndex >= index) {
this.currentHeadingIndex = this.items.length - 1
}
})
const { meta } = this
if (!meta) return nothing

const { locale, items, currentHeadingIndex, minLevel } = this
const minLevel = meta.toc.reduce(
(min, { level }) => Math.min(min, level),
6,
)

return html`<h2>${locale.toc}</h2>
return html`<h2>${this.locale.toc}</h2>
<ul>
${items.map(
(item, index) =>
${meta.toc.map(
({ level, text }, index) =>
html`<li
class=${classMap({
[`toc-${item.level}`]: true,
active: currentHeadingIndex === index,
first: item.level === minLevel,
[`toc-${level}`]: true,
active: this.currentBlockIndex === index,
first: level === minLevel,
})}
style=${styleMap({
paddingLeft: `${(item.level - minLevel) * 16 + 8}px`,
paddingLeft: `${(level - minLevel) * 16 + 8}px`,
})}
@click=${() => {
this.dispatchEvent(new CustomEvent('click', { detail: index }))
}}
>
${item.text}
${text}
</li>`,
)}
</ul>`
Expand Down
46 changes: 39 additions & 7 deletions packages/bytemd/src/viewer-next.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
import { BytemdPlugin, ViewerProps } from './types'
import { getProcessor } from './utils'
import type { Root } from 'hast'
import type { Root, Element } from 'hast'
import { LitElement, html } from 'lit'
import { customElement, property } from 'lit/decorators.js'
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
import type { Plugin } from 'unified'
import { visit } from 'unist-util-visit'
import type { VFile } from 'vfile'

export interface Meta {
hast: Root
file: VFile
toc: { level: number; text: string }[]
}

function stringifyHeading(e: Element) {
let result = ''
visit(e, (node) => {
if (node.type === 'text') {
result += node.value
}
})
return result
}

@customElement('bytemd-viewer')
export class Viewer extends LitElement {
@property({ attribute: true }) value: ViewerProps['value'] = ''
@property() plugins: ViewerProps['plugins']
@property() sanitize: ViewerProps['sanitize']
@property() remarkRehype: ViewerProps['remarkRehype']

@property({ state: true }) meta?: Meta

protected firstUpdated() {
this.renderRoot.addEventListener('click', (e) => {
const $ = e.target as HTMLElement
Expand All @@ -28,12 +46,26 @@ export class Viewer extends LitElement {

render() {
const dispatchPlugin: BytemdPlugin = {
// @ts-ignore
rehype: (processor) =>
processor.use<any>(() => (tree, file) => {
// console.log(tree, file)
this.dispatchEvent(
new CustomEvent('info', { detail: { hast: tree, file } }),
)
processor.use<any, Root>(() => (hast, file) => {
// console.log(hast, file)

let toc: Meta['toc'] = []
hast.children
.filter((v): v is Element => v.type === 'element')
.forEach((node) => {
if (node.tagName[0] === 'h' && !!node.children.length) {
const i = Number(node.tagName[1])
toc.push({
level: i,
text: stringifyHeading(node),
})
}
})

this.meta = { hast, file, toc }
this.dispatchEvent(new CustomEvent('meta', { detail: this.meta }))
}),
}

Expand Down

0 comments on commit 5649b2f

Please sign in to comment.