diff --git a/package.json b/package.json index a1639d746..64e8f5eef 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-node-resolve": "^14.1.0", "@types/css-tree": "^2.0.0", - "@types/csso": "^5.0.0", + "@types/csso": "^5.0.1", "@types/jest": "^29.5.5", "del": "^6.0.0", "eslint": "^8.24.0", diff --git a/plugins/cleanupIds.js b/plugins/cleanupIds.js index 1d2532b20..32a26e608 100644 --- a/plugins/cleanupIds.js +++ b/plugins/cleanupIds.js @@ -10,7 +10,7 @@ const { referencesProps } = require('./_collections.js'); exports.name = 'cleanupIds'; exports.description = 'removes unused IDs and minifies used'; -const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/; +const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/g; const regReferencesHref = /^#(.+?)$/; const regReferencesBegin = /(\D+)\./; const generateIdChars = [ @@ -146,7 +146,7 @@ exports.fn = (_root, params) => { */ const nodeById = new Map(); /** - * @type {Map>} + * @type {Map>} */ const referencesById = new Map(); let deoptimized = false; @@ -191,34 +191,34 @@ exports.fn = (_root, params) => { } else { // collect all references /** - * @type {null | string} + * @type {string[]} */ - let id = null; + let ids = []; if (referencesProps.includes(name)) { - const match = value.match(regReferencesUrl); - if (match != null) { - id = match[2]; // url() reference + const matches = value.matchAll(regReferencesUrl); + for (const match of matches) { + ids.push(match[2]); // url() reference } } if (name === 'href' || name.endsWith(':href')) { const match = value.match(regReferencesHref); if (match != null) { - id = match[1]; // href reference + ids.push(match[1]); // href reference } } if (name === 'begin') { const match = value.match(regReferencesBegin); if (match != null) { - id = match[1]; // href reference + ids.push(match[1]); // href reference } } - if (id != null) { + for (const id of ids) { let refs = referencesById.get(id); if (refs == null) { refs = []; referencesById.set(id, refs); } - refs.push({ element: node, name, value }); + refs.push({ element: node, name }); } } } @@ -253,7 +253,8 @@ exports.fn = (_root, params) => { currentIdString = getIdString(currentId); } while (isIdPreserved(currentIdString)); node.attributes.id = currentIdString; - for (const { element, name, value } of refs) { + for (const { element, name } of refs) { + const value = element.attributes[name]; if (value.includes('#')) { // replace id in href and url() element.attributes[name] = value.replace( diff --git a/test/plugins/cleanupIds.22.svg b/test/plugins/cleanupIds.22.svg new file mode 100644 index 000000000..6f7665866 --- /dev/null +++ b/test/plugins/cleanupIds.22.svg @@ -0,0 +1,31 @@ +When two IDs are referenced in the same attribute. + +=== + + + + + + + + + + + + + + +@@@ + + + + + + + + + + + + + diff --git a/yarn.lock b/yarn.lock index 9e78c52a9..a220adeb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1009,12 +1009,12 @@ __metadata: languageName: node linkType: hard -"@types/csso@npm:^5.0.0": - version: 5.0.0 - resolution: "@types/csso@npm:5.0.0" +"@types/csso@npm:^5.0.1": + version: 5.0.1 + resolution: "@types/csso@npm:5.0.1" dependencies: "@types/css-tree": "*" - checksum: 4aba6f76c4b402cb045525773b18f86fba7f61dc8be451b6c94b926f99c1f83c5c4b3ec62c1423da6f75437b954c8b4eaf9c4008e7a85bb10dd892a8fc42a0ae + checksum: 62c7e534dfde79c1bf3b3761baec06ac2aa2b568da9be4a548b95e709b65b3944b8ad4cd4d8926de2b4bb301b4f102fb0f8c1354cb203a92ebccf59e58c957a6 languageName: node linkType: hard @@ -4725,7 +4725,7 @@ __metadata: "@rollup/plugin-node-resolve": ^14.1.0 "@trysound/sax": 0.2.0 "@types/css-tree": ^2.0.0 - "@types/csso": ^5.0.0 + "@types/csso": ^5.0.1 "@types/jest": ^29.5.5 commander: ^7.2.0 css-select: ^5.1.0