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

capsule-lint

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

capsule-lint - npm Package Compare versions

Comparing version 0.4.15 to 0.4.16

2

package.json
{
"name": "capsule-lint",
"version": "0.4.15",
"version": "0.4.16",
"description": "The official Capsule linting package.",

@@ -5,0 +5,0 @@ "type": "module",

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

import { Reporter } from 'htmlhint';
import { Block } from 'htmlhint/htmlparser';

@@ -5,2 +6,79 @@ import { Rule } from 'htmlhint/types';

function isMatchingTag(tagName: string, tag: string) {
return !!tag.match(new RegExp(`^<${tagName}`));
}
type Tag = {
open: boolean
raw: string;
tagName: string
event: Block;
};
class BlockTag {
parent?: BlockTag;
openTag?: Tag;
closeTag?: Tag;
children: BlockTag[];
constructor(tag?: Tag, parent?: BlockTag) {
if(tag && tag.open) {
this.openTag = tag;
}
else if(tag && !tag.open) {
this.closeTag = tag;
}
this.parent = parent;
this.children = [];
}
}
function createTree(stack: Tag[]) {
const root: BlockTag = new BlockTag();
let currentTag: BlockTag = root;
for(const tag of stack) {
if(tag.open) {
currentTag.children.push(
currentTag = new BlockTag(tag, currentTag)
);
}
else if(!tag.open && currentTag.openTag?.tagName === tag.tagName) {
currentTag.closeTag = tag;
currentTag = currentTag.parent
}
else {
currentTag.children.push(new BlockTag(tag, currentTag.parent ?? root));
}
}
return root;
}
function lintTree(nodes: BlockTag[], reporter: Reporter, rule: Rule) {
for(const node of nodes) {
if(node.children) {
lintTree(node.children, reporter, rule)
}
if(node.openTag && node.closeTag) {
continue;
}
else if(node.openTag) {
reporter.error(
`Tag [${node.openTag.raw}] is missing a closing tag: [</${node.openTag.tagName}>]`,
node.openTag.event.line,
node.openTag.event.col,
rule,
node.openTag.raw
);
}
else if(node.closeTag) {
reporter.error(`Tag must be paired, no start tag: [ ${node.closeTag.raw} ]`, node.closeTag.event.line, node.closeTag.event.col, rule, node.closeTag.event.raw);
}
}
}
const rule: Rule = {

@@ -10,15 +88,19 @@ id: 'freemarker-tags',

init(parser, reporter) {
const stack: {
tag: string,
event: Block
}[] = [];
const stack: Tag[] = [];
const blockTags = ['#if', '#list'];
const pattern = new RegExp(`^<(${blockTags.join('|')})`)
parser.addListener('text', (event) => {
try {
for(const tag of parse(event.raw)) {
if(tag.match(pattern)) {
stack.push({ tag, event });
const match = tag.match(pattern);
if(match) {
stack.push({
event,
raw: tag,
tagName: match[1],
open: true
});
}

@@ -45,13 +127,12 @@ }

if(!stack.length) {
reporter.error(`Conditional must be paired, no start tag: [ ${event.raw} ]`, event.line, event.col, this, event.raw);
}
stack.pop();
stack.push({
raw: event.raw,
tagName: event.tagName,
event,
open: false
});
});
parser.addListener('end', () => {
for(const { tag, event } of stack) {
reporter.error(`Tag [${tag}] is missing a closing tag: [</${tag.match(pattern)[1]}>]`, event.line, event.col, this, event.raw)
}
lintTree(createTree(stack).children, reporter, this);
})

@@ -58,0 +139,0 @@ },

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

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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