Galerie und tage

This commit is contained in:
2021-11-23 17:56:26 +01:00
parent ff35366279
commit 5f873bee89
4693 changed files with 149659 additions and 301447 deletions

View File

@@ -9,16 +9,13 @@ exports.description = 'removes unused IDs and minifies used';
exports.params = {
remove: true,
minify: true,
prefix: '',
preserve: [],
preservePrefixes: [],
force: false
prefix: ''
};
var referencesProps = new Set(require('./_collections').referencesProps),
var referencesProps = require('./_collections').referencesProps,
regReferencesUrl = /\burl\(("|')?#(.+?)\1\)/,
regReferencesHref = /^#(.+?)$/,
regReferencesBegin = /(\w+)\./,
regReferencesBegin = /^(\w+?)\./,
styleOrScript = ['style', 'script'],
generateIDchars = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
@@ -36,15 +33,13 @@ var referencesProps = new Set(require('./_collections').referencesProps),
* @author Kir Belevich
*/
exports.fn = function(data, params) {
var currentID,
currentIDstring,
IDs = new Map(),
referencesIDs = new Map(),
hasStyleOrScript = false,
preserveIDs = new Set(Array.isArray(params.preserve) ? params.preserve : params.preserve ? [params.preserve] : []),
preserveIDPrefixes = new Set(Array.isArray(params.preservePrefixes) ? params.preservePrefixes : (params.preservePrefixes ? [params.preservePrefixes] : [])),
idValuePrefix = '#',
idValuePostfix = '.';
IDs = Object.create(null),
referencesIDs = Object.create(null),
idPrefix = 'id-', // prefix IDs so that values like '__proto__' don't break the work
hasStyleOrScript = false;
/**
* Bananas!
@@ -53,66 +48,71 @@ exports.fn = function(data, params) {
* @return {Array} output items
*/
function monkeys(items) {
for (var i = 0; i < items.content.length && !hasStyleOrScript; i++) {
var item = items.content[i];
// quit if <style> or <script> present ('force' param prevents quitting)
if (!params.force) {
if (item.isElem(styleOrScript)) {
hasStyleOrScript = true;
continue;
}
// Don't remove IDs if the whole SVG consists only of defs.
if (item.isElem('defs') && item.parentNode.isElem('svg')) {
var hasDefsOnly = true;
for (var j = i + 1; j < items.content.length; j++) {
if (items.content[j].isElem()) {
hasDefsOnly = false;
break;
}
}
if (hasDefsOnly) {
break;
}
}
for (var i = 0; i < items.content.length && !hasStyleOrScript; i++) {
var item = items.content[i],
match;
// check if <style> of <script> presents
if (item.isElem(styleOrScript)) {
hasStyleOrScript = true;
continue;
}
// …and don't remove any ID if yes
if (item.isElem()) {
item.eachAttr(function(attr) {
var key, match;
item.eachAttr(function(attr) {
var key;
// save IDs
if (attr.name === 'id') {
key = attr.value;
if (IDs.has(key)) {
item.removeAttr('id'); // remove repeated id
key = idPrefix + attr.value;
if (key in IDs) {
item.removeAttr('id');
} else {
IDs.set(key, item);
IDs[key] = item;
}
return;
}
// save references
if (referencesProps.has(attr.name) && (match = attr.value.match(regReferencesUrl))) {
key = match[2]; // url() reference
} else if (
// save IDs url() references
else if (referencesProps.indexOf(attr.name) > -1) {
match = attr.value.match(regReferencesUrl);
if (match) {
key = idPrefix + match[2];
if (referencesIDs[key]) {
referencesIDs[key].push(attr);
} else {
referencesIDs[key] = [attr];
}
}
}
// save IDs href references
else if (
attr.local === 'href' && (match = attr.value.match(regReferencesHref)) ||
attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
) {
key = match[1]; // href reference
}
if (key) {
var ref = referencesIDs.get(key) || [];
ref.push(attr);
referencesIDs.set(key, ref);
key = idPrefix + match[1];
if (referencesIDs[key]) {
referencesIDs[key].push(attr);
} else {
referencesIDs[key] = [attr];
}
}
});
}
// go deeper
if (item.content) {
monkeys(item);
}
}
return items;
}
data = monkeys(data);
@@ -121,55 +121,43 @@ exports.fn = function(data, params) {
return data;
}
const idPreserved = id => preserveIDs.has(id) || idMatchesPrefix(preserveIDPrefixes, id);
for (var k in referencesIDs) {
if (IDs[k]) {
for (var ref of referencesIDs) {
var key = ref[0];
if (IDs.has(key)) {
// replace referenced IDs with the minified ones
if (params.minify && !idPreserved(key)) {
do {
currentIDstring = getIDstring(currentID = generateID(currentID), params);
} while (idPreserved(currentIDstring));
if (params.minify) {
IDs.get(key).attr('id').value = currentIDstring;
currentIDstring = getIDstring(currentID = generateID(currentID), params);
IDs[k].attr('id').value = currentIDstring;
referencesIDs[k].forEach(function(attr) {
k = k.replace(idPrefix, '');
attr.value = attr.value
.replace('#' + k, '#' + currentIDstring)
.replace(k + '.', currentIDstring + '.');
});
for (var attr of ref[1]) {
attr.value = attr.value.includes(idValuePrefix) ?
attr.value.replace(idValuePrefix + key, idValuePrefix + currentIDstring) :
attr.value.replace(key + idValuePostfix, currentIDstring + idValuePostfix);
}
}
// don't remove referenced IDs
IDs.delete(key);
delete IDs[idPrefix + k];
}
}
// remove non-referenced IDs attributes from elements
if (params.remove) {
for(var keyElem of IDs) {
if (!idPreserved(keyElem[0])) {
keyElem[1].removeAttr('id');
}
for(var ID in IDs) {
IDs[ID].removeAttr('id');
}
}
return data;
};
/**
* Check if an ID starts with any one of a list of strings.
*
* @param {Array} of prefix strings
* @param {String} current ID
* @return {Boolean} if currentID starts with one of the strings in prefixArray
*/
function idMatchesPrefix(prefixArray, currentID) {
if (!currentID) return false;
for (var prefix of prefixArray) if (currentID.startsWith(prefix)) return true;
return false;
}
/**
* Generate unique minimal ID.
*
@@ -177,6 +165,7 @@ function idMatchesPrefix(prefixArray, currentID) {
* @return {Array} generated ID array
*/
function generateID(currentID) {
if (!currentID) return [0];
currentID[currentID.length - 1]++;
@@ -190,11 +179,14 @@ function generateID(currentID) {
}
}
}
if (currentID[0] > maxIDindex) {
currentID[0] = 0;
currentID.unshift(0);
}
return currentID;
}
/**
@@ -204,6 +196,13 @@ function generateID(currentID) {
* @return {String} output ID string
*/
function getIDstring(arr, params) {
var str = params.prefix;
return str + arr.map(i => generateIDchars[i]).join('');
arr.forEach(function(i) {
str += generateIDchars[i];
});
return str;
}