devstar插件

This commit is contained in:
2025-07-26 16:40:29 +08:00
commit 30033daafe
4387 changed files with 1041101 additions and 0 deletions

21
node_modules/mark.js/src/jquery.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import Mark from './lib/mark';
import $ from 'jquery';
$.fn.mark = function(sv, opt) {
new Mark(this.get()).mark(sv, opt);
return this;
};
$.fn.markRegExp = function(regexp, opt) {
new Mark(this.get()).markRegExp(regexp, opt);
return this;
};
$.fn.markRanges = function(ranges, opt) {
new Mark(this.get()).markRanges(ranges, opt);
return this;
};
$.fn.unmark = function(opt) {
new Mark(this.get()).unmark(opt);
return this;
};
export default $;

569
node_modules/mark.js/src/lib/domiterator.js generated vendored Normal file
View File

@@ -0,0 +1,569 @@
/**
* A NodeIterator with iframes support and a method to check if an element is
* matching a specified selector
* @example
* const iterator = new DOMIterator(
* document.querySelector("#context"), true
* );
* iterator.forEachNode(NodeFilter.SHOW_TEXT, node => {
* console.log(node);
* }, node => {
* if(DOMIterator.matches(node.parentNode, ".ignore")){
* return NodeFilter.FILTER_REJECT;
* } else {
* return NodeFilter.FILTER_ACCEPT;
* }
* }, () => {
* console.log("DONE");
* });
* @todo Outsource into separate repository
*/
export default class DOMIterator {
/**
* @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM
* element, an array of DOM elements, a NodeList or a selector
* @param {boolean} [iframes=true] - A boolean indicating if iframes should
* be handled
* @param {string[]} [exclude=[]] - An array containing exclusion selectors
* for iframes
* @param {number} [iframesTimeout=5000] - A number indicating the ms to
* wait before an iframe should be skipped, in case the load event isn't
* fired. This also applies if the user is offline and the resource of the
* iframe is online (either by the browsers "offline" mode or because
* there's no internet connection)
*/
constructor(ctx, iframes = true, exclude = [], iframesTimeout = 5000) {
/**
* The context of the instance. Either a DOM element, an array of DOM
* elements, a NodeList or a selector
* @type {HTMLElement|HTMLElement[]|NodeList|string}
* @access protected
*/
this.ctx = ctx;
/**
* Boolean indicating if iframe support is enabled
* @type {boolean}
* @access protected
*/
this.iframes = iframes;
/**
* An array containing exclusion selectors for iframes
* @type {string[]}
*/
this.exclude = exclude;
/**
* The maximum ms to wait for a load event before skipping an iframe
* @type {number}
*/
this.iframesTimeout = iframesTimeout;
}
/**
* Checks if the specified DOM element matches the selector
* @param {HTMLElement} element - The DOM element
* @param {string|string[]} selector - The selector or an array with
* selectors
* @return {boolean}
* @access public
*/
static matches(element, selector) {
const selectors = typeof selector === 'string' ? [selector] : selector,
fn = (
element.matches ||
element.matchesSelector ||
element.msMatchesSelector ||
element.mozMatchesSelector ||
element.oMatchesSelector ||
element.webkitMatchesSelector
);
if (fn) {
let match = false;
selectors.every(sel => {
if (fn.call(element, sel)) {
match = true;
return false;
}
return true;
});
return match;
} else { // may be false e.g. when el is a textNode
return false;
}
}
/**
* Returns all contexts filtered by duplicates (even nested)
* @return {HTMLElement[]} - An array containing DOM contexts
* @access protected
*/
getContexts() {
let ctx,
filteredCtx = [];
if (typeof this.ctx === 'undefined' || !this.ctx) { // e.g. null
ctx = [];
} else if (NodeList.prototype.isPrototypeOf(this.ctx)) {
ctx = Array.prototype.slice.call(this.ctx);
} else if (Array.isArray(this.ctx)) {
ctx = this.ctx;
} else if (typeof this.ctx === 'string') {
ctx = Array.prototype.slice.call(
document.querySelectorAll(this.ctx)
);
} else { // e.g. HTMLElement or element inside iframe
ctx = [this.ctx];
}
// filter duplicate text nodes
ctx.forEach(ctx => {
const isDescendant = filteredCtx.filter(contexts => {
return contexts.contains(ctx);
}).length > 0;
if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) {
filteredCtx.push(ctx);
}
});
return filteredCtx;
}
/**
* @callback DOMIterator~getIframeContentsSuccessCallback
* @param {HTMLDocument} contents - The contentDocument of the iframe
*/
/**
* Calls the success callback function with the iframe document. If it can't
* be accessed it calls the error callback function
* @param {HTMLElement} ifr - The iframe DOM element
* @param {DOMIterator~getIframeContentsSuccessCallback} successFn
* @param {function} [errorFn]
* @access protected
*/
getIframeContents(ifr, successFn, errorFn = () => {}) {
let doc;
try {
const ifrWin = ifr.contentWindow;
doc = ifrWin.document;
if (!ifrWin || !doc) { // no permission = null. Undefined in Phantom
throw new Error('iframe inaccessible');
}
} catch (e) {
errorFn();
}
if (doc) {
successFn(doc);
}
}
/**
* Checks if an iframe is empty (if about:blank is the shown page)
* @param {HTMLElement} ifr - The iframe DOM element
* @return {boolean}
* @access protected
*/
isIframeBlank(ifr) {
const bl = 'about:blank',
src = ifr.getAttribute('src').trim(),
href = ifr.contentWindow.location.href;
return href === bl && src !== bl && src;
}
/**
* Observes the onload event of an iframe and calls the success callback or
* the error callback if the iframe is inaccessible. If the event isn't
* fired within the specified {@link DOMIterator#iframesTimeout}, then it'll
* call the error callback too
* @param {HTMLElement} ifr - The iframe DOM element
* @param {DOMIterator~getIframeContentsSuccessCallback} successFn
* @param {function} errorFn
* @access protected
*/
observeIframeLoad(ifr, successFn, errorFn) {
let called = false,
tout = null;
const listener = () => {
if (called) {
return;
}
called = true;
clearTimeout(tout);
try {
if (!this.isIframeBlank(ifr)) {
ifr.removeEventListener('load', listener);
this.getIframeContents(ifr, successFn, errorFn);
}
} catch (e) { // isIframeBlank maybe throws throws an error
errorFn();
}
};
ifr.addEventListener('load', listener);
tout = setTimeout(listener, this.iframesTimeout);
}
/**
* Callback when the iframe is ready
* @callback DOMIterator~onIframeReadySuccessCallback
* @param {HTMLDocument} contents - The contentDocument of the iframe
*/
/**
* Callback if the iframe can't be accessed
* @callback DOMIterator~onIframeReadyErrorCallback
*/
/**
* Calls the callback if the specified iframe is ready for DOM access
* @param {HTMLElement} ifr - The iframe DOM element
* @param {DOMIterator~onIframeReadySuccessCallback} successFn - Success
* callback
* @param {DOMIterator~onIframeReadyErrorCallback} errorFn - Error callback
* @see {@link http://stackoverflow.com/a/36155560/3894981} for
* background information
* @access protected
*/
onIframeReady(ifr, successFn, errorFn) {
try {
if (ifr.contentWindow.document.readyState === 'complete') {
if (this.isIframeBlank(ifr)) {
this.observeIframeLoad(ifr, successFn, errorFn);
} else {
this.getIframeContents(ifr, successFn, errorFn);
}
} else {
this.observeIframeLoad(ifr, successFn, errorFn);
}
} catch (e) { // accessing document failed
errorFn();
}
}
/**
* Callback when all iframes are ready for DOM access
* @callback DOMIterator~waitForIframesDoneCallback
*/
/**
* Iterates over all iframes and calls the done callback when all of them
* are ready for DOM access (including nested ones)
* @param {HTMLElement} ctx - The context DOM element
* @param {DOMIterator~waitForIframesDoneCallback} done - Done callback
*/
waitForIframes(ctx, done) {
let eachCalled = 0;
this.forEachIframe(ctx, () => true, ifr => {
eachCalled++;
this.waitForIframes(ifr.querySelector('html'), () => {
if (!(--eachCalled)) {
done();
}
});
}, handled => {
if (!handled) {
done();
}
});
}
/**
* Callback allowing to filter an iframe. Must return true when the element
* should remain, otherwise false
* @callback DOMIterator~forEachIframeFilterCallback
* @param {HTMLElement} iframe - The iframe DOM element
*/
/**
* Callback for each iframe content
* @callback DOMIterator~forEachIframeEachCallback
* @param {HTMLElement} content - The iframe document
*/
/**
* Callback if all iframes inside the context were handled
* @callback DOMIterator~forEachIframeEndCallback
* @param {number} handled - The number of handled iframes (those who
* wheren't filtered)
*/
/**
* Iterates over all iframes inside the specified context and calls the
* callbacks when they're ready. Filters iframes based on the instance
* exclusion selectors
* @param {HTMLElement} ctx - The context DOM element
* @param {DOMIterator~forEachIframeFilterCallback} filter - Filter callback
* @param {DOMIterator~forEachIframeEachCallback} each - Each callback
* @param {DOMIterator~forEachIframeEndCallback} [end] - End callback
* @access protected
*/
forEachIframe(ctx, filter, each, end = () => {}) {
let ifr = ctx.querySelectorAll('iframe'),
open = ifr.length,
handled = 0;
ifr = Array.prototype.slice.call(ifr);
const checkEnd = () => {
if (--open <= 0) {
end(handled);
}
};
if (!open) {
checkEnd();
}
ifr.forEach(ifr => {
if (DOMIterator.matches(ifr, this.exclude)) {
checkEnd();
} else {
this.onIframeReady(ifr, con => {
if (filter(ifr)) {
handled++;
each(con);
}
checkEnd();
}, checkEnd);
}
});
}
/**
* Creates a NodeIterator on the specified context
* @see {@link https://developer.mozilla.org/en/docs/Web/API/NodeIterator}
* @param {HTMLElement} ctx - The context DOM element
* @param {DOMIterator~whatToShow} whatToShow
* @param {DOMIterator~filterCb} filter
* @return {NodeIterator}
* @access protected
*/
createIterator(ctx, whatToShow, filter) {
return document.createNodeIterator(ctx, whatToShow, filter, false);
}
/**
* Creates an instance of DOMIterator in an iframe
* @param {HTMLDocument} contents - Iframe document
* @return {DOMIterator}
* @access protected
*/
createInstanceOnIframe(contents) {
return new DOMIterator(contents.querySelector('html'), this.iframes);
}
/**
* Checks if an iframe occurs between two nodes, more specifically if an
* iframe occurs before the specified node and after the specified prevNode
* @param {HTMLElement} node - The node that should occur after the iframe
* @param {HTMLElement} prevNode - The node that should occur before the
* iframe
* @param {HTMLElement} ifr - The iframe to check against
* @return {boolean}
* @access protected
*/
compareNodeIframe(node, prevNode, ifr) {
const compCurr = node.compareDocumentPosition(ifr),
prev = Node.DOCUMENT_POSITION_PRECEDING;
if (compCurr & prev) {
if (prevNode !== null) {
const compPrev = prevNode.compareDocumentPosition(ifr),
after = Node.DOCUMENT_POSITION_FOLLOWING;
if (compPrev & after) {
return true;
}
} else {
return true;
}
}
return false;
}
/**
* @typedef {DOMIterator~getIteratorNodeReturn}
* @type {object.<string>}
* @property {HTMLElement} prevNode - The previous node or null if there is
* no
* @property {HTMLElement} node - The current node
*/
/**
* Returns the previous and current node of the specified iterator
* @param {NodeIterator} itr - The iterator
* @return {DOMIterator~getIteratorNodeReturn}
* @access protected
*/
getIteratorNode(itr) {
const prevNode = itr.previousNode();
let node;
if (prevNode === null) {
node = itr.nextNode();
} else {
node = itr.nextNode() && itr.nextNode();
}
return {
prevNode,
node
};
}
/**
* An array containing objects. The object key "val" contains an iframe
* DOM element. The object key "handled" contains a boolean indicating if
* the iframe was handled already.
* It wouldn't be enough to save all open or all already handled iframes.
* The information of open iframes is necessary because they may occur after
* all other text nodes (and compareNodeIframe would never be true). The
* information of already handled iframes is necessary as otherwise they may
* be handled multiple times
* @typedef DOMIterator~checkIframeFilterIfr
* @type {object[]}
*/
/**
* Checks if an iframe wasn't handled already and if so, calls
* {@link DOMIterator#compareNodeIframe} to check if it should be handled.
* Information wheter an iframe was or wasn't handled is given within the
* <code>ifr</code> dictionary
* @param {HTMLElement} node - The node that should occur after the iframe
* @param {HTMLElement} prevNode - The node that should occur before the
* iframe
* @param {HTMLElement} currIfr - The iframe to check
* @param {DOMIterator~checkIframeFilterIfr} ifr - The iframe dictionary.
* Will be manipulated (by reference)
* @return {boolean} Returns true when it should be handled, otherwise false
* @access protected
*/
checkIframeFilter(node, prevNode, currIfr, ifr) {
let key = false, // false === doesn't exist
handled = false;
ifr.forEach((ifrDict, i) => {
if (ifrDict.val === currIfr) {
key = i;
handled = ifrDict.handled;
}
});
if (this.compareNodeIframe(node, prevNode, currIfr)) {
if (key === false && !handled) {
ifr.push({
val: currIfr,
handled: true
});
} else if (key !== false && !handled) {
ifr[key].handled = true;
}
return true;
}
if (key === false) {
ifr.push({
val: currIfr,
handled: false
});
}
return false;
}
/**
* Creates an iterator on all open iframes in the specified array and calls
* the end callback when finished
* @param {DOMIterator~checkIframeFilterIfr} ifr
* @param {DOMIterator~whatToShow} whatToShow
* @param {DOMIterator~forEachNodeCallback} eCb - Each callback
* @param {DOMIterator~filterCb} fCb
* @access protected
*/
handleOpenIframes(ifr, whatToShow, eCb, fCb) {
ifr.forEach(ifrDict => {
if (!ifrDict.handled) {
this.getIframeContents(ifrDict.val, con => {
this.createInstanceOnIframe(con).forEachNode(
whatToShow, eCb, fCb
);
});
}
});
}
/**
* Iterates through all nodes in the specified context and handles iframe
* nodes at the correct position
* @param {DOMIterator~whatToShow} whatToShow
* @param {HTMLElement} ctx - The context
* @param {DOMIterator~forEachNodeCallback} eachCb - Each callback
* @param {DOMIterator~filterCb} filterCb - Filter callback
* @param {DOMIterator~forEachNodeEndCallback} doneCb - End callback
* @access protected
*/
iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) {
const itr = this.createIterator(ctx, whatToShow, filterCb);
let ifr = [],
elements = [],
node, prevNode, retrieveNodes = () => {
({
prevNode,
node
} = this.getIteratorNode(itr));
return node;
};
while (retrieveNodes()) {
if (this.iframes) {
this.forEachIframe(ctx, currIfr => {
// note that ifr will be manipulated here
return this.checkIframeFilter(node, prevNode, currIfr, ifr);
}, con => {
this.createInstanceOnIframe(con).forEachNode(
whatToShow, ifrNode => elements.push(ifrNode), filterCb
);
});
}
// it's faster to call the each callback in an array loop
// than in this while loop
elements.push(node);
}
elements.forEach(node => {
eachCb(node);
});
if (this.iframes) {
this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb);
}
doneCb();
}
/**
* Callback for each node
* @callback DOMIterator~forEachNodeCallback
* @param {HTMLElement} node - The DOM text node element
*/
/**
* Callback if all contexts were handled
* @callback DOMIterator~forEachNodeEndCallback
*/
/**
* Iterates over all contexts and initializes
* {@link DOMIterator#iterateThroughNodes iterateThroughNodes} on them
* @param {DOMIterator~whatToShow} whatToShow
* @param {DOMIterator~forEachNodeCallback} each - Each callback
* @param {DOMIterator~filterCb} filter - Filter callback
* @param {DOMIterator~forEachNodeEndCallback} done - End callback
* @access public
*/
forEachNode(whatToShow, each, filter, done = () => {}) {
const contexts = this.getContexts();
let open = contexts.length;
if (!open) {
done();
}
contexts.forEach(ctx => {
const ready = () => {
this.iterateThroughNodes(whatToShow, ctx, each, filter, () => {
if (--open <= 0) { // call end all contexts were handled
done();
}
});
};
// wait for iframes to avoid recursive calls, otherwise this would
// perhaps reach the recursive function call limit with many nodes
if (this.iframes) {
this.waitForIframes(ctx, ready);
} else {
ready();
}
});
}
/**
* Callback to filter nodes. Can return e.g. NodeFilter.FILTER_ACCEPT or
* NodeFilter.FILTER_REJECT
* @see {@link http://tinyurl.com/zdczmm2}
* @callback DOMIterator~filterCb
* @param {HTMLElement} node - The node to filter
*/
/**
* @typedef DOMIterator~whatToShow
* @see {@link http://tinyurl.com/zfqqkx2}
* @type {number}
*/
}

1266
node_modules/mark.js/src/lib/mark.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

22
node_modules/mark.js/src/vanilla.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import MarkJS from './lib/mark';
export default function Mark(ctx) {
const instance = new MarkJS(ctx);
this.mark = (sv, opt) => {
instance.mark(sv, opt);
return this;
};
this.markRegExp = (sv, opt) => {
instance.markRegExp(sv, opt);
return this;
};
this.markRanges = (sv, opt) => {
instance.markRanges(sv, opt);
return this;
};
this.unmark = (opt) => {
instance.unmark(opt);
return this;
};
return this;
}