Files
upstream-affine/packages/common/reader/src/doc-parser/delta-to-md/delta-to-md.ts
upstream-mirror 50f788e799
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
snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:31:07 +05:00

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;
}