@shopify/shop-minis-react
Version:
React component library for Shopify Shop Minis with Tailwind CSS v4 support (source-only, requires TypeScript)
134 lines (118 loc) • 3.61 kB
JavaScript
/**
* ESLint rule wrapper for eslint-plugin-no-secrets with custom messages
* and URL-aware delimiter handling
*/
const noSecretsPlugin = require('eslint-plugin-no-secrets')
// Get the original rule
const originalRule = noSecretsPlugin.rules['no-secrets']
/**
* Create a context-like object that overrides options while delegating
* all other property access to the original context
*/
function createContextWithOptions(context, newOptions) {
const wrapper = Object.create(context)
Object.defineProperty(wrapper, 'options', {
value: newOptions,
writable: false,
enumerable: true,
configurable: true,
})
return wrapper
}
const sharedIgnoreList = [
'^data:', // Data URLs (base64 images, fonts, etc.)
'^gid://', // Shopify GraphQL IDs
'gid%3A%2F%2F', // Shopify GraphQL IDs (URL encoded)
'^blob:', // Blob URLs from URL.createObjectURL()
]
const urlIgnoreList = [
// Video platforms
'youtube\\.com',
'youtu\\.be',
'vimeo\\.com',
'player\\.vimeo\\.com',
'tiktok\\.com',
'twitch\\.tv',
'dailymotion\\.com',
'wistia\\.com',
// Image CDNs
'imagedelivery\\.net',
'cloudinary\\.com',
'res\\.cloudinary\\.com',
'imgix\\.net',
'unsplash\\.com',
'images\\.unsplash\\.com',
'pexels\\.com',
'images\\.pexels\\.com',
// Placeholder services
'placehold\\.co',
'placeholder\\.com',
'via\\.placeholder\\.com',
'placekitten\\.com',
'picsum\\.photos',
'loremflickr\\.com',
'dummyimage\\.com',
// Cloud storage
'storage\\.googleapis\\.com',
'commondatastorage\\.googleapis\\.com',
's3\\.amazonaws\\.com',
's3\\.[a-z0-9-]+\\.amazonaws\\.com',
'blob\\.core\\.windows\\.net',
// E-commerce CDNs
'cdn\\.shopify\\.com',
'shopifycdn\\.com',
// Social media embeds
'instagram\\.com',
'twitter\\.com',
'x\\.com',
'facebook\\.com',
'pinterest\\.com',
]
module.exports = {
meta: {
...originalRule.meta,
messages: {
HIGH_ENTROPY:
'This string may be a hardcoded credential, which should never be committed. Please check the Shop Minis documentation learn how to handle these cases. You can disable this rule if it is not a credential.',
PATTERN_MATCH:
'Potential {{ name }} detected. Hardcoded credentials should never be committed. Please check the Shop Minis documentation learn how to handle these cases. You can disable this rule if it is not a credential.',
},
},
create(context) {
const baseOptions = context.options[0] || {}
// Visitor for NON-URLs: shared patterns only, skip URLs
const nonUrlContext = createContextWithOptions(context, [
{
...baseOptions,
ignoreContent: [
...(baseOptions.ignoreContent || []),
...sharedIgnoreList,
'^https?://',
],
},
])
const nonUrlVisitor = originalRule.create(nonUrlContext)
// Visitor for URLs ONLY: shared + URL patterns, with URL delimiters
const urlContext = createContextWithOptions(context, [
{
...baseOptions,
ignoreContent: [
...(baseOptions.ignoreContent || []),
...sharedIgnoreList,
...urlIgnoreList,
'^(?!https?://)',
],
additionalDelimiters: ['/', '\\?', '=', '&', '\\+'],
},
])
const urlVisitor = originalRule.create(urlContext)
// Only process Literal nodes - skip TemplateElement to avoid false positives
// on template expressions like `${variable}` which get split incorrectly
return {
Literal(node) {
nonUrlVisitor.Literal?.(node)
urlVisitor.Literal?.(node)
},
}
},
}