New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@markuplint/ml-core

Package Overview
Dependencies
Maintainers
1
Versions
201
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@markuplint/ml-core - npm Package Compare versions

Comparing version 2.0.0-rc.0 to 2.0.0-rc.1

1

lib/index.d.ts
export { RuleInfo, RuleConfig, RuleConfigValue } from '@markuplint/ml-config';
export { getAttrSpecs } from '@markuplint/ml-spec';
export * from './convert-ruleset';

@@ -3,0 +4,0 @@ export * from './ml-core';

4

lib/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.enableDebug = exports.getIndent = exports.Ruleset = exports.MLParseError = void 0;
exports.enableDebug = exports.getIndent = exports.Ruleset = exports.MLParseError = exports.getAttrSpecs = void 0;
const tslib_1 = require("tslib");
var ml_spec_1 = require("@markuplint/ml-spec");
Object.defineProperty(exports, "getAttrSpecs", { enumerable: true, get: function () { return ml_spec_1.getAttrSpecs; } });
(0, tslib_1.__exportStar)(require("./convert-ruleset"), exports);

@@ -6,0 +8,0 @@ (0, tslib_1.__exportStar)(require("./ml-core"), exports);

@@ -13,3 +13,3 @@ import type { MLFabric } from './types';

constructor({ parser, sourceCode, ruleset, rules, locale, schemas, parserOptions, filename, debug }: MLCoreParams);
get document(): MLParseError | Document<RuleConfigValue, unknown>;
get document(): Document<RuleConfigValue, unknown> | MLParseError;
verify(fix?: boolean): Promise<Violation[]>;

@@ -16,0 +16,0 @@ setCode(sourceCode: string): void;

@@ -61,4 +61,4 @@ "use strict";

for (const rule of (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_rules, "f")) {
const ruleInfo = rule.optimizeOption((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f").rules[rule.name] || false);
if (ruleInfo.disabled) {
const ruleInfo = rule.getRuleInfo((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f"), rule.name);
if (ruleInfo.disabled && ruleInfo.nodeRules.length === 0 && ruleInfo.childNodeRules.length === 0) {
continue;

@@ -89,14 +89,16 @@ }

}
const { e, w, i } = violations.reduce((c, v) => {
if (v.severity === 'error')
c.e += 1;
if (v.severity === 'warning')
c.w += 1;
if (v.severity === 'info')
c.i += 1;
return c;
}, { e: 0, w: 0, i: 0 });
resultLog('Error: %d', e);
resultLog('Warning: %d', w);
resultLog('Info: %d', i);
if (resultLog.enabled) {
const { e, w, i } = violations.reduce((c, v) => {
if (v.severity === 'error')
c.e += 1;
if (v.severity === 'warning')
c.w += 1;
if (v.severity === 'info')
c.i += 1;
return c;
}, { e: 0, w: 0, i: 0 });
resultLog('Error: %d', e);
resultLog('Warning: %d', w);
resultLog('Info: %d', i);
}
(0, debug_1.log)('verify: end');

@@ -103,0 +105,0 @@ return violations;

@@ -132,3 +132,8 @@ "use strict";

for (const node of this.nodeList) {
docLog('Add rules to node <%s%s>', node.type === 'ElementCloseTag' ? '/' : '', 'nodeName' in node ? node.nodeName : `#${node.type}`);
if (node.type === 'ElementCloseTag') {
continue;
}
if (docLog.enabled) {
docLog('Add rules to node <%s>', 'nodeName' in node ? node.nodeName : `#${node.type}`);
}
// global rules

@@ -139,17 +144,10 @@ Object.keys(ruleset.rules).forEach(ruleName => {

from: 'rules',
index: -1,
specificity: [0, 0, 0],
rule,
});
});
if (node.type !== 'Element' &&
node.type !== 'OmittedElement' &&
node.type !== 'ElementCloseTag' &&
node.type !== 'Text') {
if (node.type !== 'Element' && node.type !== 'OmittedElement' && node.type !== 'Text') {
continue;
}
const selectorTarget = node.type === 'Element' || node.type === 'OmittedElement'
? node
: node.type === 'ElementCloseTag'
? node.startTag
: null;
const selectorTarget = node.type === 'Element' || node.type === 'OmittedElement' ? node : null;
// node specs and special rules for node by selector

@@ -160,4 +158,7 @@ ruleset.nodeRules.forEach((nodeRule, i) => {

}
if (!selectorTarget) {
return;
}
const selector = nodeRule.selector || nodeRule.regexSelector || nodeRule.tagName;
const matched =
const matches =
/**

@@ -167,15 +168,21 @@ * Forward v1.x compatibility

nodeRule.tagName && /^#text$/i.test(nodeRule.tagName) && node.type === 'Text'
? { __node: '#text' }
? {
matched: true,
selector: '#text',
specificity: [0, 0, 0],
}
: /**
* v2.0.0 or later
*/
selectorTarget && (0, match_selector_1.matchSelector)(selectorTarget, selector);
if (!matched) {
(0, match_selector_1.matchSelector)(selectorTarget, selector);
if (!matches.matched) {
return;
}
docLog('Matched nodeRule: <%s%s>(%s)', node.type === 'ElementCloseTag' ? '/' : '', 'nodeName' in node ? node.nodeName : node.type, matched.__node || 'No Selector');
if (docLog.enabled) {
docLog('Matched nodeRule: <%s>(%s)', 'nodeName' in node ? node.nodeName : node.type, matches.selector || '*');
}
const ruleList = Object.keys(nodeRule.rules);
for (const ruleName of ruleList) {
const rule = nodeRule.rules[ruleName];
const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matched);
const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matches.data || {});
if (convertedRule === undefined) {

@@ -189,3 +196,3 @@ continue;

from: 'nodeRules',
index: i,
specificity: matches.specificity,
rule: mergedRule,

@@ -214,11 +221,13 @@ });

}
const matched = (0, match_selector_1.matchSelector)(selectorTarget, selector);
if (!matched) {
const matches = (0, match_selector_1.matchSelector)(selectorTarget, selector);
if (!matches.matched) {
return;
}
docLog('Matched childNodeRule: <%s%s>(%s), inheritance: %o', node.type === 'ElementCloseTag' ? '/' : '', selectorTarget.nodeName, matched.__node || 'No Selector', !!nodeRule.inheritance);
if (docLog.enabled) {
docLog('Matched childNodeRule: <%s>(%s), inheritance: %o', selectorTarget.nodeName, matches.selector || '*', !!nodeRule.inheritance);
}
const targetDescendants = nodeRule.inheritance ? descendants : children;
Object.keys(nodeRuleRules).forEach(ruleName => {
const rule = nodeRuleRules[ruleName];
const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matched);
const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matches.data || {});
if (convertedRule === undefined) {

@@ -233,3 +242,3 @@ return;

from: 'childNodeRules',
index: i,
specificity: matches.specificity,
rule: mergedRule,

@@ -236,0 +245,0 @@ });

import type MLDOMAbstractElement from '../tokens/abstract-element';
import type { Specificity } from './selector';
import type { RegexSelector } from '@markuplint/ml-config';
export declare type SelectorMatches = SelectorMatched | SelectorUnmatched;
declare type SelectorMatched = {
matched: true;
selector: string;
specificity: Specificity;
data?: Record<string, string>;
};
declare type SelectorUnmatched = {
matched: false;
};
declare type TargetElement = MLDOMAbstractElement<any, any>;
export declare function matchSelector(el: TargetElement, selector: string | RegexSelector | undefined): Record<string, string> | null;
export declare function matchSelector(el: TargetElement, selector: string | RegexSelector | undefined): SelectorMatches;
export {};

@@ -8,8 +8,19 @@ "use strict";

if (!selector) {
return null;
return {
matched: false,
};
}
if (typeof selector === 'string') {
const sel = (0, selector_1.createSelector)(selector);
const matched = sel.match(el);
return matched ? { __node: selector } : null;
const specificity = sel.match(el);
if (specificity) {
return {
matched: true,
selector,
specificity,
};
}
return {
matched: false,
};
}

@@ -40,8 +51,8 @@ return regexSelect(el, selector);

match(el) {
const matched = this._matchWithoutCombinateChecking(el);
if (!matched) {
return null;
const unitCheck = this._matchWithoutCombinateChecking(el);
if (!unitCheck.matched) {
return unitCheck;
}
if (!this._combinatedFrom) {
return matched;
return unitCheck;
}

@@ -52,32 +63,25 @@ const { target, combinator } = this._combinatedFrom;

case ' ': {
let ancestor = el.parentNode;
let ancestor = el.getParentElement();
while (ancestor) {
const ancestorMatched = target.match(ancestor);
if (ancestorMatched) {
const res = {
...ancestorMatched,
...matched,
__node: `${ancestorMatched.__node} ${matched.__node}`,
};
return res;
const matches = target.match(ancestor);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ' ');
}
ancestor = ancestor.parentNode;
ancestor = ancestor.getParentElement();
}
return null;
return {
matched: false,
};
}
// Child combinator
case '>': {
if (!el.parentNode) {
return null;
const parentNode = el.getParentElement();
if (!parentNode) {
return { matched: false };
}
const parentMatched = target.match(el.parentNode);
if (parentMatched) {
const res = {
...parentMatched,
...matched,
__node: `${parentMatched.__node} > ${matched.__node}`,
};
return res;
const matches = target.match(parentNode);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ' > ');
}
return null;
return { matched: false };
}

@@ -87,14 +91,9 @@ // Next-sibling combinator

if (!el.previousElementSibling) {
return null;
return { matched: false };
}
const prevMatched = target.match(el.previousElementSibling);
if (prevMatched) {
const res = {
...prevMatched,
...matched,
__node: `${prevMatched.__node} + ${matched.__node}`,
};
return res;
const matches = target.match(el.previousElementSibling);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ' + ');
}
return null;
return { matched: false };
}

@@ -105,14 +104,9 @@ // Subsequent-sibling combinator

while (prev) {
const prevMatched = target.match(prev);
if (prevMatched) {
const res = {
...prevMatched,
...matched,
__node: `${prevMatched.__node} ~ ${matched.__node}`,
};
return res;
const matches = target.match(prev);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ' ~ ');
}
prev = prev.previousElementSibling;
}
return null;
return { matched: false };
}

@@ -122,14 +116,9 @@ // Prev-sibling combinator

if (!el.nextElementSibling) {
return null;
return { matched: false };
}
const nextMatched = target.match(el.nextElementSibling);
if (nextMatched) {
const res = {
...nextMatched,
...matched,
__node: `${nextMatched.__node}:has(+ ${matched.__node})`,
};
return res;
const matches = target.match(el.nextElementSibling);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ':has(+ ', true);
}
return null;
return { matched: false };
}

@@ -140,14 +129,9 @@ // Subsequent-sibling (in front) combinator

while (next) {
const nextMatched = target.match(next);
if (nextMatched) {
const res = {
...nextMatched,
...matched,
__node: `${nextMatched.__node}:has(~ ${matched.__node})`,
};
return res;
const matches = target.match(next);
if (matches.matched) {
return mergeMatches(matches, unitCheck, ':has(~ ', true);
}
next = next.nextElementSibling;
}
return null;
return { matched: false };
}

@@ -167,14 +151,21 @@ default: {

function uncombinatedRegexSelect(el, selector) {
let matchedMap = {};
let matched = true;
let data = {};
let tagSelector = '';
const specificity = [0, 0, 0];
const specifiedAttr = new Map();
if (selector.nodeName) {
const matchedNodeName = (0, ml_config_1.regexSelectorMatches)(selector.nodeName, el.nodeName);
if (!matchedNodeName) {
return null;
if (matchedNodeName) {
delete matchedNodeName.$0;
}
delete matchedNodeName.$0;
matchedMap = {
...matchedMap,
else {
matched = false;
}
data = {
...data,
...matchedNodeName,
__node: el.nodeName,
};
tagSelector = el.nodeName;
specificity[2] = 1;
}

@@ -188,7 +179,7 @@ if (selector.attrName) {

delete matchedAttrName.$0;
matchedMap = {
...matchedMap,
data = {
...data,
...matchedAttrName,
__node: matchedMap.__node ? `${matchedMap.__node}[${attrName}]` : `[${attrName}]`,
};
specifiedAttr.set(attrName, '');
}

@@ -198,3 +189,3 @@ return matchedAttrName;

if (!matchedAttrNameList.some(_ => !!_)) {
return null;
matched = false;
}

@@ -210,9 +201,7 @@ }

delete matchedAttrValue.$0;
matchedMap = {
...matchedMap,
data = {
...data,
...matchedAttrValue,
__node: matchedMap.__node
? `${matchedMap.__node}[${attrName}="${attrValue}"]`
: `[${attrName}="${attrValue}"]`,
};
specifiedAttr.set(attrName, attrValue);
}

@@ -222,6 +211,35 @@ return matchedAttrValue;

if (!matchedAttrValueList.some(_ => !!_)) {
return null;
matched = false;
}
}
return matchedMap;
const attrSelector = Array.from(specifiedAttr.entries())
.map(([name, value]) => {
return `[${name}${value ? `="${value}"` : ''}]`;
})
.join('');
specificity[1] += specifiedAttr.size;
if (matched) {
return {
matched,
selector: `${tagSelector}${attrSelector}`,
specificity,
data,
};
}
return { matched };
}
function mergeMatches(a, b, sep, close = false) {
return {
matched: true,
selector: `${a.selector}${sep}${b.selector}${close ? ')' : ''}`,
specificity: [
a.specificity[0] + b.specificity[0],
a.specificity[1] + b.specificity[1],
a.specificity[2] + b.specificity[2],
],
data: {
...a.data,
...b.data,
},
};
}
import type MLDOMAbstractElement from '../tokens/abstract-element';
export declare type Specificity = [number, number, number];
export declare function createSelector(selector: string): Selector;
export declare function compareSpecificity(a: Specificity, b: Specificity): 0 | 1 | -1;
declare type TargetElement = MLDOMAbstractElement<any, any>;

@@ -7,4 +9,4 @@ declare class Selector {

constructor(selector: string);
match(el: TargetElement, caller?: TargetElement | null): boolean;
match(el: TargetElement, caller?: TargetElement | null): Specificity | false;
}
export {};
"use strict";
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_edge, _StructuredSelector_selector, _SelectorTarget_isAdded, _SelectorTarget_combinatedFrom;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSelector = void 0;
exports.compareSpecificity = exports.createSelector = void 0;
const tslib_1 = require("tslib");
const postcss_selector_parser_1 = (0, tslib_1.__importDefault)(require("postcss-selector-parser"));
const debug_1 = require("../../debug");
const log = debug_1.log.extend('selector');
const resLog = log.extend('result');
function createSelector(selector) {

@@ -11,2 +14,24 @@ return new Selector(selector);

exports.createSelector = createSelector;
function compareSpecificity(a, b) {
if (a[0] < b[0]) {
return -1;
}
else if (a[0] > b[0]) {
return 1;
}
else if (a[1] < b[1]) {
return -1;
}
else if (a[1] > b[1]) {
return 1;
}
else if (a[2] < b[2]) {
return -1;
}
else if (a[2] > b[2]) {
return 1;
}
return 0;
}
exports.compareSpecificity = compareSpecificity;
class Selector {

@@ -18,3 +43,9 @@ constructor(selector) {

match(el, caller = el) {
return (0, tslib_1.__classPrivateFieldGet)(this, _Selector_ruleset, "f").match(el, caller);
const results = (0, tslib_1.__classPrivateFieldGet)(this, _Selector_ruleset, "f").match(el, caller);
for (const result of results) {
if (result.matched) {
return result.specificity;
}
}
return false;
}

@@ -36,3 +67,8 @@ }

match(el, caller) {
return (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_selectorGroup, "f").some(selector => selector.match(el, caller));
log('%s', el.raw);
return (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_selectorGroup, "f").map(selector => {
const res = selector.match(el, caller);
resLog('%s => %o', selector.selector, res);
return res;
});
}

@@ -71,2 +107,5 @@ }

}
get selector() {
return (0, tslib_1.__classPrivateFieldGet)(this, _StructuredSelector_selector, "f").nodes.join('');
}
match(el, caller) {

@@ -88,8 +127,8 @@ return (0, tslib_1.__classPrivateFieldGet)(this, _StructuredSelector_edge, "f").match(el, caller);

match(el, caller) {
const matched = this._matchWithoutCombinateChecking(el, caller);
if (!matched) {
return false;
const unitCheck = this._matchWithoutCombinateChecking(el, caller);
if (!unitCheck.matched) {
return unitCheck;
}
if (!(0, tslib_1.__classPrivateFieldGet)(this, _SelectorTarget_combinatedFrom, "f")) {
return true;
return unitCheck;
}

@@ -100,45 +139,110 @@ const { target, combinator } = (0, tslib_1.__classPrivateFieldGet)(this, _SelectorTarget_combinatedFrom, "f");

case ' ': {
let ancestor = el.parentNode;
let ancestor = el.getParentElement();
let matched = false;
let specificity;
while (ancestor) {
const ancestorMatched = target._matchWithoutCombinateChecking(ancestor, caller);
if (ancestorMatched) {
return target.match(ancestor, caller);
const res = target.match(ancestor, caller);
if (!specificity) {
specificity = [
unitCheck.specificity[0] + res.specificity[0],
unitCheck.specificity[1] + res.specificity[1],
unitCheck.specificity[2] + res.specificity[2],
];
}
ancestor = ancestor.parentNode;
if (res.matched) {
matched = true;
}
ancestor = ancestor.getParentElement();
}
return false;
if (!specificity) {
const res = target.match(el, caller);
specificity = [
unitCheck.specificity[0] + res.specificity[0],
unitCheck.specificity[1] + res.specificity[1],
unitCheck.specificity[2] + res.specificity[2],
];
}
return {
specificity,
matched,
};
}
// Child combinator
case '>': {
if (!el.parentNode) {
return false;
let matched;
const specificity = unitCheck.specificity;
const parentNode = el.getParentElement();
if (parentNode) {
const res = target.match(parentNode, caller);
specificity[0] += res.specificity[0];
specificity[1] += res.specificity[1];
specificity[2] += res.specificity[2];
matched = res.matched;
}
const parentMatched = target._matchWithoutCombinateChecking(el.parentNode, caller);
if (parentMatched) {
return target.match(el.parentNode, caller);
else {
const res = target.match(el, caller);
specificity[0] += res.specificity[0];
specificity[1] += res.specificity[1];
specificity[2] += res.specificity[2];
matched = false;
}
return false;
return {
specificity,
matched,
};
}
// Next-sibling combinator
case '+': {
if (!el.previousElementSibling) {
return false;
let matched;
const specificity = unitCheck.specificity;
if (el.previousElementSibling) {
const res = target.match(el.previousElementSibling, caller);
specificity[0] += res.specificity[0];
specificity[1] += res.specificity[1];
specificity[2] += res.specificity[2];
matched = res.matched;
}
const prevMatched = target._matchWithoutCombinateChecking(el.previousElementSibling, caller);
if (prevMatched) {
return target.match(el.previousElementSibling, caller);
else {
const res = target.match(el, caller);
specificity[0] += res.specificity[0];
specificity[1] += res.specificity[1];
specificity[2] += res.specificity[2];
matched = false;
}
return false;
return {
specificity,
matched,
};
}
// Subsequent-sibling combinator
// // Subsequent-sibling combinator
case '~': {
let prev = el.previousElementSibling;
let matched = false;
let specificity;
while (prev) {
const prevMatched = target._matchWithoutCombinateChecking(prev, caller);
if (prevMatched) {
return target.match(prev, caller);
const res = target.match(prev, caller);
if (!specificity) {
specificity = [
unitCheck.specificity[0] + res.specificity[0],
unitCheck.specificity[1] + res.specificity[1],
unitCheck.specificity[2] + res.specificity[2],
];
}
if (res.matched) {
matched = true;
}
prev = prev.previousElementSibling;
}
return false;
if (!specificity) {
const res = target.match(el, caller);
specificity = [
unitCheck.specificity[0] + res.specificity[0],
unitCheck.specificity[1] + res.specificity[1],
unitCheck.specificity[2] + res.specificity[2],
];
}
return {
specificity,
matched,
};
}

@@ -155,23 +259,38 @@ // Column combinator

_matchWithoutCombinateChecking(el, caller) {
if (!(0, tslib_1.__classPrivateFieldGet)(this, _SelectorTarget_isAdded, "f")) {
return isScope(el, caller);
const specificity = [0, 0, 0];
let matched = true;
if (!(0, tslib_1.__classPrivateFieldGet)(this, _SelectorTarget_isAdded, "f") && !isScope(el, caller)) {
matched = false;
}
if (this.tag && this.tag.type === 'tag') {
if (this.tag.value.toLowerCase() !== el.nodeName.toLowerCase()) {
return false;
}
}
if (!this.id.every(id => id.value === el.id)) {
return false;
matched = false;
}
specificity[0] += this.id.length;
if (!this.class.every(className => el.classList.includes(className.value))) {
return false;
matched = false;
}
specificity[1] += this.class.length;
if (!this.attr.every(attr => attrMatch(attr, el))) {
return false;
matched = false;
}
if (!this.pseudo.every(pseudo => pseudoMatch(pseudo, el, caller))) {
return false;
specificity[1] += this.attr.length;
for (const pseudo of this.pseudo) {
const pseudoRes = pseudoMatch(pseudo, el, caller);
specificity[0] += pseudoRes.specificity[0];
specificity[1] += pseudoRes.specificity[1];
specificity[2] += pseudoRes.specificity[2];
if (!pseudoRes.matched) {
matched = false;
}
}
return true;
if (this.tag && this.tag.type === 'tag') {
specificity[2] += 1;
if (this.tag.value.toLowerCase() !== el.nodeName.toLowerCase()) {
matched = false;
}
}
return {
specificity,
matched,
};
}

@@ -270,10 +389,17 @@ add(selector) {

const ruleset = new Ruleset(pseudo.nodes);
let parent = el.parentNode;
const specificity = getSpecificity(ruleset.match(el, caller));
let parent = el.getParentElement();
while (parent) {
if (ruleset.match(parent, caller)) {
return true;
if (ruleset.match(parent, caller).some(r => r.matched)) {
return {
specificity,
matched: true,
};
}
parent = parent.parentNode;
parent = parent.getParentElement();
}
return false;
return {
specificity,
matched: false,
};
}

@@ -285,33 +411,62 @@ /**

const ruleset = new Ruleset(pseudo.nodes);
if (ruleset.match(el, caller)) {
return false;
}
break;
const resList = ruleset.match(el, caller);
const specificity = getSpecificity(resList);
const matched = resList.every(r => !r.matched);
return {
specificity,
matched,
};
}
case ':is': {
const ruleset = new Ruleset(pseudo.nodes);
if (!ruleset.match(el, caller)) {
return false;
}
break;
const resList = ruleset.match(el, caller);
const specificity = getSpecificity(resList);
const matched = resList.some(r => r.matched);
return {
specificity,
matched,
};
}
case ':has': {
const ruleset = new Ruleset(pseudo.nodes);
const specificity = getSpecificity(ruleset.match(el, caller));
const descendants = getDescendants(el);
if (!descendants.some(desc => ruleset.match(desc, caller))) {
return false;
}
break;
const matched = descendants.some(desc => ruleset.match(desc, caller).some(m => m.matched));
return {
specificity,
matched,
};
}
case ':where': {
const ruleset = new Ruleset(pseudo.nodes);
const resList = ruleset.match(el, caller);
const matched = resList.some(r => r.matched);
return {
specificity: [0, 0, 0],
matched,
};
}
case ':scope': {
if (!isScope(el, caller)) {
return false;
return {
specificity: [0, 1, 0],
matched: false,
};
}
break;
return {
specificity: [0, 1, 0],
matched: true,
};
}
case ':root': {
if (!(!el.isInFragmentDocument && el.parentNode === null)) {
return false;
return {
specificity: [0, 1, 0],
matched: false,
};
}
break;
return {
specificity: [0, 1, 0],
matched: true,
};
}

@@ -349,3 +504,2 @@ case ':enable':

}
case ':where':
case ':dir':

@@ -373,3 +527,2 @@ case ':lang':

}
return true;
}

@@ -382,1 +535,19 @@ function isScope(el, caller) {

}
function getSpecificity(result) {
let specificity;
for (const res of result) {
if (specificity) {
const order = compareSpecificity(specificity, res.specificity);
if (order === -1) {
specificity = res.specificity;
}
}
else {
specificity = res.specificity;
}
}
if (!specificity) {
throw new Error('Result is empty');
}
return specificity;
}

@@ -0,1 +1,2 @@

import type { Specificity } from './helper/selector';
import type { AnonymousNode } from './types';

@@ -6,3 +7,3 @@ import type { AnyRule } from '@markuplint/ml-config';

from: RuleType;
index: number;
specificity: Specificity;
rule: AnyRule;

@@ -9,0 +10,0 @@ };

@@ -7,2 +7,3 @@ "use strict";

const debug_1 = require("../debug");
const selector_1 = require("./helper/selector");
const ruleMapperLog = debug_1.log.extend('rule-mapper');

@@ -18,16 +19,21 @@ const ruleMapperNodeLog = ruleMapperLog.extend('node');

set(node, ruleName, rule) {
if (node.type === 'ElementCloseTag') {
return;
}
const rules = (0, tslib_1.__classPrivateFieldGet)(this, _RuleMapper_ruleMap, "f").get(node.uuid) || {};
const currentRule = rules[ruleName];
if (currentRule) {
if (currentRule.index <= rule.index) {
ruleMapperLog('Unset %o from %s', currentRule, node);
}
else {
ruleMapperLog("Don't set %o (%d vs %d)", rule, currentRule.index, rule.index);
const order = (0, selector_1.compareSpecificity)(currentRule.specificity, rule.specificity);
if (order === 1) {
ruleMapperLog("Don't set %o ([%s] vs [%s])", rule, currentRule.specificity, rule.specificity);
return;
}
ruleMapperLog('Unset %o from %s', currentRule, node);
}
rules[ruleName] = rule;
(0, tslib_1.__classPrivateFieldGet)(this, _RuleMapper_ruleMap, "f").set(node.uuid, rules);
ruleMapperLog('Set %o to %s', rule, node);
if (node.type === 'Element' && node.closeTag) {
(0, tslib_1.__classPrivateFieldGet)(this, _RuleMapper_ruleMap, "f").set(node.closeTag.uuid, rules);
}
ruleMapperLog('Set to %s from %s (%o): %O', node.raw, rule.from, rule.specificity, rule.rule);
}

@@ -41,9 +47,9 @@ apply() {

}
const shash = node.type === 'ElementCloseTag' ? '/' : '';
const slash = node.type === 'ElementCloseTag' ? '/' : '';
const nodeName = 'nodeName' in node ? node.nodeName : `#${node.type}`;
ruleMapperNodeLog('<%s%s>', shash, nodeName);
ruleMapperNodeLog('<%s%s>', slash, nodeName);
Object.keys(rules).forEach(ruleName => {
const rule = rules[ruleName];
node.rules[ruleName] = rule.rule;
ruleMapperNodeRuleLog('[from: %s(%d)] %s: %o', rule.from, rule.index, ruleName, rule.rule);
ruleMapperNodeRuleLog('[from: %s(%s)] %s: %o', rule.from, rule.specificity, ruleName, rule.rule);
});

@@ -50,0 +56,0 @@ });

@@ -43,2 +43,3 @@ import type { AnonymousNode, Document } from '../';

isDescendantByUUIDList(uuidList: string[]): boolean;
toNormalizeString(): string;
}
"use strict";
var _MLDOMAbstractElement_fixedNodeName;
var _MLDOMAbstractElement_fixedNodeName, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, _MLDOMAbstractElement_normalizedString;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -18,2 +18,4 @@ const tslib_1 = require("tslib");

_MLDOMAbstractElement_fixedNodeName.set(this, void 0);
_MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache.set(this, null);
_MLDOMAbstractElement_normalizedString.set(this, null);
this.nodeName = astNode.nodeName;

@@ -117,3 +119,3 @@ (0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_fixedNodeName, astNode.nodeName, "f");

}
el = el.parentNode;
el = el.getParentElement();
} while (el !== null && el.type === 'Element');

@@ -150,3 +152,3 @@ return null;

matches(selector) {
return (0, helper_1.createSelector)(selector).match(this);
return !!(0, helper_1.createSelector)(selector).match(this);
}

@@ -157,2 +159,5 @@ fixNodeName(name) {

getChildElementsAndTextNodeWithoutWhitespaces() {
if ((0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, "f")) {
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, "f");
}
const filteredNodes = [];

@@ -171,2 +176,3 @@ this.childNodes.forEach(node => {

});
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache, filteredNodes, "f");
return filteredNodes;

@@ -181,3 +187,3 @@ }

isDescendantByUUIDList(uuidList) {
let el = this.parentNode;
let el = this.getParentElement();
if (el === null) {

@@ -190,8 +196,27 @@ return false;

}
el = el.parentNode;
el = el.getParentElement();
} while (el !== null && el.type === 'Element');
return false;
}
toNormalizeString() {
if ((0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_normalizedString, "f")) {
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMAbstractElement_normalizedString, "f");
}
const children = this.getChildElementsAndTextNodeWithoutWhitespaces();
const attrs = this.attributes.map(attr => attr.toNormalizeString());
const attrString = attrs.length ? ' ' + attrs.join('') : '';
const startTag = `<${this.nodeName}${attrString}>`;
const childNodes = children.map(node => {
if (node.type === 'Element') {
return node.toNormalizeString();
}
return node.originRaw;
});
const endTag = `</${this.nodeName}>`;
const normalizedString = `${startTag}${childNodes.join('')}${endTag}`;
(0, tslib_1.__classPrivateFieldSet)(this, _MLDOMAbstractElement_normalizedString, normalizedString, "f");
return normalizedString;
}
}
exports.default = MLDOMAbstractElement;
_MLDOMAbstractElement_fixedNodeName = new WeakMap();
_MLDOMAbstractElement_fixedNodeName = new WeakMap(), _MLDOMAbstractElement_getChildElementsAndTextNodeWithoutWhitespacesCache = new WeakMap(), _MLDOMAbstractElement_normalizedString = new WeakMap();

@@ -39,2 +39,3 @@ import type { MLASTHTMLAttr, MLToken } from '@markuplint/ml-ast';

toString(withSpace?: boolean): string;
toNormalizeString(): string;
}

@@ -72,3 +72,10 @@ "use strict";

}
toNormalizeString() {
return (this.name.originRaw +
this.equal.originRaw +
this.startQuote.originRaw +
this.value.originRaw +
this.endQuote.originRaw);
}
}
exports.default = MLDOMAttribute;
import type { Document } from '../';
import type { RuleInfo } from '../../';
import type { AnonymousNode, IMLDOMNode, NodeType } from '../types';
import type { MLDOMElement, MLDOMOmittedElement } from './';
import type { MLDOMElement, MLDOMOmittedElement, MLDOMPreprocessorSpecificBlock } from './';
import type { MLASTAbstructNode } from '@markuplint/ml-ast';

@@ -14,11 +14,12 @@ import type { AnyRule, RuleConfigValue } from '@markuplint/ml-config';

constructor(astNode: A, document: Document<T, O>);
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
get prevNode(): AnonymousNode<T, O> | null;
get nextNode(): AnonymousNode<T, O> | null;
get syntaxicalParentNode(): MLDOMElement<T, O> | null;
get syntaxicalParentNode(): MLDOMElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
get prevToken(): AnonymousNode<T, O> | null;
get nodeStore(): import("../helper").NodeStore;
get rule(): RuleInfo<T, O>;
getParentElement(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
is(type: NodeType): boolean;
toString(): string;
is(type: NodeType): boolean;
get rule(): RuleInfo<T, O>;
}

@@ -73,8 +73,2 @@ "use strict";

}
toString() {
return this.raw;
}
is(type) {
return this.type === type;
}
get rule() {

@@ -86,9 +80,26 @@ if (!(0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule) {

const rule = this.rules[name];
if (rule == null) {
throw new Error('Invalid call "rule" property.');
}
return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.optimizeOption(rule);
}
getParentElement() {
let parent = this.parentNode;
if (!parent) {
return null;
}
while (parent) {
if (parent.type === 'PSBlock') {
parent = parent.parentNode;
continue;
}
return parent;
}
return null;
}
is(type) {
return this.type === type;
}
toString() {
return this.raw;
}
}
exports.default = MLDOMNode;
_MLDOMNode_doc = new WeakMap(), _MLDOMNode_prevToken = new WeakMap();

@@ -23,2 +23,3 @@ import type { MLASTPreprocessorSpecificAttr } from '@markuplint/ml-ast';

toString(): string;
toNormalizeString(): string;
}

@@ -33,3 +33,6 @@ "use strict";

}
toNormalizeString() {
return this.raw;
}
}
exports.default = MLDOMPreprocessorSpecificAttribute;

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

import type { Ruleset } from '..';
import type Document from '../ml-dom/document';
import type { RuleSeed } from './types';
import type { LocaleSet } from '@markuplint/i18n';
import type { RuleConfig, RuleConfigValue, RuleInfo, Severity, Violation } from '@markuplint/ml-config';
import type { GlobalRuleInfo, RuleConfig, RuleConfigValue, RuleInfo, Rules, Severity, Violation } from '@markuplint/ml-config';
export declare class MLRule<T extends RuleConfigValue, O = null> {

@@ -25,4 +26,6 @@ #private;

verify(document: Document<T, O>, locale: LocaleSet, globalRule: RuleInfo<T, O>, fix: boolean): Promise<Violation[]>;
optimizeOption(configSettings: T | RuleConfig<T, O>): RuleInfo<T, O>;
getRuleInfo(ruleSet: Ruleset, ruleName: string): GlobalRuleInfo<T, O>;
_optimize(rules: Rules | undefined, ruleName: string): RuleInfo<T, O>;
optimizeOption(configSettings: T | RuleConfig<T, O> | undefined): RuleInfo<T, O>;
}
export declare type AnyMLRule = MLRule<RuleConfigValue, unknown>;

@@ -9,2 +9,3 @@ "use strict";

constructor(o) {
var _a, _b;
_MLRule_v.set(this, void 0);

@@ -14,4 +15,4 @@ _MLRule_f.set(this, void 0);

this.defaultServerity = o.defaultServerity || 'error';
this.defaultValue = o.defaultValue;
this.defaultOptions = o.defaultOptions;
this.defaultValue = (_a = o.defaultValue) !== null && _a !== void 0 ? _a : true;
this.defaultOptions = (_b = o.defaultOptions) !== null && _b !== void 0 ? _b : null;
(0, tslib_1.__classPrivateFieldSet)(this, _MLRule_v, o.verify, "f");

@@ -84,4 +85,17 @@ (0, tslib_1.__classPrivateFieldSet)(this, _MLRule_f, o.fix, "f");

}
getRuleInfo(ruleSet, ruleName) {
const info = this._optimize(ruleSet.rules, ruleName);
return {
...info,
nodeRules: ruleSet.nodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
childNodeRules: ruleSet.childNodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
};
}
_optimize(rules, ruleName) {
const rule = (rules && rules[ruleName]) || false;
const info = this.optimizeOption(rule);
return info;
}
optimizeOption(configSettings) {
if (typeof configSettings === 'boolean') {
if (configSettings === undefined || typeof configSettings === 'boolean') {
return {

@@ -88,0 +102,0 @@ disabled: !configSettings,

import type { MLRuleContext } from './ml-rule-context';
import type { RuleConfigValue, Severity } from '@markuplint/ml-config';
export declare type RuleSeed<T extends RuleConfigValue, O = null> = {
export declare type RuleSeed<T extends RuleConfigValue = boolean, O = null> = {
defaultServerity?: Severity;
defaultValue: T;
defaultOptions: O;
defaultValue?: T;
defaultOptions?: O;
verify(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;

@@ -8,0 +8,0 @@ fix?(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;

{
"rules": {
"attr-duplication": true,
"attr-equal-space-after": false,
"attr-equal-space-before": false,
"attr-spacing": false,
"attr-value-quotes": false,
"case-sensitive-attr-name": false,
"case-sensitive-tag-name": false,
"character-reference": true,
"class-naming": false,
"deprecated-attr": true,
"deprecated-element": true,
"disallowed-element": ["hgroup"],
"doctype": true,
"id-duplication": true,
"indentation": false,
"ineffective-attr": true,
"invalid-attr": {
"option": {
"attrs": {
"autofocus": {
"disallowed": true
},
"accesskey": {
"disallowed": true
}
}
}
},
"landmark-roles": true,
"no-boolean-attr-value": true,
"no-default-value": false,
"no-hard-code-id": false,
"no-refer-to-non-existent-id": true,
"no-use-event-handler-attr": false,
"permitted-contents": true,
"required-attr": true,
"invalid-attr": true,
"landmark-roles": true,
"required-element": false,
"required-h1": true,

@@ -18,3 +45,3 @@ "wai-aria": true

{
"selector": "html",
"selector": ":where(html)",
"rules": {

@@ -25,4 +52,42 @@ "required-attr": ["lang"]

{
"selector": "script[src]",
"selector": ":where(head)",
"rules": {
"required-element": ["meta[charset=\"UTF-8\" i]"]
}
},
{
"selector": ":where(meta[property])",
"rules": {
"invalid-attr": {
"option": {
"attrs": {
"property": {
"pattern": "/^og:[a-z_]+/"
},
"content": {
"type": "NoEmptyAny"
}
}
}
},
"required-attr": false
}
},
{
"selector": ":where(meta[itemprop])",
"rules": {
"invalid-attr": {
"option": {
"attrs": {
"content": {
"type": "NoEmptyAny"
}
}
}
}
}
},
{
"selector": ":where(script[src])",
"rules": {
"required-attr": ["defer"]

@@ -32,26 +97,94 @@ }

{
"selector": "img",
"selector": "h1, h2, h3, h4, h5, h6",
"rules": {
"required-attr": ["decoding", "width", "height", "alt"]
"disallowed-element": {
"value": ["small"],
"reason": "The small element must not be used for subheadings. https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-small-element"
}
}
},
{
"selector": "iframe",
"selector": ":where(img)",
"rules": {
"required-attr": ["loading", "title"]
"required-attr": [
"width",
"height",
"alt",
{
"name": "decoding",
"value": "async"
}
]
}
},
{
"selector": "a[target=_blank], area[target=_blank]",
"selector": ":where(iframe)",
"rules": {
"required-attr": ["rel"]
"required-attr": [
"title",
{
"name": "loading",
"value": "lazy"
}
]
}
},
{
"selector": "abbr",
"selector": ":where(a[target=_blank], area[target=_blank])",
"rules": {
"required-attr": [
{
"name": "rel",
"value": "noreferrer"
}
]
}
},
{
"selector": ":where(abbr)",
"rules": {
"required-attr": ["title"]
}
},
{
"selector": ":where(video, audio)",
"rules": {
"required-element": ["track"]
}
},
{
"selector": ":where(video[autoplay])",
"rules": {
"required-attr": ["muted"]
}
},
{
"selector": ":where(th, td)",
"rules": {
"invalid-attr": {
"option": {
"attrs": {
"span": {
"disallowed": false
}
}
}
}
}
},
{
"selector": ":where(body :not(button))",
"rules": {
"invalid-attr": {
"option": {
"attrs": {
"onclick": {
"disallowed": false
}
}
}
}
}
}
]
}
{
"name": "@markuplint/ml-core",
"version": "2.0.0-rc.0",
"version": "2.0.0-rc.1",
"description": "The core module of markuplint",

@@ -20,6 +20,6 @@ "repository": "git@github.com:markuplint/markuplint.git",

"dependencies": {
"@markuplint/i18n": "2.0.0-rc.0",
"@markuplint/ml-ast": "2.0.0-rc.0",
"@markuplint/ml-config": "2.0.0-rc.0",
"@markuplint/ml-spec": "2.0.0-rc.0",
"@markuplint/i18n": "2.0.0-rc.1",
"@markuplint/ml-ast": "2.0.0-rc.1",
"@markuplint/ml-config": "2.0.0-rc.1",
"@markuplint/ml-spec": "2.0.0-rc.1",
"debug": "^4.3.2",

@@ -30,6 +30,6 @@ "postcss-selector-parser": "^6.0.6",

"devDependencies": {
"@markuplint/html-parser": "2.0.0-rc.0",
"@markuplint/html-parser": "2.0.0-rc.1",
"@types/debug": "^4.1.7"
},
"gitHead": "67134f1addbdd271ad1d425de8f296d1875dbf25"
"gitHead": "34dbaf8bc5ee499315a32857c59b9c6f6bb73594"
}

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