routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+177
@@ -0,0 +1,177 @@
|
||||
'use strict';
|
||||
|
||||
const require_runtime = require('../_virtual/_rolldown/runtime.js');
|
||||
const require_index = require('../utils/index.js');
|
||||
|
||||
//#region lib/rules/use-v-on-exact.js
|
||||
/**
|
||||
* @fileoverview enforce usage of `exact` modifier on `v-on`.
|
||||
* @author Armano
|
||||
*/
|
||||
var require_use_v_on_exact = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
||||
/**
|
||||
* @typedef { {name: string, node: VDirectiveKey, modifiers: string[] } } EventDirective
|
||||
*/
|
||||
const utils = require_index.default;
|
||||
const SYSTEM_MODIFIERS = new Set([
|
||||
"ctrl",
|
||||
"shift",
|
||||
"alt",
|
||||
"meta"
|
||||
]);
|
||||
const GLOBAL_MODIFIERS = new Set([
|
||||
"stop",
|
||||
"prevent",
|
||||
"capture",
|
||||
"self",
|
||||
"once",
|
||||
"passive",
|
||||
"native"
|
||||
]);
|
||||
/**
|
||||
* Finds and returns all keys for event directives
|
||||
*
|
||||
* @param {VStartTag} startTag Element startTag
|
||||
* @param {SourceCode} sourceCode The source code object.
|
||||
* @returns {EventDirective[]} [{ name, node, modifiers }]
|
||||
*/
|
||||
function getEventDirectives(startTag, sourceCode) {
|
||||
return utils.getDirectives(startTag, "on").map((attribute) => ({
|
||||
name: attribute.key.argument ? sourceCode.getText(attribute.key.argument) : "",
|
||||
node: attribute.key,
|
||||
modifiers: attribute.key.modifiers.map((modifier) => modifier.name)
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Checks whether given modifier is key modifier
|
||||
*
|
||||
* @param {string} modifier
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isKeyModifier(modifier) {
|
||||
return !GLOBAL_MODIFIERS.has(modifier) && !SYSTEM_MODIFIERS.has(modifier);
|
||||
}
|
||||
/**
|
||||
* Checks whether given modifier is system one
|
||||
*
|
||||
* @param {string} modifier
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isSystemModifier(modifier) {
|
||||
return SYSTEM_MODIFIERS.has(modifier);
|
||||
}
|
||||
/**
|
||||
* Checks whether given any of provided modifiers
|
||||
* has system modifier
|
||||
*
|
||||
* @param {string[]} modifiers
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasSystemModifier(modifiers) {
|
||||
return modifiers.some(isSystemModifier);
|
||||
}
|
||||
/**
|
||||
* Groups all events in object,
|
||||
* with keys represinting each event name
|
||||
*
|
||||
* @param {EventDirective[]} events
|
||||
* @returns { { [key: string]: EventDirective[] } } { click: [], keypress: [] }
|
||||
*/
|
||||
function groupEvents(events) {
|
||||
/** @type { { [key: string]: EventDirective[] } } */
|
||||
const grouped = {};
|
||||
for (const event of events) {
|
||||
if (!grouped[event.name]) grouped[event.name] = [];
|
||||
grouped[event.name].push(event);
|
||||
}
|
||||
return grouped;
|
||||
}
|
||||
/**
|
||||
* Creates alphabetically sorted string with system modifiers
|
||||
*
|
||||
* @param {string[]} modifiers
|
||||
* @returns {string} e.g. "alt,ctrl,del,shift"
|
||||
*/
|
||||
function getSystemModifiersString(modifiers) {
|
||||
return modifiers.filter(isSystemModifier).sort().join(",");
|
||||
}
|
||||
/**
|
||||
* Creates alphabetically sorted string with key modifiers
|
||||
*
|
||||
* @param {string[]} modifiers
|
||||
* @returns {string} e.g. "enter,tab"
|
||||
*/
|
||||
function getKeyModifiersString(modifiers) {
|
||||
return modifiers.filter(isKeyModifier).sort().join(",");
|
||||
}
|
||||
/**
|
||||
* Compares two events based on their modifiers
|
||||
* to detect possible event leakeage
|
||||
*
|
||||
* @param {EventDirective} baseEvent
|
||||
* @param {EventDirective} event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasConflictedModifiers(baseEvent, event) {
|
||||
if (event.node === baseEvent.node || event.modifiers.includes("exact")) return false;
|
||||
const eventKeyModifiers = getKeyModifiersString(event.modifiers);
|
||||
const baseEventKeyModifiers = getKeyModifiersString(baseEvent.modifiers);
|
||||
if (eventKeyModifiers && baseEventKeyModifiers && eventKeyModifiers !== baseEventKeyModifiers) return false;
|
||||
const eventSystemModifiers = getSystemModifiersString(event.modifiers);
|
||||
const baseEventSystemModifiers = getSystemModifiersString(baseEvent.modifiers);
|
||||
return baseEvent.modifiers.length > 0 && baseEventSystemModifiers !== eventSystemModifiers && baseEventSystemModifiers.includes(eventSystemModifiers);
|
||||
}
|
||||
/**
|
||||
* Searches for events that might conflict with each other
|
||||
*
|
||||
* @param {EventDirective[]} events
|
||||
* @returns {EventDirective[]} conflicted events, without duplicates
|
||||
*/
|
||||
function findConflictedEvents(events) {
|
||||
/** @type {EventDirective[]} */
|
||||
const conflictedEvents = [];
|
||||
for (const event of events) conflictedEvents.push(...events.filter((evt) => !conflictedEvents.includes(evt)).filter(hasConflictedModifiers.bind(null, event)));
|
||||
return conflictedEvents;
|
||||
}
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
docs: {
|
||||
description: "enforce usage of `exact` modifier on `v-on`",
|
||||
categories: ["vue3-essential", "vue2-essential"],
|
||||
url: "https://eslint.vuejs.org/rules/use-v-on-exact.html"
|
||||
},
|
||||
fixable: null,
|
||||
schema: [],
|
||||
messages: { considerExact: "Consider to use '.exact' modifier." }
|
||||
},
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
return utils.defineTemplateBodyVisitor(context, { VStartTag(node) {
|
||||
if (node.attributes.length === 0) return;
|
||||
const isCustomComponent = utils.isCustomComponent(node.parent);
|
||||
let events = getEventDirectives(node, sourceCode);
|
||||
if (isCustomComponent) events = events.filter((event) => event.modifiers.includes("native"));
|
||||
const grouppedEvents = groupEvents(events);
|
||||
for (const eventName of Object.keys(grouppedEvents)) {
|
||||
const eventsInGroup = grouppedEvents[eventName];
|
||||
if (!eventsInGroup.some((event) => hasSystemModifier(event.modifiers))) continue;
|
||||
const conflictedEvents = findConflictedEvents(eventsInGroup);
|
||||
for (const e of conflictedEvents) context.report({
|
||||
node: e.node,
|
||||
loc: e.node.loc,
|
||||
messageId: "considerExact"
|
||||
});
|
||||
}
|
||||
} });
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
//#endregion
|
||||
Object.defineProperty(exports, 'default', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return require_use_v_on_exact();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user