1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-25 01:33:37 +01:00
slate/lib/utils/offset-key.js
Ian Storm Taylor 420d38edec bug fixing
2016-06-20 13:21:24 -07:00

100 lines
1.8 KiB
JavaScript

/**
* Offset key parser regex.
*/
const PARSER = /^(\w+)(?::(\d+)-(\d+))?$/
/**
* Offset key attribute name.
*/
const ATTRIBUTE = 'data-offset-key'
const SELECTOR = `[${ATTRIBUTE}]`
/**
* From a `node`, find the closest parent's offset key.
*
* @param {Node} node
* @return {String} key
*/
function findKey(node) {
if (node.nodeType == 3) node = node.parentNode
// If a parent with an offset key exists, use it.
const parent = node.closest(SELECTOR)
if (parent) return parent.getAttribute(ATTRIBUTE)
// Otherwise, if a child with an offset key exists, use it.
const child = node.querySelector(SELECTOR)
if (child) return child.getAttribute(ATTRIBUTE)
// Shouldn't get here... else we have an edge case to handle.
console.error('No offset key found for node:', node)
}
/**
* From a `node` and `offset`, find the closest parent's point.
*
* @param {Node} node
* @param {Offset} offset
* @return {String} key
*/
function findPoint(node, offset) {
const key = findKey(node)
const parsed = parse(key)
return {
key: parsed.key,
offset: parsed.start + offset
}
}
/**
* Parse an offset key `string`.
*
* @param {String} string
* @return {Object} parsed
*/
function parse(string) {
const matches = PARSER.exec(string)
if (!matches) throw new Error(`Invalid offset key string "${string}".`)
let [ original, key, start, end ] = matches
start = parseInt(start, 10)
end = parseInt(end, 10)
return {
key,
start,
end
}
}
/**
* Stringify an offset key `object`.
*
* @param {Object} object
* @property {String} key
* @property {Number} start
* @property {Number} end
* @return {String} key
*/
function stringify(object) {
return `${object.key}:${object.start}-${object.end}`
}
/**
* Export.
*/
export default {
findKey,
findPoint,
parse,
stringify
}