Skip to content

Commit

Permalink
revert: html inline node parse method
Browse files Browse the repository at this point in the history
  • Loading branch information
drl990114 committed Aug 5, 2024
1 parent 8886167 commit d61c5a1
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 77 deletions.
75 changes: 75 additions & 0 deletions src/editor/extensions/HtmlNode/html-inline-extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { isImageElement } from '@/editor/utils/html'
import type { MarkExtensionSpec, NodeViewMethod } from 'remirror'
import { MarkExtension, extension } from 'remirror'

type LineHtmlInlineExtensionOptions = {
handleViewImgSrcUrl?: (src: string) => Promise<string>
}

@extension<LineHtmlInlineExtensionOptions>({
defaultOptions: {
handleViewImgSrcUrl: async (src: string) => src,
},
})
export class LineHtmlInlineExtension extends MarkExtension<LineHtmlInlineExtensionOptions> {
static disableExtraAttributes = true

get name() {
return 'mdHtmlInline' as const
}

createMarkSpec(): MarkExtensionSpec {
return {
attrs: {
depth: { default: 0 },
key: {
default: '',
},
htmlText: {
default: '',
},
},
toDOM: (mark) => [
'span',
{
...mark.attrs,
},
0,
],
}
}

createNodeViews(): NodeViewMethod | Record<string, NodeViewMethod> {
return (node) => {
const container = document.createElement('span')

const domParser = new DOMParser()
const doc = domParser.parseFromString(node.attrs.htmlText || '', 'text/html')

doc.body.childNodes.forEach((child) => {
if (isImageElement(child) && child.src && this.options.handleViewImgSrcUrl) {
let targetUrl = child.src

if (child.src.includes(location.origin)) {
targetUrl = child.src.split(location.origin)[1]
}

this.options.handleViewImgSrcUrl(targetUrl).then((newHref) => {
child.src = newHref
})
}
container.appendChild(child)
})

const contentDom = document.createElement('span')
container.appendChild(contentDom)
container.setAttribute('key', node.attrs.key)
contentDom.setAttribute('class', 'md-html-inline')

return {
dom: container,
contentDOM: contentDom,
}
}
}
}
188 changes: 112 additions & 76 deletions src/editor/extensions/Inline/from-inline-markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { InlineToken } from './inline-types'
import { getAttrsBySignalHtmlContent, getTagName, isClosingTag } from '../../utils/html'
import { needSplitInlineHtmlTokenTags } from '@/editor/transform/markdown-it-html-inline'
import { HtmlMarksSpec } from '../HtmlNode/html-inline-marks'
import { cloneDeep } from 'lodash'

gfmAutolinkLiteralFromMarkdown.transforms = []

Expand Down Expand Up @@ -349,78 +350,78 @@ function parseMdInline(phrasingContents: mdast.PhrasingContent[], depth = 1) {
return inlineTokens
}

// function mergePhrasingContents(
// phrasingContents: mdast.HTML[],
// startIndex: number,
// endIndex: number,
// ): MdAstHtml[] {
// const merged = cloneDeep(phrasingContents[startIndex]) as MdAstHtml

// for (let i = startIndex + 1; i <= endIndex; i++) {
// merged.value += phrasingContents[i].value || ''
// merged.position!.end = phrasingContents[i].position!.end
// merged.complete = true
// }

// phrasingContents.splice(startIndex, endIndex - startIndex + 1, merged)
// return phrasingContents as MdAstHtml[]
// }

// function getMergeArr(phrasingContents: MdAstHtml[]) {
// const unCloseedHtmlStack: HTMLNode[] = []
// const mergeArr: HTMLNode[][] = []
// for (let i = 0; i < phrasingContents.length; i++) {
// const phrasingContent = phrasingContents[i]
// if (phrasingContent.type === 'html') {
// const tagName = getTagName(phrasingContent.value)
// const htmlNode = {
// tag: tagName,
// voidElement: !!voidElements[tagName],
// isClosingTag: isClosingTag(phrasingContent.value),
// index: i,
// }

// if (!htmlNode.voidElement) {
// if (!htmlNode.isClosingTag) {
// unCloseedHtmlStack.push(htmlNode)
// } else if (unCloseedHtmlStack[unCloseedHtmlStack.length - 1]?.tag === htmlNode.tag) {
// if (unCloseedHtmlStack.length >= 1) {
// mergeArr.push([unCloseedHtmlStack.pop()!, htmlNode])
// phrasingContent.complete = true
// }
// }
// } else {
// phrasingContent.complete = true
// }
// }
// }

// for (let i = 0; i < mergeArr.length; i++) {
// const merge = mergeArr[i]
// const startIndex = merge[0].index
// const endIndex = merge[1].index
// const parentNode = mergeArr.findIndex(
// (item) => item[0].index < startIndex && item[1].index > endIndex,
// )
// if (parentNode >= 0) {
// mergeArr.splice(i, 1)
// i--
// }
// }

// return mergeArr
// }

// function mergeHtmlPhrasingContents(phrasingContents: MdAstHtml[]) {
// const mergeArr = getMergeArr(phrasingContents)
// let offset = 0
// mergeArr.forEach((merge) => {
// const startIndex = merge[0].index + offset
// const endIndex = merge[1].index + offset
// mergePhrasingContents(phrasingContents, startIndex, endIndex)
// offset += startIndex - endIndex
// })
// }
function mergePhrasingContents(
phrasingContents: mdast.HTML[],
startIndex: number,
endIndex: number,
): MdAstHtml[] {
const merged = cloneDeep(phrasingContents[startIndex]) as MdAstHtml

for (let i = startIndex + 1; i <= endIndex; i++) {
merged.value += phrasingContents[i].value || ''
merged.position!.end = phrasingContents[i].position!.end
merged.complete = true
}

phrasingContents.splice(startIndex, endIndex - startIndex + 1, merged)
return phrasingContents as MdAstHtml[]
}

function getMergeArr(phrasingContents: MdAstHtml[]) {
const unCloseedHtmlStack: HTMLNode[] = []
const mergeArr: HTMLNode[][] = []
for (let i = 0; i < phrasingContents.length; i++) {
const phrasingContent = phrasingContents[i]
if (phrasingContent.type === 'html') {
const tagName = getTagName(phrasingContent.value)
const htmlNode = {
tag: tagName,
voidElement: !!voidElements[tagName],
isClosingTag: isClosingTag(phrasingContent.value),
index: i,
}

if (!htmlNode.voidElement) {
if (!htmlNode.isClosingTag) {
unCloseedHtmlStack.push(htmlNode)
} else if (unCloseedHtmlStack[unCloseedHtmlStack.length - 1]?.tag === htmlNode.tag) {
if (unCloseedHtmlStack.length >= 1) {
mergeArr.push([unCloseedHtmlStack.pop()!, htmlNode])
phrasingContent.complete = true
}
}
} else {
phrasingContent.complete = true
}
}
}

for (let i = 0; i < mergeArr.length; i++) {
const merge = mergeArr[i]
const startIndex = merge[0].index
const endIndex = merge[1].index
const parentNode = mergeArr.findIndex(
(item) => item[0].index < startIndex && item[1].index > endIndex,
)
if (parentNode >= 0) {
mergeArr.splice(i, 1)
i--
}
}

return mergeArr
}

function mergeHtmlPhrasingContents(phrasingContents: MdAstHtml[]) {
const mergeArr = getMergeArr(phrasingContents)
let offset = 0
mergeArr.forEach((merge) => {
const startIndex = merge[0].index + offset
const endIndex = merge[1].index + offset
mergePhrasingContents(phrasingContents, startIndex, endIndex)
offset += startIndex - endIndex
})
}

export const splitHtmlTokens = (tokens: mdast.PhrasingContent[]) => {
let splitArr = []
Expand Down Expand Up @@ -555,18 +556,53 @@ function hasHtmlToken(mdastToken: mdast.PhrasingContent[]) {
return false
}

function flatHTMLInlineCode(phrasingContents: MdAstHtml[], depth = 1) {
mergeHtmlPhrasingContents(phrasingContents)

const inlineTokens: InlineToken[] = []
phrasingContents.forEach((phrascontent) => {
if (phrascontent.type === 'html') {
if (phrascontent.complete) {
inlineTokens.push({
marks: ['mdHtmlInline'],
attrs: {
depth: 1,
htmlText: phrascontent.value,
key: nanoid(),
first: true,
last: true,
},
start: phrascontent.position!.start.offset!,
end: phrascontent.position!.end.offset!,
})
} else {
inlineTokens.push({
marks: ['mdText'],
attrs: { depth, first: true, last: true },
start: phrascontent.position!.start.offset!,
end: phrascontent.position!.end.offset!,
})
}
} else {
const tokens = flatPhrasingContent(phrascontent, depth)
inlineTokens.push(...fixTokensMarkNames(tokens))
}
})

return inlineTokens
}

export function fromInlineMarkdown(text: string): InlineToken[] {
const phrasingContents = parseInlineMarkdown(text)

if (hasHtmlToken(phrasingContents)) {
const nodes = flatHTMLInlineToken(phrasingContents as MdAstHtml[])
return nodes
return flatHTMLInlineCode(phrasingContents as MdAstHtml[])
}

const tokens = parseMdInline(phrasingContents)
return tokens
return parseMdInline(phrasingContents)
}


type HtmlToken = {
depth?: number
start?: boolean
Expand Down
2 changes: 1 addition & 1 deletion src/editor/extensions/Inline/inline-mark-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export const markExtensions = (options: LineMarkExtensionOptions = {}) => [
new ImgUri({
handleViewImgSrcUrl: options.handleViewImgSrcUrl,
}),
new HtmlInlineMarks(),
// new HtmlInlineMarks(),
]
export type LineMarkExtension = ReturnType<typeof markExtensions>[number]
export type LineMarkName = LineMarkExtension['name']
Expand Down
4 changes: 4 additions & 0 deletions src/editor/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { PlaceholderExtension } from './Placeholder'
import { ClipboardExtension } from './Clipboard'
import { minimalSetup } from './CodeMirror/setup'
import { HtmlBrExtension } from './HtmlBr/br-extension'
import { LineHtmlInlineExtension } from './HtmlNode/html-inline-extension'

// import { TableExtension } from './ReactTables';

Expand All @@ -70,6 +71,9 @@ function extensions({ handleViewImgSrcUrl }: ExtensionsOptions): any[] {
new IframeExtension({
enableResizing: true,
}),
new LineHtmlInlineExtension({
handleViewImgSrcUrl,
}),

new PlaceholderExtension({ placeholder: 'Type \'/\' for commands' }),
new LineHorizontalRuleExtension({}),
Expand Down

0 comments on commit d61c5a1

Please sign in to comment.