mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-11 22:18:54 +08:00
0c7b20dc18
#### PR Dependency Tree * **PR #15464** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Replaced the project’s formatting and linting workflow with Oxfmt and Oxlint. * Added shared formatting and linting configuration, editor integration, and updated automated checks. * Updated generated files, scripts, and lint guidance to use the new tooling. * **Style** * Reformatted templates, source code, examples, and configuration files for consistent readability. * No user-facing functionality or rendering behavior changed. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
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;
|
|
}
|