Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@blocksuite/virgo

Package Overview
Dependencies
Maintainers
5
Versions
509
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@blocksuite/virgo - npm Package Compare versions

Comparing version 0.5.0-20230228114851-7e82f3e to 0.5.0-20230301172958-2384904

3

dist/components/base-text.d.ts

@@ -10,3 +10,2 @@ import { LitElement } from 'lit';

code: z.ZodOptional<z.ZodBoolean>;
link: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -18,3 +17,2 @@ bold?: boolean | undefined;

code?: boolean | undefined;
link?: string | undefined;
}, {

@@ -26,3 +24,2 @@ bold?: boolean | undefined;

code?: boolean | undefined;
link?: string | undefined;
}>;

@@ -29,0 +26,0 @@ export type BaseTextAttributes = z.infer<typeof baseTextAttributes>;

@@ -19,3 +19,2 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

code: z.boolean().optional(),
link: z.string().optional(),
});

@@ -22,0 +21,0 @@ function virgoTextStyles(props) {

6

dist/virgo.d.ts

@@ -10,3 +10,9 @@ import { Signal } from '@blocksuite/global/utils';

export type DeltaEntry = [DeltaInsert, VRange];
export interface DomPoint {
text: Text;
index: number;
}
export declare class VEditor {
static nativePointToTextPoint(node: unknown, offset: number): readonly [Text, number] | null;
static textPointToDomPoint(text: Text, offset: number, rootElement: HTMLElement): DomPoint | null;
private _rootElement;

@@ -13,0 +19,0 @@ private _rootElementAbort;

@@ -8,2 +8,61 @@ import { assertExists, Signal } from '@blocksuite/global/utils';

export class VEditor {
static nativePointToTextPoint(node, offset) {
let text = null;
let textOffset = offset;
if (isVText(node)) {
text = node;
textOffset = offset;
}
else if (isVElement(node)) {
const textNode = getTextNodeFromElement(node);
if (textNode) {
text = textNode;
textOffset = offset;
}
}
else if (isVLine(node)) {
const firstTextElement = node.querySelector('v-text');
if (firstTextElement) {
const textNode = getTextNodeFromElement(firstTextElement);
if (textNode) {
text = textNode;
textOffset = 0;
}
}
}
if (!text) {
return null;
}
return [text, textOffset];
}
static textPointToDomPoint(text, offset, rootElement) {
if (rootElement.dataset.virgoRoot !== 'true') {
throw new Error('textRangeToDomPoint should be called with editor root element');
}
if (!rootElement.contains(text)) {
return null;
}
const textNodes = Array.from(rootElement.querySelectorAll('[data-virgo-text="true"]')).map(textElement => getTextNodeFromElement(textElement));
const goalIndex = textNodes.indexOf(text);
let index = 0;
for (const textNode of textNodes.slice(0, goalIndex)) {
if (!textNode) {
return null;
}
index += calculateTextLength(textNode);
}
if (text.wholeText !== ZERO_WIDTH_SPACE) {
index += offset;
}
const textElement = text.parentElement;
if (!textElement) {
throw new Error('text element not found');
}
const lineElement = textElement.closest('virgo-line');
if (!lineElement) {
throw new Error('line element not found');
}
const lineIndex = Array.from(rootElement.querySelectorAll('virgo-line')).indexOf(lineElement);
return { text, index: index + lineIndex };
}
constructor(yText, opts = {}) {

@@ -36,7 +95,5 @@ this._rootElement = null;

return;
const { anchorNode, focusNode } = selection;
if (!this._rootElement.contains(anchorNode) ||
!this._rootElement.contains(focusNode)) {
const range = selection.getRangeAt(0);
if (!range || !range.intersectsNode(this._rootElement))
return;
}
const vRange = this.toVRange(selection);

@@ -89,2 +146,5 @@ if (vRange) {

};
if (!yText.doc) {
throw new Error('yText must be attached to a Y.Doc');
}
this.yText = yText;

@@ -355,2 +415,3 @@ const { renderElement, onKeyDown } = opts;

assertExists(this._rootElement);
const root = this._rootElement;
const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;

@@ -360,8 +421,13 @@ if (!anchorNode || !focusNode) {

}
const [anchorText, anchorTextOffset] = getTextAndOffset(anchorNode, anchorOffset);
const [focusText, focusTextOffset] = getTextAndOffset(focusNode, focusOffset);
const anchorTextPoint = VEditor.nativePointToTextPoint(anchorNode, anchorOffset);
const focusTextPoint = VEditor.nativePointToTextPoint(focusNode, focusOffset);
if (!anchorTextPoint || !focusTextPoint) {
return null;
}
const [anchorText, anchorTextOffset] = anchorTextPoint;
const [focusText, focusTextOffset] = focusTextPoint;
// case 1
if (anchorText && focusText) {
const anchorDomPoint = textPointToDomPoint(anchorText, anchorTextOffset, this._rootElement);
const focusDomPoint = textPointToDomPoint(focusText, focusTextOffset, this._rootElement);
if (root.contains(anchorText) && root.contains(focusText)) {
const anchorDomPoint = VEditor.textPointToDomPoint(anchorText, anchorTextOffset, this._rootElement);
const focusDomPoint = VEditor.textPointToDomPoint(focusText, focusTextOffset, this._rootElement);
if (!anchorDomPoint || !focusDomPoint) {

@@ -375,37 +441,45 @@ return null;

}
// case 2
if (anchorText && !focusText) {
const anchorDomPoint = textPointToDomPoint(anchorText, anchorTextOffset, this._rootElement);
if (!anchorDomPoint) {
return null;
}
// case 2.1
if (!root.contains(anchorText) && root.contains(focusText)) {
if (isSelectionBackwards(selection)) {
const anchorDomPoint = VEditor.textPointToDomPoint(anchorText, anchorTextOffset, this._rootElement);
if (!anchorDomPoint) {
return null;
}
return {
index: 0,
length: anchorDomPoint.index,
index: anchorDomPoint.index,
length: this.yText.length - anchorDomPoint.index,
};
}
else {
const focusDomPoint = VEditor.textPointToDomPoint(focusText, focusTextOffset, this._rootElement);
if (!focusDomPoint) {
return null;
}
return {
index: anchorDomPoint.index,
length: anchorDomPoint.text.wholeText.length - anchorDomPoint.index,
index: 0,
length: focusDomPoint.index,
};
}
}
// case 2
if (!anchorText && focusText) {
const focusDomPoint = textPointToDomPoint(focusText, focusTextOffset, this._rootElement);
if (!focusDomPoint) {
return null;
}
// case 2.2
if (root.contains(anchorText) && !root.contains(focusText)) {
if (isSelectionBackwards(selection)) {
const focusDomPoint = VEditor.textPointToDomPoint(focusText, focusTextOffset, this._rootElement);
if (!focusDomPoint) {
return null;
}
return {
index: focusDomPoint.index,
length: focusDomPoint.text.wholeText.length - focusDomPoint.index,
index: 0,
length: focusDomPoint.index,
};
}
else {
const anchorDomPoint = VEditor.textPointToDomPoint(anchorText, anchorTextOffset, this._rootElement);
if (!anchorDomPoint) {
return null;
}
return {
index: 0,
length: focusDomPoint.index,
index: anchorDomPoint.index,
length: this.yText.length - anchorDomPoint.index,
};

@@ -415,5 +489,3 @@ }

// case 3
if (!anchorText &&
!focusText &&
selection.containsNode(this._rootElement)) {
if (!root.contains(anchorText) && !root.contains(focusText)) {
return {

@@ -514,32 +586,2 @@ index: 0,

}
function textPointToDomPoint(text, offset, rootElement) {
if (rootElement.dataset.virgoRoot !== 'true') {
throw new Error('textRangeToDomPoint should be called with editor root element');
}
if (!rootElement.contains(text)) {
throw new Error('text is not in root element');
}
const textNodes = Array.from(rootElement.querySelectorAll('[data-virgo-text="true"]')).map(textElement => getTextNodeFromElement(textElement));
const goalIndex = textNodes.indexOf(text);
let index = 0;
for (const textNode of textNodes.slice(0, goalIndex)) {
if (!textNode) {
return null;
}
index += calculateTextLength(textNode);
}
if (text.wholeText !== ZERO_WIDTH_SPACE) {
index += offset;
}
const textElement = text.parentElement;
if (!textElement) {
throw new Error('text element not found');
}
const lineElement = textElement.closest('virgo-line');
if (!lineElement) {
throw new Error('line element not found');
}
const lineIndex = Array.from(rootElement.querySelectorAll('virgo-line')).indexOf(lineElement);
return { text, index: index + lineIndex };
}
function isSelectionBackwards(selection) {

@@ -591,28 +633,2 @@ let backwards = false;

}
function getTextAndOffset(node, offset) {
let text = null;
let textOffset = offset;
if (isVText(node)) {
text = node;
textOffset = offset;
}
else if (isVElement(node)) {
const textNode = getTextNodeFromElement(node);
if (textNode) {
text = textNode;
textOffset = offset;
}
}
else if (isVLine(node)) {
const firstTextElement = node.querySelector('v-text');
if (firstTextElement) {
const textNode = getTextNodeFromElement(firstTextElement);
if (textNode) {
text = textNode;
textOffset = 0;
}
}
}
return [text, textOffset];
}
function findDocumentOrShadowRoot(editor) {

@@ -619,0 +635,0 @@ const el = editor.getRootElement();

{
"name": "@blocksuite/virgo",
"version": "0.5.0-20230228114851-7e82f3e",
"version": "0.5.0-20230301172958-2384904",
"description": "A micro editor.",

@@ -26,3 +26,3 @@ "main": "dist/index.js",

"dependencies": {
"@blocksuite/global": "0.5.0-20230228114851-7e82f3e",
"@blocksuite/global": "0.5.0-20230301172958-2384904",
"zod": "^3.20.6"

@@ -29,0 +29,0 @@ },

@@ -16,3 +16,2 @@ import { html, LitElement } from 'lit';

code: z.boolean().optional(),
link: z.string().optional(),
});

@@ -19,0 +18,0 @@

@@ -20,3 +20,3 @@ import { assertExists, Signal } from '@blocksuite/global/utils';

interface DomPoint {
export interface DomPoint {
// which text node this point is in

@@ -29,2 +29,85 @@ text: Text;

export class VEditor {
static nativePointToTextPoint(
node: unknown,
offset: number
): readonly [Text, number] | null {
let text: Text | null = null;
let textOffset = offset;
if (isVText(node)) {
text = node;
textOffset = offset;
} else if (isVElement(node)) {
const textNode = getTextNodeFromElement(node);
if (textNode) {
text = textNode;
textOffset = offset;
}
} else if (isVLine(node)) {
const firstTextElement = node.querySelector('v-text');
if (firstTextElement) {
const textNode = getTextNodeFromElement(firstTextElement);
if (textNode) {
text = textNode;
textOffset = 0;
}
}
}
if (!text) {
return null;
}
return [text, textOffset] as const;
}
static textPointToDomPoint(
text: Text,
offset: number,
rootElement: HTMLElement
): DomPoint | null {
if (rootElement.dataset.virgoRoot !== 'true') {
throw new Error(
'textRangeToDomPoint should be called with editor root element'
);
}
if (!rootElement.contains(text)) {
return null;
}
const textNodes = Array.from(
rootElement.querySelectorAll('[data-virgo-text="true"]')
).map(textElement => getTextNodeFromElement(textElement));
const goalIndex = textNodes.indexOf(text);
let index = 0;
for (const textNode of textNodes.slice(0, goalIndex)) {
if (!textNode) {
return null;
}
index += calculateTextLength(textNode);
}
if (text.wholeText !== ZERO_WIDTH_SPACE) {
index += offset;
}
const textElement = text.parentElement;
if (!textElement) {
throw new Error('text element not found');
}
const lineElement = textElement.closest('virgo-line');
if (!lineElement) {
throw new Error('line element not found');
}
const lineIndex = Array.from(
rootElement.querySelectorAll('virgo-line')
).indexOf(lineElement);
return { text, index: index + lineIndex };
}
private _rootElement: HTMLElement | null = null;

@@ -53,2 +136,6 @@ private _rootElementAbort: AbortController | null = null;

) {
if (!yText.doc) {
throw new Error('yText must be attached to a Y.Doc');
}
this.yText = yText;

@@ -408,2 +495,3 @@ const { renderElement, onKeyDown } = opts;

assertExists(this._rootElement);
const root = this._rootElement;

@@ -415,7 +503,7 @@ const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;

const [anchorText, anchorTextOffset] = getTextAndOffset(
const anchorTextPoint = VEditor.nativePointToTextPoint(
anchorNode,
anchorOffset
);
const [focusText, focusTextOffset] = getTextAndOffset(
const focusTextPoint = VEditor.nativePointToTextPoint(
focusNode,

@@ -425,5 +513,12 @@ focusOffset

if (!anchorTextPoint || !focusTextPoint) {
return null;
}
const [anchorText, anchorTextOffset] = anchorTextPoint;
const [focusText, focusTextOffset] = focusTextPoint;
// case 1
if (anchorText && focusText) {
const anchorDomPoint = textPointToDomPoint(
if (root.contains(anchorText) && root.contains(focusText)) {
const anchorDomPoint = VEditor.textPointToDomPoint(
anchorText,

@@ -433,3 +528,3 @@ anchorTextOffset,

);
const focusDomPoint = textPointToDomPoint(
const focusDomPoint = VEditor.textPointToDomPoint(
focusText,

@@ -450,23 +545,33 @@ focusTextOffset,

// case 2
if (anchorText && !focusText) {
const anchorDomPoint = textPointToDomPoint(
anchorText,
anchorTextOffset,
this._rootElement
);
// case 2.1
if (!root.contains(anchorText) && root.contains(focusText)) {
if (isSelectionBackwards(selection)) {
const anchorDomPoint = VEditor.textPointToDomPoint(
anchorText,
anchorTextOffset,
this._rootElement
);
if (!anchorDomPoint) {
return null;
}
if (!anchorDomPoint) {
return null;
}
if (isSelectionBackwards(selection)) {
return {
index: 0,
length: anchorDomPoint.index,
index: anchorDomPoint.index,
length: this.yText.length - anchorDomPoint.index,
};
} else {
const focusDomPoint = VEditor.textPointToDomPoint(
focusText,
focusTextOffset,
this._rootElement
);
if (!focusDomPoint) {
return null;
}
return {
index: anchorDomPoint.index,
length: anchorDomPoint.text.wholeText.length - anchorDomPoint.index,
index: 0,
length: focusDomPoint.index,
};

@@ -476,23 +581,33 @@ }

// case 2
if (!anchorText && focusText) {
const focusDomPoint = textPointToDomPoint(
focusText,
focusTextOffset,
this._rootElement
);
// case 2.2
if (root.contains(anchorText) && !root.contains(focusText)) {
if (isSelectionBackwards(selection)) {
const focusDomPoint = VEditor.textPointToDomPoint(
focusText,
focusTextOffset,
this._rootElement
);
if (!focusDomPoint) {
return null;
}
if (!focusDomPoint) {
return null;
}
if (isSelectionBackwards(selection)) {
return {
index: focusDomPoint.index,
length: focusDomPoint.text.wholeText.length - focusDomPoint.index,
index: 0,
length: focusDomPoint.index,
};
} else {
const anchorDomPoint = VEditor.textPointToDomPoint(
anchorText,
anchorTextOffset,
this._rootElement
);
if (!anchorDomPoint) {
return null;
}
return {
index: 0,
length: focusDomPoint.index,
index: anchorDomPoint.index,
length: this.yText.length - anchorDomPoint.index,
};

@@ -503,7 +618,3 @@ }

// case 3
if (
!anchorText &&
!focusText &&
selection.containsNode(this._rootElement)
) {
if (!root.contains(anchorText) && !root.contains(focusText)) {
return {

@@ -635,9 +746,4 @@ index: 0,

const { anchorNode, focusNode } = selection;
if (
!this._rootElement.contains(anchorNode) ||
!this._rootElement.contains(focusNode)
) {
return;
}
const range = selection.getRangeAt(0);
if (!range || !range.intersectsNode(this._rootElement)) return;

@@ -709,52 +815,2 @@ const vRange = this.toVRange(selection);

function textPointToDomPoint(
text: Text,
offset: number,
rootElement: HTMLElement
): DomPoint | null {
if (rootElement.dataset.virgoRoot !== 'true') {
throw new Error(
'textRangeToDomPoint should be called with editor root element'
);
}
if (!rootElement.contains(text)) {
throw new Error('text is not in root element');
}
const textNodes = Array.from(
rootElement.querySelectorAll('[data-virgo-text="true"]')
).map(textElement => getTextNodeFromElement(textElement));
const goalIndex = textNodes.indexOf(text);
let index = 0;
for (const textNode of textNodes.slice(0, goalIndex)) {
if (!textNode) {
return null;
}
index += calculateTextLength(textNode);
}
if (text.wholeText !== ZERO_WIDTH_SPACE) {
index += offset;
}
const textElement = text.parentElement;
if (!textElement) {
throw new Error('text element not found');
}
const lineElement = textElement.closest('virgo-line');
if (!lineElement) {
throw new Error('line element not found');
}
const lineIndex = Array.from(
rootElement.querySelectorAll('virgo-line')
).indexOf(lineElement);
return { text, index: index + lineIndex };
}
function isSelectionBackwards(selection: Selection): boolean {

@@ -821,28 +877,2 @@ let backwards = false;

function getTextAndOffset(node: unknown, offset: number) {
let text: Text | null = null;
let textOffset = offset;
if (isVText(node)) {
text = node;
textOffset = offset;
} else if (isVElement(node)) {
const textNode = getTextNodeFromElement(node);
if (textNode) {
text = textNode;
textOffset = offset;
}
} else if (isVLine(node)) {
const firstTextElement = node.querySelector('v-text');
if (firstTextElement) {
const textNode = getTextNodeFromElement(firstTextElement);
if (textNode) {
text = textNode;
textOffset = 0;
}
}
}
return [text, textOffset] as const;
}
function findDocumentOrShadowRoot(editor: VEditor): Document {

@@ -849,0 +879,0 @@ const el = editor.getRootElement();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc