@html-eslint/eslint-plugin
Advanced tools
| const { RULE_CATEGORY } = require("../constants"); | ||
| const { NodeUtils } = require("./utils"); | ||
| const MESSAGE_IDS = { | ||
| UNEXPECTED: "unexpected", | ||
| }; | ||
| module.exports = { | ||
| meta: { | ||
| type: "code", | ||
| docs: { | ||
| description: | ||
| 'Disallow use of `user-scalable=no` in `<meta name="viewport">`.', | ||
| category: RULE_CATEGORY.ACCESSIBILITY, | ||
| recommended: false, | ||
| }, | ||
| fixable: null, | ||
| schema: [], | ||
| messages: { | ||
| [MESSAGE_IDS.UNEXPECTED]: "unexpected use of `user-scalable=no`.", | ||
| }, | ||
| }, | ||
| create(context) { | ||
| return { | ||
| Meta(node) { | ||
| const nameAttr = NodeUtils.findAttr(node, "name"); | ||
| const contentAttr = NodeUtils.findAttr(node, "content"); | ||
| if ( | ||
| nameAttr && | ||
| contentAttr && | ||
| nameAttr.value.toLowerCase() === "viewport" && | ||
| contentAttr.value.match(/user-scalable\s*=\s*no/i) | ||
| ) { | ||
| context.report({ | ||
| node: contentAttr, | ||
| messageId: MESSAGE_IDS.UNEXPECTED, | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; |
| const { RULE_CATEGORY } = require("../constants"); | ||
| const { NodeUtils } = require("./utils"); | ||
| const MESSAGE_IDS = { | ||
| UNEXPECTED: "unexpected", | ||
| }; | ||
| module.exports = { | ||
| meta: { | ||
| type: "code", | ||
| docs: { | ||
| description: "Disallow use of positive `tabindex`.", | ||
| category: RULE_CATEGORY.ACCESSIBILITY, | ||
| recommended: false, | ||
| }, | ||
| fixable: null, | ||
| schema: [], | ||
| messages: { | ||
| [MESSAGE_IDS.UNEXPECTED]: "Unexpected use of positive `tabindex`.", | ||
| }, | ||
| }, | ||
| create(context) { | ||
| return { | ||
| "*"(node) { | ||
| const tabIndexAttr = NodeUtils.findAttr(node, "tabindex"); | ||
| if (tabIndexAttr && parseInt(tabIndexAttr.value, 10) > 0) { | ||
| context.report({ | ||
| node: tabIndexAttr, | ||
| messageId: MESSAGE_IDS.UNEXPECTED, | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; |
| const { RULE_CATEGORY } = require("../constants"); | ||
| const { NodeUtils } = require("./utils"); | ||
| const MESSAGE_IDS = { | ||
| MISSING: "missing", | ||
| UNEXPECTED: "unexpected", | ||
| }; | ||
| module.exports = { | ||
| meta: { | ||
| type: "code", | ||
| docs: { | ||
| description: "Require `title` in `<frame>`, `<iframe>`", | ||
| category: RULE_CATEGORY.ACCESSIBILITY, | ||
| recommended: false, | ||
| }, | ||
| fixable: false, | ||
| schema: [], | ||
| messages: { | ||
| [MESSAGE_IDS.MISSING]: "Missing `title` attribute in {{frame}}", | ||
| [MESSAGE_IDS.UNEXPECTED]: "Unexpected empty `title`.", | ||
| }, | ||
| }, | ||
| create(context) { | ||
| return { | ||
| "Frame, Iframe"(node) { | ||
| const title = NodeUtils.findAttr(node, "title"); | ||
| if (!title) { | ||
| context.report({ | ||
| node: node.startTag, | ||
| messageId: MESSAGE_IDS.MISSING, | ||
| }); | ||
| } else if (title.value.trim().length === 0) { | ||
| context.report({ | ||
| node: title, | ||
| messageId: MESSAGE_IDS.UNEXPECTED, | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; |
| const { RULE_CATEGORY, NODE_TYPES } = require("../constants"); | ||
| const { NodeUtils } = require("./utils"); | ||
| const MESSAGE_IDS = { | ||
| MISSING: "missing", | ||
| EMPTY: "empty", | ||
| }; | ||
| module.exports = { | ||
| meta: { | ||
| type: "code", | ||
| docs: { | ||
| description: 'Require use of `<meta name="description">` in `<head>`', | ||
| category: RULE_CATEGORY.SEO, | ||
| recommended: false, | ||
| }, | ||
| fixable: null, | ||
| schema: [], | ||
| messages: { | ||
| [MESSAGE_IDS.MISSING]: 'Missing `<meta name="description">`.', | ||
| [MESSAGE_IDS.EMPTY]: | ||
| 'Unexpected emtpy `conetnt` in `<meta name="description">`', | ||
| }, | ||
| }, | ||
| create(context) { | ||
| return { | ||
| Head(node) { | ||
| const metaTags = (node.childNodes || []).filter( | ||
| (child) => child.type === NODE_TYPES.META | ||
| ); | ||
| const descripMetaTags = metaTags.filter((meta) => { | ||
| const nameAttr = NodeUtils.findAttr(meta, "name"); | ||
| return !!nameAttr && nameAttr.value.toLowerCase() === "description"; | ||
| }); | ||
| if (descripMetaTags.length === 0) { | ||
| context.report({ | ||
| node, | ||
| messageId: MESSAGE_IDS.MISSING, | ||
| }); | ||
| } else { | ||
| descripMetaTags.forEach((meta) => { | ||
| const content = NodeUtils.findAttr(meta, "content"); | ||
| if (!content || !content.value.trim().length) { | ||
| context.report({ | ||
| node: content || meta, | ||
| messageId: MESSAGE_IDS.EMPTY, | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; |
| const { RULE_CATEGORY, NODE_TYPES } = require("../constants"); | ||
| const { NodeUtils } = require("./utils"); | ||
| const MESSAGE_IDS = { | ||
| MISSING: "missing", | ||
| EMPTY: "empty", | ||
| }; | ||
| module.exports = { | ||
| meta: { | ||
| type: "code", | ||
| docs: { | ||
| description: 'Enforce to use `<meta name="viewport">` in `<head>`', | ||
| category: RULE_CATEGORY.ACCESSIBILITY, | ||
| recommended: false, | ||
| }, | ||
| fixable: null, | ||
| schema: [], | ||
| messages: { | ||
| [MESSAGE_IDS.MISSING]: 'Missing `<meta name="viewport">`.', | ||
| [MESSAGE_IDS.EMPTY]: | ||
| 'Unexpected empty `content` attribute in `<meta name="viewport">`.', | ||
| }, | ||
| }, | ||
| create(context) { | ||
| function isMetaViewport(node) { | ||
| if (node.type === NODE_TYPES.META) { | ||
| const nameAttr = NodeUtils.findAttr(node, "name"); | ||
| return nameAttr.value.toLowerCase() === "viewport"; | ||
| } | ||
| return false; | ||
| } | ||
| return { | ||
| Head(node) { | ||
| const metaViewport = (node.childNodes || []).find(isMetaViewport); | ||
| if (!metaViewport) { | ||
| context.report({ | ||
| node, | ||
| messageId: MESSAGE_IDS.MISSING, | ||
| }); | ||
| return; | ||
| } | ||
| const contentAttr = NodeUtils.findAttr(metaViewport, "content"); | ||
| if (!contentAttr || !contentAttr.value.length) { | ||
| context.report({ | ||
| node: contentAttr, | ||
| messageId: MESSAGE_IDS.EMPTY, | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; |
@@ -15,2 +15,3 @@ /** | ||
| SCRIPT: "Script", | ||
| META: "Meta", | ||
| }; |
@@ -0,1 +1,5 @@ | ||
| /** | ||
| * @typedef {import("../types").HTMLNode} HTMLNode | ||
| */ | ||
| const { RULE_CATEGORY, NODE_TYPES } = require("../constants"); | ||
@@ -13,3 +17,3 @@ | ||
| docs: { | ||
| description: "Enforce newline between elements", | ||
| description: "Enforce newline between elements.", | ||
| category: RULE_CATEGORY.STYLE, | ||
@@ -90,10 +94,16 @@ recommended: true, | ||
| /** | ||
| * Checks whether two nodes are on the same line or not. | ||
| * @param {HTMLNode} nodeBefore A node before | ||
| * @param {HTMLNode} nodeAfter A node after | ||
| * @returns {boolean} `true` if two nodes are on the same line, otherwise `false`. | ||
| */ | ||
| function isOnTheSameLine(nodeBefore, nodeAfter) { | ||
| return ( | ||
| nodeBefore && | ||
| nodeAfter && | ||
| nodeBefore.loc && | ||
| nodeAfter.loc && | ||
| nodeBefore.loc.end.line === nodeAfter.loc.start.line | ||
| ); | ||
| if (nodeBefore && nodeAfter) { | ||
| if (nodeBefore.endTag) { | ||
| return nodeBefore.endTag.loc.end.line === nodeAfter.loc.start.line; | ||
| } | ||
| return nodeBefore.loc.start.line === nodeAfter.loc.start.line; | ||
| } | ||
| return false; | ||
| } |
+10
-0
@@ -17,2 +17,7 @@ const requireLang = require("./require-lang"); | ||
| const requireClosingTags = require("./require-closing-tags"); | ||
| const requireMetaDescription = require("./require-meta-description"); | ||
| const requireFrameTitle = require("./require-frame-title"); | ||
| const noNonScalableViewport = require("./no-non-scalable-viewport"); | ||
| const noPositiveTabindex = require("./no-positive-tabindex"); | ||
| const requireMetaViewport = require("./require-meta-viewport"); | ||
@@ -36,2 +41,7 @@ module.exports = { | ||
| "require-closing-tags": requireClosingTags, | ||
| "require-meta-description": requireMetaDescription, | ||
| "require-frame-title": requireFrameTitle, | ||
| "no-non-scalable-viewport": noNonScalableViewport, | ||
| "no-positive-tabindex": noPositiveTabindex, | ||
| "require-meta-viewport": requireMetaViewport, | ||
| }; |
| const { RULE_CATEGORY } = require("../constants"); | ||
| const MESSAGE_IDS = { | ||
| MISSING_DOCTYPE: "missingDoctype", | ||
| MISSING: "missing", | ||
| }; | ||
@@ -20,3 +20,3 @@ | ||
| messages: { | ||
| [MESSAGE_IDS.MISSING_DOCTYPE]: "Missing `<!DOCTYPE HTML>`", | ||
| [MESSAGE_IDS.MISSING]: "Missing `<!DOCTYPE HTML>`", | ||
| }, | ||
@@ -35,5 +35,5 @@ }, | ||
| node, | ||
| messageId: MESSAGE_IDS.MISSING_DOCTYPE, | ||
| messageId: MESSAGE_IDS.MISSING, | ||
| fix(fixer) { | ||
| return fixer.insertTextBefore(node, "<!DOCTYPE html>\n"); | ||
| return fixer.insertTextBeforeRange([0, 0], "<!DOCTYPE html>\n"); | ||
| }, | ||
@@ -40,0 +40,0 @@ }); |
+1
-0
@@ -17,2 +17,3 @@ export type RuleCategory = { | ||
| SCRIPT: "Script"; | ||
| META: "Meta"; | ||
| }; | ||
@@ -19,0 +20,0 @@ |
+3
-3
| { | ||
| "name": "@html-eslint/eslint-plugin", | ||
| "version": "0.6.5", | ||
| "version": "0.7.0", | ||
| "description": "ESLint plugin for html", | ||
@@ -42,5 +42,5 @@ "author": "yeonjuan", | ||
| "devDependencies": { | ||
| "@html-eslint/parser": "^0.6.0" | ||
| "@html-eslint/parser": "^0.7.0" | ||
| }, | ||
| "gitHead": "db6c66935e2ee0e2a5febce3f51bc7cc1bb589e0" | ||
| "gitHead": "a88f7f4b5199ead03455753d07a6f8669dc46427" | ||
| } |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
47644
16.61%37
15.63%1727
15.91%