Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@shopify/theme-check-common

Package Overview
Dependencies
Maintainers
25
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/theme-check-common - npm Package Compare versions

Comparing version 1.18.1 to 1.18.2

7

CHANGELOG.md
# @shopify/theme-check-common
## 1.18.2
### Patch Changes
- fe54680: Fix `MissingAsset` false positives for .css.liquid, .js.liquid and .scss.liquid files
- e00c319: Fix false ParserBlockingScript reports for scripts of type module
## 1.18.1

@@ -4,0 +11,0 @@

21

dist/checks/missing-asset/index.js

@@ -29,9 +29,22 @@ "use strict";

return;
const expression = node.expression;
const assetPath = `assets/${expression.value}`;
const fileExists = await (0, file_utils_1.assertFileExists)(context, assetPath);
let expression = node.expression;
let originalAssetPath = `assets/${expression.value}`;
let assetPath = originalAssetPath;
let fileExists = await (0, file_utils_1.assertFileExists)(context, assetPath);
if (fileExists)
return;
if (assetPath.endsWith('.scss.css')) {
assetPath = assetPath.replace('.scss.css', '.scss.liquid');
fileExists = await (0, file_utils_1.assertFileExists)(context, assetPath);
if (fileExists)
return;
}
if (assetPath.endsWith('.js') || assetPath.endsWith('.css')) {
assetPath += '.liquid';
fileExists = await (0, file_utils_1.assertFileExists)(context, assetPath);
if (fileExists)
return;
}
context.report({
message: `'${assetPath}' does not exist`,
message: `'${originalAssetPath}' does not exist`,
startIndex: expression.position.start,

@@ -38,0 +51,0 @@ endIndex: expression.position.end,

@@ -61,3 +61,30 @@ "use strict";

});
(0, vitest_1.it)('should not report for compiled .js.liquid files', async () => {
const file = `{{ 'foo.js' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.js.liquid': 'console.log("{{ "hi" }}");',
};
const offenses = await (0, test_1.check)(files, [_1.MissingAsset]);
(0, vitest_1.expect)(offenses).to.have.length(0);
});
(0, vitest_1.it)('should not report for compiled .css.liquid files', async () => {
const file = `{{ 'foo.css' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.css.liquid': 'body { color: {{ "blue" }}; }',
};
const offenses = await (0, test_1.check)(files, [_1.MissingAsset]);
(0, vitest_1.expect)(offenses).to.have.length(0);
});
(0, vitest_1.it)('should not report for compiled .scss.liquid files', async () => {
const file = `{{ 'foo.scss.css' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.scss.liquid': 'html { & body { color: {{ "blue" }}; } }',
};
const offenses = await (0, test_1.check)(files, [_1.MissingAsset]);
(0, vitest_1.expect)(offenses).to.have.length(0);
});
});
//# sourceMappingURL=index.spec.js.map

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

.some((attr) => (0, utils_2.isAttr)(attr, 'async') || (0, utils_2.isAttr)(attr, 'defer'));
if (hasDeferOrAsync) {
const isTypeModule = node.attributes
.filter(utils_2.isValuedHtmlAttribute)
.some((attr) => (0, utils_2.isAttr)(attr, 'type') &&
((0, utils_2.hasAttributeValueOf)(attr, 'module') || (0, utils_2.hasAttributeValueOf)(attr, 'importmap')));
if (hasDeferOrAsync || isTypeModule) {
return;

@@ -67,0 +71,0 @@ }

@@ -157,4 +157,14 @@ "use strict";

});
(0, vitest_1.it)('should not report any offense when using scripts of type module', async () => {
const file = `
<script src="https://foo.bar/baz.js" type="module"></script>
<script src="https://foo.bar/baz.js" type="importmap"></script>
`;
const offenses = await (0, test_1.check)({
'code.liquid': file,
}, [_1.ParserBlockingScript]);
(0, vitest_1.expect)(offenses).to.have.length(0);
});
});
});
//# sourceMappingURL=index.spec.js.map

@@ -16,3 +16,4 @@ import { Position, NodeTypes, HtmlElement, AttrEmpty, AttrSingleQuoted, AttrDoubleQuoted, AttrUnquoted, LiquidHtmlNode } from '@shopify/liquid-html-parser';

export declare function valueIncludes(attr: ValuedHtmlAttribute, word: string): boolean;
export declare function hasAttributeValueOf(attr: ValuedHtmlAttribute, value: string): boolean;
export declare function isLiquidString(node: LiquidHtmlNode): node is NodeOfType<NodeTypes.String>;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isLiquidString = exports.valueIncludes = exports.isValuedHtmlAttribute = exports.isHtmlAttribute = exports.isAttr = exports.isHtmlTag = exports.isNodeOfType = void 0;
exports.isLiquidString = exports.hasAttributeValueOf = exports.valueIncludes = exports.isValuedHtmlAttribute = exports.isHtmlAttribute = exports.isAttr = exports.isHtmlTag = exports.isNodeOfType = void 0;
const liquid_html_parser_1 = require("@shopify/liquid-html-parser");

@@ -42,2 +42,8 @@ function isNodeOfType(type, node) {

exports.valueIncludes = valueIncludes;
function hasAttributeValueOf(attr, value) {
return (attr.value.length === 1 &&
isNodeOfType(liquid_html_parser_1.NodeTypes.TextNode, attr.value[0]) &&
attr.value[0].value === value);
}
exports.hasAttributeValueOf = hasAttributeValueOf;
function isLiquidString(node) {

@@ -44,0 +50,0 @@ return node.type === liquid_html_parser_1.NodeTypes.String;

2

package.json
{
"name": "@shopify/theme-check-common",
"version": "1.18.1",
"version": "1.18.2",
"license": "MIT",

@@ -5,0 +5,0 @@ "homepage": "https://github.com/Shopify/theme-tools/blob/main/packages/theme-check-common/README.md",

@@ -71,2 +71,38 @@ import { expect, describe, it } from 'vitest';

});
it('should not report for compiled .js.liquid files', async () => {
const file = `{{ 'foo.js' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.js.liquid': 'console.log("{{ "hi" }}");',
};
const offenses = await check(files, [MissingAsset]);
expect(offenses).to.have.length(0);
});
it('should not report for compiled .css.liquid files', async () => {
const file = `{{ 'foo.css' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.css.liquid': 'body { color: {{ "blue" }}; }',
};
const offenses = await check(files, [MissingAsset]);
expect(offenses).to.have.length(0);
});
it('should not report for compiled .scss.liquid files', async () => {
const file = `{{ 'foo.scss.css' | asset_url }} `;
const files = {
'snippets/snippet.liquid': file,
'assets/foo.scss.liquid': 'html { & body { color: {{ "blue" }}; } }',
};
const offenses = await check(files, [MissingAsset]);
expect(offenses).to.have.length(0);
});
});

@@ -29,9 +29,23 @@ import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';

const expression = node.expression;
const assetPath = `assets/${expression.value}`;
const fileExists = await assertFileExists(context, assetPath);
let expression = node.expression;
let originalAssetPath = `assets/${expression.value}`;
let assetPath = originalAssetPath;
let fileExists = await assertFileExists(context, assetPath);
if (fileExists) return;
if (assetPath.endsWith('.scss.css')) {
assetPath = assetPath.replace('.scss.css', '.scss.liquid');
fileExists = await assertFileExists(context, assetPath);
if (fileExists) return;
}
if (assetPath.endsWith('.js') || assetPath.endsWith('.css')) {
assetPath += '.liquid';
fileExists = await assertFileExists(context, assetPath);
if (fileExists) return;
}
context.report({
message: `'${assetPath}' does not exist`,
message: `'${originalAssetPath}' does not exist`,
startIndex: expression.position.start,

@@ -38,0 +52,0 @@ endIndex: expression.position.end,

@@ -210,3 +210,17 @@ import { expect, describe, it } from 'vitest';

});
it('should not report any offense when using scripts of type module', async () => {
const file = `
<script src="https://foo.bar/baz.js" type="module"></script>
<script src="https://foo.bar/baz.js" type="importmap"></script>
`;
const offenses = await reportOffenses(
{
'code.liquid': file,
},
[ParserBlockingScript],
);
expect(offenses).to.have.length(0);
});
});
});
import { NodeTypes } from '@shopify/liquid-html-parser';
import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types';
import { last } from '../../utils';
import { isAttr, isHtmlAttribute, isValuedHtmlAttribute } from '../utils';
import { hasAttributeValueOf, isAttr, isHtmlAttribute, isValuedHtmlAttribute } from '../utils';
import { liquidFilterSuggestion, scriptTagSuggestion } from './suggestions';

@@ -70,4 +70,11 @@

.some((attr) => isAttr(attr, 'async') || isAttr(attr, 'defer'));
const isTypeModule = node.attributes
.filter(isValuedHtmlAttribute)
.some(
(attr) =>
isAttr(attr, 'type') &&
(hasAttributeValueOf(attr, 'module') || hasAttributeValueOf(attr, 'importmap')),
);
if (hasDeferOrAsync) {
if (hasDeferOrAsync || isTypeModule) {
return;

@@ -74,0 +81,0 @@ }

@@ -72,4 +72,12 @@ import {

export function hasAttributeValueOf(attr: ValuedHtmlAttribute, value: string) {
return (
attr.value.length === 1 &&
isNodeOfType(NodeTypes.TextNode, attr.value[0]) &&
attr.value[0].value === value
);
}
export function isLiquidString(node: LiquidHtmlNode): node is NodeOfType<NodeTypes.String> {
return node.type === NodeTypes.String;
}

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

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