Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@frontmeans/doqry

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@frontmeans/doqry - npm Package Compare versions

Comparing version
1.0.1
to
1.0.2
+5
-718
dist/doqry.js

@@ -0,1 +1,6 @@

import { escapeCSS, escapeCSSVal } from '@frontmeans/httongue';
import { isQualifiedName, compareNames, newNamespaceAliaser, id__naming, css__naming, html__naming, namesEqual } from '@frontmeans/namespace-aliaser';
import { isArrayOfElements, arraysAreEqual } from '@proc7ts/primitives';
import { flatMapIt } from '@proc7ts/push-iterator';
/**

@@ -12,720 +17,2 @@ * Checks whether the given value is a {@DoqryCombinator CSS selector combinator}.

/**
* Decodes URL component.
*
* In contrast to standard [decodeURIComponent] function this one decodes `+` signs as spaces.
*
* [decodeURIComponent]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent
*
* @param url - URL component to decode.
*
* @returns Decoded URL component.
*/
/**
* Escapes CSS identifier accordingly to the rules defined for [CSS.escape()](https://drafts.csswg.org/cssom/#the-css.escape%28%29-method)
* utility method.
*
* Can be applied to CSS values as well, although it escapes characters that don't strictly need to be escaped.
* A {@link escapeCSSVal} is a better alternative for that.
*
* @param text - A text to escape.
*
* @returns A string safe to be used as CSS identifier, e.g. as CSS selector.
*/
function escapeCSS(text) {
const len = text.length;
const first = text.charCodeAt(0);
let out = '';
let i = 0;
if (first === 0x2d) {
// If the first character is a "-" (U+002D)
const second = text.charCodeAt(1);
// ... and the second character is in the range [0-9] (U+0030 to U+0039).
if (second > 0x2f && second < 0x3a) {
// then '-' followed by the character escaped as code point.
out += `-\\${second.toString(16)} `;
i = 2;
}
else {
out = '-';
i = 1;
}
if (len === 1) {
// ... and there is no second character, then the escaped character.
return '\\-';
}
}
else if (first > 0x2f && first < 0x3a) {
// If the first character is in the range [0-9] (U+0030 to U+0039),
// then the character escaped as code point.
out += `\\${first.toString(16)} `;
i = 1;
}
for (; i < len; ++i) {
const c = text.charCodeAt(i);
if (
// Is in range [a-z] (U+0061 to U+007A),
(c > 0x60 && c < 0x7b)
// or is "-" (U+002D),
|| c === 0x2d
// or is "_" (U+005F)
|| c === 0x5f
// or is in range [0-9] (U+0030 to U+0039),
|| (c > 0x2f && c < 0x3a)
// or is in range [A-Z] (U+0041 to U+005A)
|| (c > 0x40 && c < 0x5b)) {
// then the character itself.
out += text[i];
}
else if (c > 0x7e) {
out += c === 0x7f
// If the character is U+007F
// then the character escaped as code point.
? `\\${c.toString(16)} `
// If the character is greater than or equal to U+0080,
// then the character itself
: text[i];
}
else if (c < 0x20) {
out += c
// If the character is in the range [\1-\1f] (U+0001 to U+001F)
// then the character escaped as code point.
? `\\${c.toString(16)} `
// If the character is NULL (U+0000)
// then the REPLACEMENT CHARACTER (U+FFFD).
: '\uFFFD';
}
else {
// Otherwise, the escaped character.
out += `\\${text[i]}`;
}
}
return out;
}
/**
* Escapes CSS value to be included into CSS string.
*
* Escapes accordingly to [serialize a string] algorithm.
*
* [serialize a string]: https://drafts.csswg.org/cssom/#serialize-a-string
*
* @param text - A text to escape.
*
* @returns A string safe to be included into CSS value, e.g. within CSS string.
*/
function escapeCSSVal(text) {
let out = '';
const len = text.length;
for (let i = 0; i < len; ++i) {
const c = text.charCodeAt(i);
out += c < 0x20 || c === 0x7f
? (c
// If the character is in the range [\1-\1f] (U+0001 to U+001F),
// the character escaped as code point.
? `\\${c.toString(16)} `
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).;
: '\uFFFD')
: (c === 0x22 || c === 0x5c
// If the character is '"' (U+0022) or "\" (U+005C),
// the escaped character.
? `\\${text[i]}`
// Otherwise, the character itself.
: text[i]);
}
return out;
}
/**
* Naming schema is responsible for applying namespace aliases to simple names. E.g. by appending alias as prefix or
* suffix of the name.
*/
class Naming {
/**
* Converts the given qualified `name` into simple one accordingly to this naming schema.
*
* @param name Qualified name to convert.
* @param nsAlias Namespace aliaser to use.
*/
name(name, nsAlias) {
if (typeof name === 'string') {
return name;
}
const [local, ns] = name;
return ns.name(nsAlias(ns), local, this);
}
}
class DefaultNaming extends Naming {
applyAlias(name, alias) {
return `${alias}-${name}`;
}
}
/**
* Default naming schema.
*
* Prefixes a name with namespace alias separating them by dash.
*
* The result looks like `<alias>-<name>`.
*/
const default__naming = ( /*#__PURE__*/new DefaultNaming());
/**
* HTML elements naming schema.
*
* Prefixes a name with namespace alias separating them by dash.
*
* The result looks like `<alias>-<name>`.
*/
const html__naming = ( /*#__PURE__*/new DefaultNaming());
class XmlNaming extends Naming {
applyAlias(name, alias) {
return `${alias}:${name}`;
}
}
/**
* Element identifiers naming schema.
*
* Prefixes a name with namespace alias separating them by colon.
*
* The result looks like `<alias>:<name>`.
*/
const id__naming = ( /*#__PURE__*/new XmlNaming());
class CssNaming extends Naming {
applyAlias(name, alias) {
return `${name}@${alias}`;
}
}
/**
* CSS classes naming scheme.
*
* Appends namespace alias as a name suffix separated by `@` sign.
*
* The result looks like `<name>@<alias>`.
*/
const css__naming = ( /*#__PURE__*/new CssNaming());
/**
* Namespace definition.
*
* Namespaces are identified by their URLs.
*/
class NamespaceDef {
/**
* Constructs new namespace definition.
*
* @param url - Unique namespace URL.
* @param aliases - Preferred namespace aliases. It is expected that each alias is an ASCII letter followed by
* any number of ASCII letters, digits, `-`, or `_` signs. Aliases starting with `xml` are reserved. Empty alias
* is reserved for {@link DEFAULT__NS default namespace}.
*/
constructor(url, ...aliases) {
this.url = url;
this.aliases = aliases;
}
/**
* The most preferred namespace alias.
*
* By default this is the first preferred alias, or `ns` if there is no preferred aliases.
*/
get alias() {
return this.aliases[0] || 'ns';
}
/**
* Converts a local `name` belonging to this namespace to simple one according to the given `naming` schema.
*
* Calls {@link Naming.applyAlias} by default.
*
* @param alias - Namespace alias to apply to the name.
* @param name - A name to convert.
* @param naming - Naming schema to use. {@link default__naming default naming schema} is used when omitted.
*
* @returns A simple name with this namespace alias applied.
*/
name(alias, name, naming = default__naming) {
return naming.applyAlias(name, alias, this);
}
}
/**
* Checks whether the given `value` is a name+namespace tuple.
*
* @param value - A value to check.
*
* @returns `true` if the given `value` is an array consisting of exactly two elements, where the first element is a
* non-empty string, and the second element is an instance of {@link NamespaceDef}. Or `false` otherwise.
*/
function isNameAndNamespace(value) {
return Array.isArray(value)
&& value.length === 2
&& typeof value[0] === 'string'
&& isNamespaceDef(value[1]);
}
function isNamespaceDef(value) {
if (value instanceof NamespaceDef) {
return true;
}
return typeof value === 'object'
&& typeof value.url === 'string'
&& typeof value.alias === 'string'
&& Array.isArray(value.aliases)
&& typeof value.name === 'function';
}
/**
* Checks whether the given `value` is a qualified name.
*
* @param value - A value to check.
*
* @returns `true` if the given `value` is a string, or an array consisting of exactly two elements, where the first
* element is a non-empty string, and the second element is an instance of {@link NamespaceDef}. `false` otherwise.
*/
function isQualifiedName(value) {
return typeof value === 'string' || isNameAndNamespace(value);
}
/**
* Checks whether two qualified names are equal to each other.
*
* @param first - First qualified name to compare.
* @param second - Second qualified name to compare.
*
* @returns `true` if both names are equal, or `false` otherwise.
*/
function namesEqual(first, second) {
if (typeof first === 'string') {
return typeof second === 'string' ? first === second : !second[1].url && second[0] === first;
}
const [firstName, { url: firstUrl }] = first;
if (typeof second === 'string') {
return !firstUrl && firstName === second;
}
return firstName === second[0] && firstUrl === second[1].url;
}
/**
* Compares two qualified names.
*
* Names in default namespace considered less than other names. Namespaces are compared by their URLs.
*
* @param first - First qualified name to compare.
* @param second - Second qualified name to compare.
*
* @returns `-1` if the `first` name is less than the `second` one, `0` if they are equal, or `1` if the `first` name
* is greater than the `second` one.
*/
function compareNames(first, second) {
if (typeof first === 'string') {
if (typeof second === 'string') {
return compareStrings(first, second);
}
if (!second[1].url) {
return compareStrings(first, second[0]);
}
return -1;
}
const [firstName, { url: firstUrl }] = first;
if (typeof second === 'string') {
if (!firstUrl) {
return compareStrings(firstName, second);
}
return 1;
}
return compareStrings(firstUrl, second[1].url) || compareStrings(firstName, second[0]);
}
function compareStrings(first, second) {
return first < second ? -1 : first > second ? 1 : 0;
}
/**
* Creates a namespace aliaser.
*
* The returned function tries to find a registered alias for the given namespace. If not found then tries to use one
* of its preferred aliases. If all of them are reserved already for another namespaces, generates a new unique alias.
*
* @returns New instance of namespace aliaser.
*/
function newNamespaceAliaser() {
const aliasesByNs = new Map();
const nsNumPerAlias = new Map();
return function nsAlias(ns) {
const found = aliasesByNs.get(ns.url);
if (found) {
return found;
}
const mostPreferred = ns.alias;
let nsNumRegistered = 0;
for (const preferred of [mostPreferred, ...ns.aliases]) {
const ids = nsNumPerAlias.get(preferred);
if (!ids) {
aliasesByNs.set(ns.url, preferred);
nsNumPerAlias.set(preferred, 1);
return preferred;
}
if (!nsNumRegistered) {
// Use the first one
nsNumRegistered = ids;
}
}
const generated = `${mostPreferred}${++nsNumRegistered}`;
aliasesByNs.set(ns.url, generated);
nsNumPerAlias.set(mostPreferred, nsNumRegistered);
return generated;
};
}
function isArrayOfElements(value) {
return Array.isArray(value);
}
/**
* Checks whether two values are the same. I.e. strictly equal to each other.
*
* @typeParam T - A type of values.
* @param first - First value to compare.
* @param second - Second value to compare.
*
* @returns `true` if `first === second`, or `false` otherwise.
*/
function areTheSame(first, second) {
return first === second;
}
function arraysAreEqual(first, second, compareOrFromOrLength, fromOrLength, to) {
return typeof compareOrFromOrLength === 'function'
? arrayElementsAreEqual(first, second, compareOrFromOrLength, fromOrLength, to)
: arrayElementsAreEqual(first, second, areTheSame, compareOrFromOrLength, fromOrLength);
}
function arrayElementsAreEqual(first, second, elementsAreEqual, fromOrLength, to) {
let start;
let end;
if (to !== undefined) {
start = fromOrLength ? Math.max(fromOrLength, 0) : 0;
end = to != null ? to : Math.max(first.length, second.length);
}
else if (fromOrLength != null) {
start = 0;
end = fromOrLength;
}
else {
start = 0;
end = Math.max(first.length, second.length);
}
if ((first.length <= end || second.length <= end) && first.length !== second.length) {
return false;
}
for (let i = start; i < end; ++i) {
if (!elementsAreEqual(first[i], second[i], i)) {
return false;
}
}
return true;
}
/**
* A key of {@link PushIterable} iteration method.
*/
const PushIterator__symbol = ( /*#__PURE__*/Symbol('push-iterator'));
function isPushIterable(iterable) {
return !!iterable[PushIterator__symbol];
}
/**
* Creates a push iterable implementation.
*
* @typeParam T - Iterated elements type.
* @param iterate - A function iterating over iterable elements conforming to {@link PushIterable.Iterate} requirements.
*
* @returns New push iterable instance performing iteration by `forNext` function.
*/
function makePushIterable(iterate) {
return {
[Symbol.iterator]: PushIterable$iterator,
[PushIterator__symbol]: iterate,
};
}
function PushIterable$iterator() {
return this[PushIterator__symbol]();
}
function PushIterator$iterator() {
return this;
}
function PushIterator$next() {
for (;;) {
let result;
const tail = this[PushIterator__symbol](value => {
result = { value };
return true;
});
if (result) {
return result;
}
if (tail.isOver()) {
return { done: true };
}
}
}
const PushIterator$empty = {
[Symbol.iterator]: PushIterator$iterator,
[PushIterator__symbol](_accept) {
return this;
},
next: PushIterator$noNext,
isOver: PushIterator$over,
};
function PushIterator$noNext() {
return { done: true };
}
function PushIterator$dontIterate(_accept) {
// Do not iterate
}
function PushIterator$over() {
return true;
}
/**
* Creates a push iterator implementation.
*
* @typeParam T - Iterated elements type.
* @param forNext - A function iterating over elements conforming to push iteration protocol.
*
* @returns New push iterator instance performing iteration by `forNext` function.
*/
function makePushIterator(forNext) {
let over = false;
let iterate = (accept) => {
if (accept && !forNext(accept)) {
over = true;
iterate = PushIterator$dontIterate;
}
};
return {
[Symbol.iterator]: PushIterator$iterator,
[PushIterator__symbol](accept) {
iterate(accept);
return this;
},
next: PushIterator$next,
isOver: () => over,
};
}
function iterateOverIndexed(indexed, elementOf) {
return accept => {
let i = 0;
const forNext = (accept) => {
if (i >= indexed.length) {
return false;
}
for (;;) {
const goOn = accept(elementOf(indexed, i++));
if (i >= indexed.length || goOn === false) {
return false;
}
if (goOn === true) {
return true;
}
}
};
if (accept && !forNext(accept)) {
return PushIterator$empty;
}
let over = false;
let iterate = (accept) => {
if (accept && !forNext(accept)) {
over = true;
iterate = PushIterator$dontIterate;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
next = PushIterator$noNext;
}
};
let next = () => {
if (i < indexed.length) {
return { value: elementOf(indexed, i++) };
}
over = true;
iterate = PushIterator$dontIterate;
next = PushIterator$noNext;
return { done: true };
};
return {
[Symbol.iterator]: PushIterator$iterator,
[PushIterator__symbol](accept) {
iterate(accept);
return this;
},
next: () => next(),
isOver: () => over,
};
};
}
function arrayElementOf(array, index) {
return array[index];
}
function iterateOverArray(array) {
return iterateOverIndexed(array, arrayElementOf);
}
function toPushIterator(it, forNext) {
let over = false;
let iterate = (accept) => {
if ((over = !!accept && !forNext(accept))) {
iterate = PushIterator$dontIterate;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
next = PushIterator$noNext;
}
};
let next = () => {
const res = it.next();
if (res.done) {
over = true;
iterate = PushIterator$dontIterate;
next = PushIterator$noNext;
}
return res;
};
return {
[Symbol.iterator]: PushIterator$iterator,
[PushIterator__symbol](accept) {
iterate(accept);
return this;
},
next() {
return next();
},
isOver: () => over,
};
}
function rawIteratorPusher(it) {
return accept => {
for (;;) {
const res = it.next();
if (res.done) {
return false;
}
const status = accept(res.value);
if (typeof status === 'boolean') {
return status;
}
}
};
}
/**
* Iterates over elements of the given iterable.
*
* Calls `accept` method for each iterated element until there are elements to iterate, or `accept` returned either
* `true` or `false`.
*
* @typeParam T - Iterated elements type.
* @param iterable - An iterable to iterate elements of.
* @param accept - A function to push iterated elements to. Accepts iterated element as its only parameter. May return
* `true` to suspend iteration, or `false` to stop it.
*
* @returns A push iterator instance representing the tail of the given iterable. This iterator can be used to continue
* iteration with, unless `accept` returned `false`. In the latter case the further iteration won't be possible.
*/
function iterateIt(iterable, accept) {
if (isPushIterable(iterable)) {
return iterable[PushIterator__symbol](accept);
}
if (Array.isArray(iterable)) {
return iterateIt$array(iterable, accept);
}
return iterateIt$raw(iterable, accept);
}
function iterateIt$array(array, accept) {
return array.length ? iterateOverArray(array)(accept) : PushIterator$empty;
}
function iterateIt$raw(iterable, accept) {
const it = iterable[Symbol.iterator]();
if (isPushIterable(it)) {
return it[PushIterator__symbol](accept);
}
const forEach = rawIteratorPusher(it);
return forEach(accept) ? toPushIterator(it, forEach) : PushIterator$empty;
}
/**
* Returns a {@link PushIterator push iterator} without elements.
*
* @typeParam T - Iterated elements type.
*
* @returns Empty push iterator instance.
*/
function overNone() {
return PushIterator$empty;
}
function flatMapIt(source, convert = flatMapIt$defaultConverter) {
return makePushIterable(accept => {
const forNext = isPushIterable(source)
? flatMap$(source, convert)
: flatMap$raw(source, convert);
return accept && !forNext(accept) ? overNone() : makePushIterator(forNext);
});
}
function flatMap$(source, convert) {
let subs;
let lastSrc = false;
return accept => {
for (;;) {
while (!subs) {
const sourceTail = source[PushIterator__symbol](src => {
subs = convert(src);
return true;
});
source = sourceTail;
if (sourceTail.isOver()) {
if (!subs) {
return false;
}
lastSrc = true;
}
}
let status;
const subsTail = iterateIt(subs, element => status = accept(element));
if (subsTail.isOver()) {
subs = undefined;
if (lastSrc) {
return false;
}
}
else {
subs = subsTail;
}
if (typeof status === 'boolean') {
return status;
}
}
};
}
function flatMap$raw(source, convert) {
const it = source[Symbol.iterator]();
if (isPushIterable(it)) {
return flatMap$(it, convert);
}
let subs;
return accept => {
for (;;) {
if (!subs) {
const next = it.next();
if (next.done) {
return false;
}
subs = convert(next.value);
}
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
let status;
const subsTail = iterateIt(subs, element => status = accept(element));
subs = subsTail.isOver() ? undefined : subsTail;
if (typeof status === 'boolean') {
return status;
}
}
};
}
function flatMapIt$defaultConverter(element) {
return element;
}
const DoqryPicker__symbol = ( /*#__PURE__*/Symbol('DoqryPicker'));

@@ -732,0 +19,0 @@ class DoqryPicker$Mutable extends Array {

+5
-4
{
"name": "@frontmeans/doqry",
"version": "1.0.1",
"version": "1.0.2",
"description": "Document query notation for CSS selectors",

@@ -26,8 +26,9 @@ "keywords": [

"@proc7ts/primitives": "^3.0.2",
"@proc7ts/push-iterator": "^3.0.0"
"@proc7ts/push-iterator": "^3.1.0"
},
"devDependencies": {
"@jest/globals": "^27.0.6",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-node-resolve": "^13.0.2",
"@run-z/eslint-config": "^1.3.0",
"@run-z/rollup-helpers": "^1.1.1",
"@typescript-eslint/eslint-plugin": "^4.28.3",

@@ -47,3 +48,3 @@ "@typescript-eslint/parser": "^4.28.3",

"rollup-plugin-typescript2": "^0.30.0",
"run-z": "^1.9.1",
"run-z": "^1.9.2",
"shx": "^0.3.3",

@@ -50,0 +51,0 @@ "ts-jest": "^27.0.3",

import nodeResolve from '@rollup/plugin-node-resolve';
import { externalModules } from '@run-z/rollup-helpers';
import { defineConfig } from 'rollup';

@@ -21,2 +22,3 @@ import flatDts from 'rollup-plugin-flat-dts';

],
external: externalModules(),
output: {

@@ -23,0 +25,0 @@ dir: '.',

Sorry, the diff of this file is too big to display