Skip to content

fix(merge): incorrect caret position on merge #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = false

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
60 changes: 18 additions & 42 deletions dist/paragraph.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-paragraph[data-placeholder]:empty:before{content:attr(data-placeholder);color:#707684;font-weight:400;opacity:0}.codex-editor--empty .ce-block:first-child .ce-paragraph[data-placeholder]:empty:before{opacity:1}.codex-editor--toolbox-opened .ce-block:first-child .ce-paragraph[data-placeholder]:empty:before,.codex-editor--empty .ce-block:first-child .ce-paragraph[data-placeholder]:empty:focus:before{opacity:0}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
const s = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8 9V7.2C8 7.08954 8.08954 7 8.2 7L12 7M16 9V7.2C16 7.08954 15.9105 7 15.8 7L12 7M12 7L12 17M12 17H10M12 17H14"/></svg>';
function l(i) {
const t = document.createElement("div");
t.innerHTML = i.trim();
for (var e = document.createDocumentFragment(); t.firstChild; )
e.appendChild(t.firstChild);
return e;
}
/**
* Base Paragraph Block for the Editor.js.
* Represents a regular text block
Expand All @@ -8,7 +15,7 @@ const s = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="
* @copyright CodeX 2018
* @license The MIT License (MIT)
*/
class a {
class n {
/**
* Default placeholder for Paragraph Tool
*
Expand All @@ -27,11 +34,11 @@ class a {
* @param {object} params.api - editor.js api
* @param {boolean} readOnly - read only mode flag
*/
constructor({ data: t, config: e, api: i, readOnly: n }) {
this.api = i, this.readOnly = n, this._CSS = {
constructor({ data: t, config: e, api: r, readOnly: a }) {
this.api = r, this.readOnly = a, this._CSS = {
block: this.api.styles.block,
wrapper: "ce-paragraph"
}, this.readOnly || (this.onKeyUp = this.onKeyUp.bind(this)), this._placeholder = e.placeholder ? e.placeholder : a.DEFAULT_PLACEHOLDER, this._data = {}, this._element = null, this._preserveBlank = e.preserveBlank !== void 0 ? e.preserveBlank : !1, this.data = t;
}, this.readOnly || (this.onKeyUp = this.onKeyUp.bind(this)), this._placeholder = e.placeholder ? e.placeholder : n.DEFAULT_PLACEHOLDER, this._data = t ?? {}, this._element = null, this._preserveBlank = e.preserveBlank !== void 0 ? e.preserveBlank : !1;
}
/**
* Check if text content is empty and set empty string to inner html.
Expand Down Expand Up @@ -71,10 +78,9 @@ class a {
* @public
*/
merge(t) {
const e = {
text: this.data.text + t.text
};
this.data = e;
this._data.text += t.text;
const e = l(t.text);
this._element.appendChild(e), console.log("normalizing"), this._element.normalize();
}
/**
* Validate Paragraph block data:
Expand Down Expand Up @@ -108,7 +114,9 @@ class a {
const e = {
text: t.detail.data.innerHTML
};
this.data = e;
this._data = e, window.requestAnimationFrame(() => {
this._element.innerHTML = this._data.text || "";
});
}
/**
* Enable Conversion Toolbar. Paragraph can be converted to/from other tools
Expand Down Expand Up @@ -139,38 +147,6 @@ class a {
static get isReadOnlySupported() {
return !0;
}
/**
* Get current Tools`s data
*
* @returns {ParagraphData} Current data
* @private
*/
get data() {
if (this._element !== null) {
const t = this._element.innerHTML;
this._data.text = t;
}
return this._data;
}
/**
* Store data in plugin:
* - at the this._data property
* - at the HTML
*
* @param {ParagraphData} data — data to set
* @private
*/
set data(t) {
this._data = t || {}, this._element !== null && this.hydrate();
}
/**
* Fill tool's view with data
*/
hydrate() {
window.requestAnimationFrame(() => {
this._element.innerHTML = this._data.text || "";
});
}
/**
* Used by Editor paste handling API.
* Provides configuration to handle P tags.
Expand All @@ -195,5 +171,5 @@ class a {
}
}
export {
a as default
n as default
};
4 changes: 2 additions & 2 deletions dist/paragraph.umd.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@editorjs/paragraph",
"version": "2.11.3",
"version": "2.11.4",
"keywords": [
"codex editor",
"paragraph",
Expand Down
69 changes: 20 additions & 49 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import './index.css';

import { IconText } from '@codexteam/icons'
import makeFragment from './utils/makeFragment';

/**
* Base Paragraph Block for the Editor.js.
Expand Down Expand Up @@ -64,11 +65,9 @@ export default class Paragraph {
* @type {string}
*/
this._placeholder = config.placeholder ? config.placeholder : Paragraph.DEFAULT_PLACEHOLDER;
this._data = {};
this._data = data ?? {};
this._element = null;
this._preserveBlank = config.preserveBlank !== undefined ? config.preserveBlank : false;

this.data = data;
}

/**
Expand Down Expand Up @@ -133,11 +132,17 @@ export default class Paragraph {
* @public
*/
merge(data) {
const newData = {
text : this.data.text + data.text,
};
this._data.text += data.text;

/**
* We use appendChild instead of innerHTML to keep the links of the existing nodes
* (for example, shadow caret)
*/
const fragment = makeFragment(data.text);

this.data = newData;
this._element.appendChild(fragment);

this._element.normalize();
}

/**
Expand Down Expand Up @@ -179,7 +184,14 @@ export default class Paragraph {
text: event.detail.data.innerHTML,
};

this.data = data;
this._data = data;

/**
* We use requestAnimationFrame for performance purposes
*/
window.requestAnimationFrame(() => {
this._element.innerHTML = this._data.text || '';
});
}

/**
Expand Down Expand Up @@ -212,47 +224,6 @@ export default class Paragraph {
return true;
}

/**
* Get current Tools`s data
*
* @returns {ParagraphData} Current data
* @private
*/
get data() {
if (this._element !== null) {
const text = this._element.innerHTML;

this._data.text = text;
}

return this._data;
}

/**
* Store data in plugin:
* - at the this._data property
* - at the HTML
*
* @param {ParagraphData} data — data to set
* @private
*/
set data(data) {
this._data = data || {};

if (this._element !== null) {
this.hydrate();
}
}

/**
* Fill tool's view with data
*/
hydrate(){
window.requestAnimationFrame(() => {
this._element.innerHTML = this._data.text || '';
});
}

/**
* Used by Editor paste handling API.
* Provides configuration to handle P tags.
Expand Down
19 changes: 19 additions & 0 deletions src/utils/makeFragment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Create a DocumentFragment and fill it with HTML from a string
*
* @param {string} htmlString - A string of valid HTML
* @returns {DocumentFragment}
*/
export default function makeFragment(htmlString) {
const tempDiv = document.createElement('div');

tempDiv.innerHTML = htmlString.trim();

var fragment = document.createDocumentFragment();

while (tempDiv.firstChild) {
fragment.appendChild(tempDiv.firstChild);
}

return fragment;
}