Some checks failed
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 4s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Analyze (javascript, affine) (push) Failing after 3s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
148 lines
3.8 KiB
TypeScript
148 lines
3.8 KiB
TypeScript
// oxlint-disable
|
|
// @ts-nocheck
|
|
import { Node } from './utils/node';
|
|
|
|
export const deltaToMd = (delta, converters) => {
|
|
return convert(delta, converters).render().trimEnd() + '\n';
|
|
};
|
|
|
|
function convert(ops, converters) {
|
|
let group, line, el, activeInline, beginningOfLine;
|
|
let root = new Node();
|
|
|
|
function newLine() {
|
|
el = line = new Node(['', '\n']);
|
|
root.append(line);
|
|
activeInline = {};
|
|
}
|
|
newLine();
|
|
|
|
for (let i = 0; i < ops.length; i++) {
|
|
let op = ops[i];
|
|
|
|
if (typeof op.insert === 'object') {
|
|
for (let k in op.insert) {
|
|
if (converters.embed[k]) {
|
|
applyInlineAttributes(op.attributes);
|
|
converters.embed[k].call(el, op.insert[k], op.attributes);
|
|
}
|
|
}
|
|
} else {
|
|
let lines = op.insert.split('\n');
|
|
|
|
if (hasBlockLevelAttribute(op.attributes, converters)) {
|
|
// Some line-level styling (ie headings) is applied by inserting a \n
|
|
// with the style; the style applies back to the previous \n.
|
|
// There *should* only be one style in an insert operation.
|
|
|
|
for (let j = 1; j < lines.length; j++) {
|
|
for (let attr in op.attributes) {
|
|
if (converters.block[attr]) {
|
|
let fn = converters.block[attr];
|
|
if (typeof fn === 'object') {
|
|
if (group && group.type !== attr) {
|
|
group = null;
|
|
}
|
|
if (!group && fn.group) {
|
|
group = {
|
|
el: fn.group(),
|
|
type: attr,
|
|
value: op.attributes[attr],
|
|
distance: 0,
|
|
};
|
|
root.append(group.el);
|
|
}
|
|
|
|
if (group) {
|
|
group.el.append(line);
|
|
group.distance = 0;
|
|
}
|
|
fn = fn.line;
|
|
}
|
|
|
|
fn.call(line, op.attributes, group);
|
|
newLine();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
beginningOfLine = true;
|
|
} else {
|
|
for (let l = 0; l < lines.length; l++) {
|
|
if ((l > 0 || beginningOfLine) && group && ++group.distance >= 2) {
|
|
group = null;
|
|
}
|
|
applyInlineAttributes(
|
|
op.attributes,
|
|
ops[i + 1] && ops[i + 1].attributes
|
|
);
|
|
el.append(lines[l]);
|
|
if (l < lines.length - 1) {
|
|
newLine();
|
|
}
|
|
}
|
|
beginningOfLine = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return root;
|
|
|
|
function applyInlineAttributes(attrs, next?: any) {
|
|
let first: any[] = [];
|
|
let then: any[] = [];
|
|
attrs = attrs || {};
|
|
|
|
let tag = el,
|
|
seen = {};
|
|
while (tag._format) {
|
|
seen[tag._format] = true;
|
|
if (!attrs[tag._format] || tag.open !== tag.close) {
|
|
for (let k in seen) {
|
|
delete activeInline[k];
|
|
}
|
|
el = tag.parent();
|
|
}
|
|
|
|
tag = tag.parent();
|
|
}
|
|
|
|
for (let attr in attrs) {
|
|
if (converters.inline[attr] && attrs[attr]) {
|
|
if (activeInline[attr] && activeInline[attr] === attrs[attr]) {
|
|
continue; // do nothing -- we should already be inside this style's tag
|
|
}
|
|
|
|
if (next && attrs[attr] === next[attr]) {
|
|
first.push(attr); // if the next operation has the same style, this should be the outermost tag
|
|
} else {
|
|
then.push(attr);
|
|
}
|
|
activeInline[attr] = attrs[attr];
|
|
}
|
|
}
|
|
|
|
first.forEach(apply);
|
|
then.forEach(apply);
|
|
|
|
function apply(fmt) {
|
|
let newEl = converters.inline[fmt].call(null, attrs[fmt]);
|
|
if (Array.isArray(newEl)) {
|
|
newEl = new Node(newEl);
|
|
}
|
|
newEl._format = fmt;
|
|
el.append(newEl);
|
|
el = newEl;
|
|
}
|
|
}
|
|
}
|
|
|
|
function hasBlockLevelAttribute(attrs, converters) {
|
|
for (let k in attrs) {
|
|
if (Object.keys(converters.block).includes(k)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|