Files
rspade_system/node_modules/svgo/plugins/removeAttrs.js
root d523f0f600 Fix code quality violations and exclude Manifest from checks
Document application modes (development/debug/production)
Add global file drop handler, order column normalization, SPA hash fix
Serve CDN assets via /_vendor/ URLs instead of merging into bundles
Add production minification with license preservation
Improve JSON formatting for debugging and production optimization
Add CDN asset caching with CSS URL inlining for production builds
Add three-mode system (development, debug, production)
Update Manifest CLAUDE.md to reflect helper class architecture
Refactor Manifest.php into helper classes for better organization
Pre-manifest-refactor checkpoint: Add app_mode documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-14 10:38:22 +00:00

154 lines
4.1 KiB
JavaScript
Executable File

/**
* @typedef RemoveAttrsParams
* @property {string=} elemSeparator
* @property {boolean=} preserveCurrentColor
* @property {string | string[]} attrs
*/
export const name = 'removeAttrs';
export const description = 'removes specified attributes';
const DEFAULT_SEPARATOR = ':';
const ENOATTRS = `Warning: The plugin "removeAttrs" requires the "attrs" parameter.
It should have a pattern to remove, otherwise the plugin is a noop.
Config example:
plugins: [
{
name: "removeAttrs",
params: {
attrs: "(fill|stroke)"
}
}
]
`;
/**
* Remove attributes
*
* @example elemSeparator
* format: string
*
* @example preserveCurrentColor
* format: boolean
*
* @example attrs:
*
* format: [ element* : attribute* : value* ]
*
* element : regexp (wrapped into ^...$), single * or omitted > all elements (must be present when value is used)
* attribute : regexp (wrapped into ^...$)
* value : regexp (wrapped into ^...$), single * or omitted > all values
*
* examples:
*
* > basic: remove fill attribute
* ---
* removeAttrs:
* attrs: 'fill'
*
* > remove fill attribute on path element
* ---
* attrs: 'path:fill'
*
* > remove fill attribute on path element where value is none
* ---
* attrs: 'path:fill:none'
*
*
* > remove all fill and stroke attribute
* ---
* attrs:
* - 'fill'
* - 'stroke'
*
* [is same as]
*
* attrs: '(fill|stroke)'
*
* [is same as]
*
* attrs: '*:(fill|stroke)'
*
* [is same as]
*
* attrs: '.*:(fill|stroke)'
*
* [is same as]
*
* attrs: '.*:(fill|stroke):.*'
*
*
* > remove all stroke related attributes
* ----
* attrs: 'stroke.*'
*
*
* @author Benny Schudel
*
* @type {import('../lib/types.js').Plugin<RemoveAttrsParams>}
*/
export const fn = (root, params) => {
if (typeof params.attrs == 'undefined') {
console.warn(ENOATTRS);
return null;
}
const elemSeparator =
typeof params.elemSeparator == 'string'
? params.elemSeparator
: DEFAULT_SEPARATOR;
const preserveCurrentColor =
typeof params.preserveCurrentColor == 'boolean'
? params.preserveCurrentColor
: false;
const attrs = Array.isArray(params.attrs) ? params.attrs : [params.attrs];
return {
element: {
enter: (node) => {
for (let pattern of attrs) {
// if no element separators (:), assume it's attribute name, and apply to all elements *regardless of value*
if (!pattern.includes(elemSeparator)) {
pattern = ['.*', pattern, '.*'].join(elemSeparator);
// if only 1 separator, assume it's element and attribute name, and apply regardless of attribute value
} else if (pattern.split(elemSeparator).length < 3) {
pattern = [pattern, '.*'].join(elemSeparator);
}
// create regexps for element, attribute name, and attribute value
const list = pattern.split(elemSeparator).map((value) => {
// adjust single * to match anything
if (value === '*') {
value = '.*';
}
return new RegExp(['^', value, '$'].join(''), 'i');
});
// matches element
if (list[0].test(node.name)) {
// loop attributes
for (const [name, value] of Object.entries(node.attributes)) {
const isCurrentColor = value.toLowerCase() === 'currentcolor';
const isFillCurrentColor =
preserveCurrentColor && name == 'fill' && isCurrentColor;
const isStrokeCurrentColor =
preserveCurrentColor && name == 'stroke' && isCurrentColor;
if (
!isFillCurrentColor &&
!isStrokeCurrentColor &&
// matches attribute name
list[1].test(name) &&
// matches attribute value
list[2].test(value)
) {
delete node.attributes[name];
}
}
}
}
},
},
};
};