mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 18:16:15 +08:00
refactor: recode html2block
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
import { AsyncBlock, BaseView } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { defaultBulletProps, BulletView } from './BulletView';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
export class BulletBlock extends BaseView {
|
||||
public type = Protocol.Block.Type.bullet;
|
||||
@@ -18,49 +24,41 @@ export class BulletBlock extends BaseView {
|
||||
}
|
||||
return block;
|
||||
}
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
if (element.tagName === 'UL') {
|
||||
const firstList = element.querySelector('li');
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'UL') {
|
||||
const result = [];
|
||||
for (let i = 0; i < el.children.length; i++) {
|
||||
const blocks_info = parseEl(el.children[i]);
|
||||
result.push(...blocks_info);
|
||||
if (!firstList || firstList.innerText.startsWith('[ ] ')) {
|
||||
return null;
|
||||
}
|
||||
return result.length > 0 ? result : null;
|
||||
const children = Array.from(element.children);
|
||||
const childrenBlockInfos = (
|
||||
await Promise.all(
|
||||
children.map(childElement =>
|
||||
this.html2block2({
|
||||
editor,
|
||||
element: childElement,
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter(v => v);
|
||||
return childrenBlockInfos.length ? childrenBlockInfos : null;
|
||||
}
|
||||
|
||||
if (tag_name == 'LI' && !el.textContent.startsWith('[ ] ')) {
|
||||
const childNodes = el.childNodes;
|
||||
const texts = [];
|
||||
const children = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
} else {
|
||||
children.push(blocks_info[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: children,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'LI',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { BaseView, AsyncBlock } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
BaseView,
|
||||
AsyncBlock,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { CodeView } from './CodeView';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
|
||||
export class CodeBlock extends BaseView {
|
||||
@@ -21,39 +27,19 @@ export class CodeBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
// TODO: internal format not implemented yet
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'CODE') {
|
||||
const childNodes = el.childNodes;
|
||||
let text_value = '';
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
if (block_texts.length > 0) {
|
||||
text_value += block_texts[0].text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: [{ text: text_value }] },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'CODE',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
SelectBlock,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { DividerView } from './divider-view';
|
||||
import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
import { Block2HtmlProps, commonHTML2block } from '../../utils/commonBlockClip';
|
||||
|
||||
export class DividerBlock extends BaseView {
|
||||
type = Protocol.Block.Type.divider;
|
||||
View = DividerView;
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'HR') {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: {},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'HR',
|
||||
ignoreEmptyElement: false,
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
return `<hr/>`;
|
||||
}
|
||||
|
||||
@@ -13,29 +13,6 @@ export class EmbedLinkBlock extends BaseView {
|
||||
type = Protocol.Block.Type.embedLink;
|
||||
View = EmbedLinkView;
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'A' && el.parentElement?.childElementCount === 1) {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
// TODO: Not sure what value to fill for name
|
||||
embedLink: {
|
||||
name: this.type,
|
||||
value: el.getAttribute('href'),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
override async block2html({ block }: Block2HtmlProps) {
|
||||
const url = block.getProperty('embedLink')?.value;
|
||||
return `<p><a href="${url}">${url}</a></p>`;
|
||||
|
||||
@@ -13,35 +13,6 @@ export class FigmaBlock extends BaseView {
|
||||
type = Protocol.Block.Type.figma;
|
||||
View = FigmaView;
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'A' && el.parentElement?.childElementCount === 1) {
|
||||
const href = el.getAttribute('href');
|
||||
const allowedHosts = ['www.figma.com'];
|
||||
const host = new URL(href).host;
|
||||
|
||||
if (allowedHosts.includes(host)) {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
// TODO: Not sure what value to fill for name
|
||||
embedLink: {
|
||||
name: this.type,
|
||||
value: el.getAttribute('href'),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
override async block2html({ block }: Block2HtmlProps) {
|
||||
const figmaUrl = block.getProperty('embedLink')?.value;
|
||||
return `<p><a href="${figmaUrl}">${figmaUrl}</a></p>`;
|
||||
|
||||
@@ -10,25 +10,7 @@ import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
export class GroupDividerBlock extends BaseView {
|
||||
type = Protocol.Block.Type.groupDivider;
|
||||
View = GroupDividerView;
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'HR') {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: {},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
return `<hr/>`;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { BaseView } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { ImageView } from './ImageView';
|
||||
import { Block2HtmlProps } from '../../utils/commonBlockClip';
|
||||
import { getRandomString } from '@toeverything/components/common';
|
||||
|
||||
export class ImageBlock extends BaseView {
|
||||
public override selectable = true;
|
||||
@@ -10,27 +15,30 @@ export class ImageBlock extends BaseView {
|
||||
View = ImageView;
|
||||
|
||||
// TODO: needs to download the image and then upload it to get a new link and then assign it
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'IMG') {
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
if (element.tagName === 'IMG') {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
value: '',
|
||||
url: el.getAttribute('src'),
|
||||
name: el.getAttribute('src'),
|
||||
size: 0,
|
||||
type: 'link',
|
||||
image: {
|
||||
value: getRandomString('image'),
|
||||
url: element.getAttribute('src'),
|
||||
name: element.getAttribute('src'),
|
||||
size: 0,
|
||||
type: 'link',
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { AsyncBlock, BaseView } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { defaultTodoProps, NumberedView } from './NumberedView';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
|
||||
export class NumberedBlock extends BaseView {
|
||||
@@ -22,55 +28,38 @@ export class NumberedBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'OL') {
|
||||
const result = [];
|
||||
for (let i = 0; i < el.children.length; i++) {
|
||||
const blocks_info = parseEl(el.children[i]);
|
||||
result.push(...blocks_info);
|
||||
}
|
||||
return result.length > 0 ? result : null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
if (element.tagName === 'OL') {
|
||||
const children = Array.from(element.children);
|
||||
const childrenBlockInfos = (
|
||||
await Promise.all(
|
||||
children.map(childElement =>
|
||||
this.html2block2({
|
||||
editor,
|
||||
element: childElement,
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter(v => v);
|
||||
return childrenBlockInfos.length ? childrenBlockInfos : null;
|
||||
}
|
||||
|
||||
if (tag_name == 'LI' && el.textContent.startsWith('[ ] ')) {
|
||||
const childNodes = el.childNodes;
|
||||
let texts = [];
|
||||
const children = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
} else {
|
||||
children.push(blocks_info[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (texts.length > 0 && (texts[0].text || '').startsWith('[ ] ')) {
|
||||
texts[0].text = texts[0].text.substring('[ ] '.length);
|
||||
if (!texts[0].text) {
|
||||
texts = texts.slice(1);
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: children,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'LI',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
return `<ol><li>${await commonBlock2HtmlContent(props)}</li></ol>`;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
CreateView,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
|
||||
import { TextView } from './TextView';
|
||||
@@ -27,36 +30,19 @@ export class QuoteBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'BLOCKQUOTE') {
|
||||
const childNodes = el.childNodes;
|
||||
const texts = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'BLOCKQUOTE',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
@@ -82,52 +68,19 @@ export class CalloutBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (
|
||||
tag_name === 'ASIDE' ||
|
||||
el.firstChild?.nodeValue?.startsWith('<aside>')
|
||||
) {
|
||||
const childNodes = el.childNodes;
|
||||
let texts = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
texts.length > 0 &&
|
||||
(texts[0].text || '').startsWith('<aside>')
|
||||
) {
|
||||
texts[0].text = texts[0].text.substring('<aside>'.length);
|
||||
if (!texts[0].text) {
|
||||
texts = texts.slice(1);
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (el.firstChild?.nodeValue?.startsWith('</aside>')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'ASIDE',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
|
||||
@@ -2,14 +2,15 @@ import {
|
||||
BaseView,
|
||||
CreateView,
|
||||
AsyncBlock,
|
||||
HTML2BlockResult,
|
||||
BlockEditor,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { TextView } from './TextView';
|
||||
|
||||
import { getRandomString } from '@toeverything/components/common';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
|
||||
export class TextBlock extends BaseView {
|
||||
@@ -26,92 +27,30 @@ export class TextBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
if (el instanceof Text) {
|
||||
// TODO: parsing style
|
||||
return el.textContent.split('\n').map(text => {
|
||||
return {
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: [{ text: text }] },
|
||||
},
|
||||
children: [],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const tag_name = el.tagName;
|
||||
const block_style: any = {};
|
||||
switch (tag_name) {
|
||||
case 'STRONG':
|
||||
case 'B':
|
||||
block_style.bold = true;
|
||||
break;
|
||||
case 'A':
|
||||
block_style.type = 'link';
|
||||
block_style.url = el.getAttribute('href');
|
||||
block_style.id = getRandomString('link');
|
||||
block_style.children = [];
|
||||
break;
|
||||
case 'EM':
|
||||
block_style.italic = true;
|
||||
break;
|
||||
case 'U':
|
||||
block_style.underline = true;
|
||||
break;
|
||||
case 'CODE':
|
||||
block_style.inlinecode = true;
|
||||
break;
|
||||
case 'S':
|
||||
case 'DEL':
|
||||
block_style.strikethrough = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const child_nodes = el.childNodes;
|
||||
let texts = [];
|
||||
if (Object.keys(block_style).length > 0) {
|
||||
for (let i = 0; i < child_nodes.length; i++) {
|
||||
const blocks_info: any[] = parseEl(child_nodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
const block = blocks_info[j];
|
||||
if (block.type === this.type) {
|
||||
const block_texts = block.properties.text.value.map(
|
||||
(text_value: any) => {
|
||||
return tag_name === 'A'
|
||||
? { ...text_value }
|
||||
: { ...block_style, ...text_value };
|
||||
}
|
||||
);
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag_name === 'A') {
|
||||
block_style.children.push(...texts);
|
||||
texts = [block_style];
|
||||
}
|
||||
return texts.length > 0
|
||||
? [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
]
|
||||
: null;
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
return `<p>${await commonBlock2HtmlContent(props)}</p>`;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: [
|
||||
'DIV',
|
||||
'P',
|
||||
'PRE',
|
||||
'B',
|
||||
'A',
|
||||
'EM',
|
||||
'U',
|
||||
'CODE',
|
||||
'S',
|
||||
'DEL',
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,37 +67,19 @@ export class Heading1Block extends BaseView {
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'H1') {
|
||||
const childNodes = el.childNodes;
|
||||
const texts = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'H1',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
@@ -179,37 +100,19 @@ export class Heading2Block extends BaseView {
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'H2') {
|
||||
const childNodes = el.childNodes;
|
||||
const texts = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'H2',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
@@ -231,36 +134,19 @@ export class Heading3Block extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'H3') {
|
||||
const childNodes = el.childNodes;
|
||||
const texts = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'H3',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { BaseView } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
BaseView,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
} from '@toeverything/framework/virgo';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import { withTreeViewChildren } from '../../utils/WithTreeViewChildren';
|
||||
import { TodoView, defaultTodoProps } from './TodoView';
|
||||
@@ -6,6 +10,7 @@ import type { TodoAsyncBlock } from './types';
|
||||
import {
|
||||
Block2HtmlProps,
|
||||
commonBlock2HtmlContent,
|
||||
commonHTML2block,
|
||||
} from '../../utils/commonBlockClip';
|
||||
|
||||
export class TodoBlock extends BaseView {
|
||||
@@ -22,54 +27,41 @@ export class TodoBlock extends BaseView {
|
||||
return block;
|
||||
}
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'UL') {
|
||||
const result = [];
|
||||
for (let i = 0; i < el.children.length; i++) {
|
||||
const blocks_info = parseEl(el.children[i]);
|
||||
result.push(...blocks_info);
|
||||
override async html2block2({
|
||||
element,
|
||||
editor,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
}): Promise<HTML2BlockResult> {
|
||||
if (element.tagName === 'UL') {
|
||||
const firstList = element.querySelector('li');
|
||||
if (!firstList || !firstList.innerText.startsWith('[ ] ')) {
|
||||
return null;
|
||||
}
|
||||
return result.length > 0 ? result : null;
|
||||
|
||||
const children = Array.from(element.children);
|
||||
const childrenBlockInfos = (
|
||||
await Promise.all(
|
||||
children.map(childElement =>
|
||||
this.html2block2({
|
||||
editor,
|
||||
element: childElement,
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter(v => v);
|
||||
return childrenBlockInfos.length ? childrenBlockInfos : null;
|
||||
}
|
||||
|
||||
if (tag_name == 'LI' && el.textContent.startsWith('[ ] ')) {
|
||||
const childNodes = el.childNodes;
|
||||
let texts = [];
|
||||
const children = [];
|
||||
for (let i = 0; i < childNodes.length; i++) {
|
||||
const blocks_info = parseEl(childNodes[i] as Element);
|
||||
for (let j = 0; j < blocks_info.length; j++) {
|
||||
if (blocks_info[j].type === 'text') {
|
||||
const block_texts =
|
||||
blocks_info[j].properties.text.value;
|
||||
texts.push(...block_texts);
|
||||
} else {
|
||||
children.push(blocks_info[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (texts.length > 0 && (texts[0].text || '').startsWith('[ ] ')) {
|
||||
texts[0].text = texts[0].text.substring('[ ] '.length);
|
||||
if (!texts[0].text) {
|
||||
texts = texts.slice(1);
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
text: { value: texts },
|
||||
},
|
||||
children: children,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
return commonHTML2block({
|
||||
element,
|
||||
editor,
|
||||
type: this.type,
|
||||
tagName: 'LI',
|
||||
});
|
||||
}
|
||||
|
||||
override async block2html(props: Block2HtmlProps) {
|
||||
|
||||
@@ -16,35 +16,6 @@ export class YoutubeBlock extends BaseView {
|
||||
type = Protocol.Block.Type.youtube;
|
||||
View = YoutubeView;
|
||||
|
||||
override html2block(
|
||||
el: Element,
|
||||
parseEl: (el: Element) => any[]
|
||||
): any[] | null {
|
||||
const tag_name = el.tagName;
|
||||
if (tag_name === 'A' && el.parentElement?.childElementCount === 1) {
|
||||
const href = el.getAttribute('href');
|
||||
const allowedHosts = ['www.youtu.be', 'www.youtube.com'];
|
||||
const host = new URL(href).host;
|
||||
|
||||
if (allowedHosts.includes(host)) {
|
||||
return [
|
||||
{
|
||||
type: this.type,
|
||||
properties: {
|
||||
// TODO: is not sure what value to fill in name
|
||||
embedLink: {
|
||||
name: this.type,
|
||||
value: el.getAttribute('href'),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
override async block2Text(block: AsyncBlock, selectInfo: SelectBlock) {
|
||||
return block.getProperty('embedLink')?.value ?? '';
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {
|
||||
AsyncBlock,
|
||||
BlockEditor,
|
||||
HTML2BlockResult,
|
||||
SelectBlock,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { BlockFlavorKeys } from '@toeverything/datasource/db-service';
|
||||
|
||||
export type Block2HtmlProps = {
|
||||
editor: BlockEditor;
|
||||
@@ -28,3 +30,28 @@ export const commonBlock2HtmlContent = async ({
|
||||
);
|
||||
return `${html}${childrenHtml}`;
|
||||
};
|
||||
|
||||
export const commonHTML2block = ({
|
||||
element,
|
||||
editor,
|
||||
tagName,
|
||||
type,
|
||||
ignoreEmptyElement = true,
|
||||
}: {
|
||||
element: Element;
|
||||
editor: BlockEditor;
|
||||
tagName: string | string[];
|
||||
type: BlockFlavorKeys;
|
||||
ignoreEmptyElement?: boolean;
|
||||
}): HTML2BlockResult => {
|
||||
const tagNames = typeof tagName === 'string' ? [tagName] : tagName;
|
||||
if (tagNames.includes(element.tagName)) {
|
||||
const res = editor.clipboard.clipboardUtils.commonHTML2Block(
|
||||
element,
|
||||
type,
|
||||
ignoreEmptyElement
|
||||
);
|
||||
return res ? [res] : null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user