@linalgo/annotate-core
Advanced tools
Comparing version
@@ -16,1 +16,11 @@ import { Selection } from '../selectors'; | ||
export declare function isAnnotation(obj: any): obj is Annotation; | ||
export interface AnnotationType { | ||
id?: string; | ||
title?: string; | ||
description?: string; | ||
color?: string; | ||
icon_name?: string; | ||
type_name?: string; | ||
flashcard_type?: string; | ||
action?: string; | ||
} |
import { Selection } from '../selectors'; | ||
import { Annotation } from './annotation'; | ||
import { Annotation, AnnotationType } from './annotation'; | ||
export declare class Annotator { | ||
private rootNode; | ||
private tag; | ||
schema: AnnotationType[]; | ||
colorSchema: { | ||
[id: string]: string; | ||
}; | ||
annotationMap: { | ||
@@ -11,3 +16,5 @@ [id: string]: Annotation; | ||
}; | ||
constructor(tag: string); | ||
constructor(rootNode?: Node, tag?: string); | ||
setRoot(rootNode: Node): void; | ||
setSchema(schema: AnnotationType[]): void; | ||
getTextNodes(node: Node): Node[]; | ||
@@ -14,0 +21,0 @@ getSubRanges(range: Range): Range[]; |
@@ -6,7 +6,21 @@ "use strict"; | ||
var Annotator = /** @class */ (function () { | ||
function Annotator(tag) { | ||
function Annotator(rootNode, tag) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
if (tag === void 0) { tag = 'span'; } | ||
this.rootNode = rootNode; | ||
this.tag = tag; | ||
this.colorSchema = {}; | ||
this.annotationMap = {}; | ||
this.nodeMap = {}; | ||
} | ||
Annotator.prototype.setRoot = function (rootNode) { | ||
this.rootNode = rootNode; | ||
}; | ||
Annotator.prototype.setSchema = function (schema) { | ||
this.schema = schema; | ||
for (var _i = 0, _a = this.schema; _i < _a.length; _i++) { | ||
var entity = _a[_i]; | ||
this.colorSchema[entity.id] = entity.color; | ||
} | ||
}; | ||
Annotator.prototype.getTextNodes = function (node) { | ||
@@ -57,3 +71,3 @@ var textNodes = []; | ||
if (body === void 0) { body = null; } | ||
var selector = selectors_1.SelectorFactory.getBestSelector(rs, this.tag); | ||
var selector = selectors_1.SelectorFactory.getBestSelector(rs, this.rootNode, this.tag); | ||
if (!body) { | ||
@@ -78,4 +92,4 @@ body = rs.toString(); | ||
var selection = annotation.target.selector[0]; | ||
var selector = selectors_1.SelectorFactory.getBestSelector(selection, this.tag); | ||
var range = selector.rangeFromSelection(selection); | ||
var selector = selectors_1.SelectorFactory.getBestSelector(selection, this.rootNode, this.tag); | ||
var range = selector.range; | ||
var newNodes = []; | ||
@@ -86,2 +100,3 @@ for (var _i = 0, _a = this.getSubRanges(range); _i < _a.length; _i++) { | ||
newNode.setAttribute('annotation', annotation.id); | ||
newNode.style.backgroundColor = "#" + this.colorSchema[annotation.entity]; | ||
subRange.surroundContents(newNode); | ||
@@ -88,0 +103,0 @@ newNodes.push(newNode); |
@@ -14,5 +14,5 @@ "use strict"; | ||
// }); | ||
// const annotator = new Annotator('b'); | ||
// const annotator = new Annotator(document, 'b'); | ||
// function highlight(range: Range) { | ||
// const annotation = annotator.createAnnotation(range); | ||
// const annotation = annotator.createAnnotation(range, 'test', 'test', document.URL, 'test'); | ||
// annotator.showAnnotation(annotation); | ||
@@ -19,0 +19,0 @@ // console.log(JSON.stringify(annotation)); |
import { Selection } from "./selection"; | ||
import { Selector } from "./selector"; | ||
export declare class SelectorFactory { | ||
static getBestSelector(rs: Range | Selection, ignoreNodeName: string): Selector; | ||
static getBestSelector(rs: Range | Selection, rootNode: Node, ignoreNodeName: string): Selector; | ||
} |
@@ -9,11 +9,12 @@ "use strict"; | ||
} | ||
SelectorFactory.getBestSelector = function (rs, ignoreNodeName) { | ||
SelectorFactory.getBestSelector = function (rs, rootNode, ignoreNodeName) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
if (rs instanceof Range) { | ||
return new xpath_selector_1.XPathSelector(rs, ignoreNodeName); | ||
return new xpath_selector_1.XPathSelector(rs, rootNode, ignoreNodeName); | ||
} | ||
else if (selection_1.isXPathSelection(rs)) { | ||
return new xpath_selector_1.XPathSelector(rs, ignoreNodeName); | ||
return new xpath_selector_1.XPathSelector(rs, rootNode, ignoreNodeName); | ||
} | ||
else if (selection_1.isTextPositionSelection(rs)) { | ||
return new text_position_selector_1.TextPositionSelector(rs, ignoreNodeName); | ||
return new text_position_selector_1.TextPositionSelector(rs, rootNode, ignoreNodeName); | ||
} | ||
@@ -20,0 +21,0 @@ else { |
import { Selection } from './selection'; | ||
export declare abstract class Selector { | ||
rootNode: Node; | ||
range: Range; | ||
selection: Selection; | ||
ignoreNodeName: string; | ||
constructor(rs?: Range | Selection, ignoreNodeName?: string); | ||
abstract selectionFromRange(range: Range): Selection; | ||
abstract rangeFromSelection(selection: Selection): Range; | ||
constructor(rs?: Range | Selection, rootNode?: Node, ignoreNodeName?: string); | ||
abstract selectionFromRange(range: Range, rootNode: Node): Selection; | ||
abstract rangeFromSelection(selection: Selection, rootNode: Node): Range; | ||
} |
@@ -5,10 +5,14 @@ "use strict"; | ||
var Selector = /** @class */ (function () { | ||
function Selector(rs, ignoreNodeName) { | ||
function Selector(rs, rootNode, ignoreNodeName) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
if (ignoreNodeName === void 0) { ignoreNodeName = null; } | ||
this.ignoreNodeName = ignoreNodeName; | ||
this.rootNode = rootNode; | ||
if (rs instanceof Range) { | ||
this.selectionFromRange(rs); | ||
this.range = rs; | ||
this.selectionFromRange(rs, rootNode); | ||
} | ||
else if (selection_1.isSelection(rs)) { | ||
this.rangeFromSelection(rs); | ||
this.selection = rs; | ||
this.rangeFromSelection(rs, rootNode); | ||
} | ||
@@ -15,0 +19,0 @@ } |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
@@ -7,0 +10,0 @@ extendStatics(d, b); |
import { XPathSelection } from './selection'; | ||
import { Selector } from './selector'; | ||
export declare class XPathSelector extends Selector { | ||
selectionFromRange(range: Range): XPathSelection; | ||
rangeFromSelection(selection: XPathSelection): Range; | ||
selectionFromRange(range: Range, rootNode?: Node): XPathSelection; | ||
rangeFromSelection(selection: XPathSelection, rootNode?: Node): Range; | ||
} |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
@@ -19,7 +22,8 @@ extendStatics(d, b); | ||
} | ||
XPathSelector.prototype.selectionFromRange = function (range) { | ||
XPathSelector.prototype.selectionFromRange = function (range, rootNode) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
this.range = range; | ||
this.selection = { | ||
startContainer: getPathTo(range.startContainer, document, this.ignoreNodeName), | ||
endContainer: getPathTo(range.endContainer, document, this.ignoreNodeName), | ||
startContainer: getPathTo(range.startContainer, rootNode, this.ignoreNodeName), | ||
endContainer: getPathTo(range.endContainer, rootNode, this.ignoreNodeName), | ||
startOffset: getNormalizedOffset(range.startContainer, range.startOffset, this.ignoreNodeName), | ||
@@ -30,9 +34,10 @@ endOffset: getNormalizedOffset(range.endContainer, range.endOffset, this.ignoreNodeName) | ||
}; | ||
XPathSelector.prototype.rangeFromSelection = function (selection) { | ||
XPathSelector.prototype.rangeFromSelection = function (selection, rootNode) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
this.selection = selection; | ||
var range = document.createRange(); | ||
try { | ||
var _a = findOriginalNodeAndOffset(selection.startContainer, selection.startOffset), node = _a.node, offset = _a.offset; | ||
var _a = findOriginalNodeAndOffset(selection.startContainer, selection.startOffset, rootNode, this.ignoreNodeName), node = _a.node, offset = _a.offset; | ||
range.setStart(node, offset); | ||
var _b = findOriginalNodeAndOffset(selection.endContainer, selection.endOffset), node = _b.node, offset = _b.offset; | ||
var _b = findOriginalNodeAndOffset(selection.endContainer, selection.endOffset, rootNode, this.ignoreNodeName), node = _b.node, offset = _b.offset; | ||
range.setEnd(node, offset); | ||
@@ -77,3 +82,3 @@ this.range = range; | ||
var path = ''; | ||
while (node !== fromNode) { | ||
while (!node.isSameNode(fromNode)) { | ||
if (node.nodeType != Node.TEXT_NODE && nodeName(node) !== ignoreNodeName) { | ||
@@ -86,4 +91,4 @@ path = "/" + nodeName(node) + "[" + nodePosition(node) + "]" + path; | ||
} | ||
function findOriginalNodeAndOffset(path, offset) { | ||
var container = findNode(path); | ||
function findOriginalNodeAndOffset(path, offset, rootNode, ignoreNodeName) { | ||
var container = findNode(path, rootNode, ignoreNodeName); | ||
var newOffset = 0; | ||
@@ -118,6 +123,9 @@ for (var _i = 0, _a = getTextNodes(container); _i < _a.length; _i++) { | ||
} | ||
function findNode(path) { | ||
var query = document.evaluate(path, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null); | ||
function findNode(path, rootNode, ignoreNodeName) { | ||
if (rootNode === void 0) { rootNode = document; } | ||
var prefix = getPathTo(rootNode, document, ignoreNodeName); | ||
var newPath = prefix.concat(path.slice(1, path.length)); | ||
var query = document.evaluate(newPath, rootNode, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null); | ||
return query.singleNodeValue; | ||
} | ||
//# sourceMappingURL=xpath-selector.js.map |
{ | ||
"name": "@linalgo/annotate-core", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"description": "A library for html document annotations following W3C standards.", | ||
@@ -28,3 +28,3 @@ "main": "./dist/index.js", | ||
"ts-loader": "^4.2.0", | ||
"typescript": "^2.8.3", | ||
"typescript": "^3.5.1", | ||
"uuid": "^3.3.2" | ||
@@ -31,0 +31,0 @@ }, |
@@ -19,2 +19,13 @@ import { Selection } from '../selectors'; | ||
return obj.type && obj.target; | ||
} | ||
export interface AnnotationType { | ||
id?: string; | ||
title?: string; | ||
description?: string; | ||
color?: string; | ||
icon_name?: string; | ||
type_name?: string; | ||
flashcard_type?: string; | ||
action?: string; | ||
} |
import * as uuid from 'uuid'; | ||
import { Selection, SelectorFactory } from '../selectors' | ||
import { Annotation } from './annotation'; | ||
import { Annotation, AnnotationType } from './annotation'; | ||
export class Annotator { | ||
schema: AnnotationType[]; | ||
colorSchema: { [id: string]: string } = {}; | ||
annotationMap: { [id: string]: Annotation } = {}; | ||
nodeMap: { [id: string]: Node[] } = {}; | ||
constructor(private tag: string) { } | ||
constructor(private rootNode: Node = document, private tag: string = 'span') { } | ||
setRoot(rootNode: Node) { | ||
this.rootNode = rootNode; | ||
} | ||
setSchema(schema: AnnotationType[]) { | ||
this.schema = schema; | ||
for (const entity of this.schema) { | ||
this.colorSchema[entity.id] = entity.color; | ||
} | ||
} | ||
getTextNodes(node: Node) { | ||
@@ -55,3 +68,3 @@ const textNodes = []; | ||
createAnnotation(rs: Range | Selection, task: string, entity: string, document: string, body: string = null): Annotation { | ||
let selector = SelectorFactory.getBestSelector(rs, this.tag); | ||
let selector = SelectorFactory.getBestSelector(rs, this.rootNode, this.tag); | ||
if (!body) { | ||
@@ -77,4 +90,4 @@ body = rs.toString(); | ||
const selection = annotation.target.selector[0]; | ||
const selector = SelectorFactory.getBestSelector(selection, this.tag); | ||
const range = selector.rangeFromSelection(selection); | ||
const selector = SelectorFactory.getBestSelector(selection, this.rootNode, this.tag); | ||
const range = selector.range; | ||
const newNodes: Node[] = []; | ||
@@ -84,2 +97,3 @@ for (const subRange of this.getSubRanges(range)) { | ||
newNode.setAttribute('annotation', annotation.id); | ||
newNode.style.backgroundColor = `#${this.colorSchema[annotation.entity]}`; | ||
subRange.surroundContents(newNode); | ||
@@ -86,0 +100,0 @@ newNodes.push(newNode); |
@@ -12,5 +12,5 @@ export * from './annotators'; | ||
// const annotator = new Annotator('b'); | ||
// const annotator = new Annotator(document, 'b'); | ||
// function highlight(range: Range) { | ||
// const annotation = annotator.createAnnotation(range); | ||
// const annotation = annotator.createAnnotation(range, 'test', 'test', document.URL, 'test'); | ||
// annotator.showAnnotation(annotation); | ||
@@ -17,0 +17,0 @@ // console.log(JSON.stringify(annotation)); |
@@ -8,9 +8,9 @@ import { XPathSelector } from "./xpath-selector"; | ||
static getBestSelector(rs: Range | Selection, ignoreNodeName: string): Selector { | ||
static getBestSelector(rs: Range | Selection, rootNode: Node = document, ignoreNodeName: string): Selector { | ||
if (rs instanceof Range) { | ||
return new XPathSelector(rs, ignoreNodeName); | ||
return new XPathSelector(rs, rootNode, ignoreNodeName); | ||
} else if (isXPathSelection(rs)) { | ||
return new XPathSelector(rs, ignoreNodeName); | ||
return new XPathSelector(rs, rootNode, ignoreNodeName); | ||
} else if (isTextPositionSelection(rs)) { | ||
return new TextPositionSelector(rs, ignoreNodeName); | ||
return new TextPositionSelector(rs, rootNode, ignoreNodeName); | ||
} else { | ||
@@ -17,0 +17,0 @@ throw new Error('Range or Selection only.') |
@@ -5,2 +5,3 @@ import { Selection, isSelection } from './selection'; | ||
export abstract class Selector { | ||
rootNode: Node; | ||
range: Range; | ||
@@ -10,14 +11,17 @@ selection: Selection; | ||
constructor(rs?: Range | Selection, ignoreNodeName: string = null) { | ||
constructor(rs?: Range | Selection, rootNode: Node = document, ignoreNodeName: string = null) { | ||
this.ignoreNodeName = ignoreNodeName; | ||
this.rootNode = rootNode; | ||
if (rs instanceof Range) { | ||
this.selectionFromRange(rs); | ||
this.range = rs; | ||
this.selectionFromRange(rs, rootNode); | ||
} else if (isSelection(rs)) { | ||
this.rangeFromSelection(rs); | ||
this.selection = rs; | ||
this.rangeFromSelection(rs, rootNode); | ||
} | ||
} | ||
abstract selectionFromRange(range: Range): Selection; | ||
abstract rangeFromSelection(selection: Selection): Range; | ||
abstract selectionFromRange(range: Range, rootNode: Node): Selection; | ||
abstract rangeFromSelection(selection: Selection, rootNode: Node): Range; | ||
} |
@@ -6,7 +6,7 @@ import { XPathSelection } from './selection'; | ||
selectionFromRange(range: Range): XPathSelection { | ||
selectionFromRange(range: Range, rootNode: Node = document): XPathSelection { | ||
this.range = range; | ||
this.selection = { | ||
startContainer: getPathTo(range.startContainer, document, this.ignoreNodeName), | ||
endContainer: getPathTo(range.endContainer, document, this.ignoreNodeName), | ||
startContainer: getPathTo(range.startContainer, rootNode, this.ignoreNodeName), | ||
endContainer: getPathTo(range.endContainer, rootNode, this.ignoreNodeName), | ||
startOffset: getNormalizedOffset(range.startContainer, range.startOffset, this.ignoreNodeName), | ||
@@ -18,9 +18,9 @@ endOffset: getNormalizedOffset(range.endContainer, range.endOffset, this.ignoreNodeName) | ||
rangeFromSelection(selection: XPathSelection): Range { | ||
rangeFromSelection(selection: XPathSelection, rootNode: Node = document): Range { | ||
this.selection = selection | ||
let range = document.createRange(); | ||
try { | ||
var { node, offset } = findOriginalNodeAndOffset(selection.startContainer, selection.startOffset); | ||
var { node, offset } = findOriginalNodeAndOffset(selection.startContainer, selection.startOffset, rootNode, this.ignoreNodeName); | ||
range.setStart(node, offset); | ||
var { node, offset } = findOriginalNodeAndOffset(selection.endContainer, selection.endOffset); | ||
var { node, offset } = findOriginalNodeAndOffset(selection.endContainer, selection.endOffset, rootNode, this.ignoreNodeName); | ||
range.setEnd(node, offset); | ||
@@ -65,3 +65,3 @@ this.range = range; | ||
let path = ''; | ||
while (node !== fromNode) { | ||
while (!node.isSameNode(fromNode)) { | ||
if (node.nodeType != Node.TEXT_NODE && nodeName(node) !== ignoreNodeName) { | ||
@@ -75,4 +75,4 @@ path = `/${nodeName(node)}[${nodePosition(node)}]${path}`; | ||
function findOriginalNodeAndOffset(path: string, offset: number) { | ||
const container = findNode(path); | ||
function findOriginalNodeAndOffset(path: string, offset: number, rootNode: Node, ignoreNodeName: string) { | ||
const container = findNode(path, rootNode, ignoreNodeName); | ||
let newOffset = 0 | ||
@@ -105,5 +105,7 @@ for (const node of getTextNodes(container)) { | ||
function findNode(path: string): Node { | ||
let query = document.evaluate(path, document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null) | ||
function findNode(path: string, rootNode: Node = document, ignoreNodeName: string): Node { | ||
const prefix = getPathTo(rootNode, document, ignoreNodeName); | ||
let newPath = prefix.concat(path.slice(1, path.length)); | ||
let query = document.evaluate(newPath, rootNode, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null) | ||
return query.singleNodeValue | ||
} |
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
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
674573
0.7%1093
7.58%0
-100%+ Added
- Removed
Updated