Anonymous
Извлеките CSS из SVG и переместите его в отдельный файл [закрыто]
Сообщение
Anonymous » 17 июл 2024, 09:09
mkdir каталог-вашего-проекта
cd каталог-вашего-проекта
mkdir svgs
npm init -y
npm install xmldom
нажмите имя_скрипта.js
Код: Выделить всё
const fs = require('fs');
const path = require('path');
const { DOMParser, XMLSerializer } = require('xmldom');
// Function to generate unique class names
let classCounter = 0;
const generateClassName = () => `svg-class-${classCounter++}`;
// Function to convert SVG styles to classes and return the modified SVG and extracted CSS
function convertSVGStylesToClasses(svgString, uniqueSuffix) {
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
let styles = "";
let index = 0;
let existingClasses = {};
traverseNodes(svgDoc.documentElement);
extractStyleElements(svgDoc);
function traverseNodes(node) {
if (node.nodeType === 1) { // Element node
const attributes = ["fill", "stroke", "stroke-width"];
let style = "";
let hasStyle = false;
attributes.forEach(attr => {
if (node.hasAttribute(attr)) {
style += `${attr}: ${node.getAttribute(attr)}; `;
node.removeAttribute(attr);
hasStyle = true;
}
});
// Process existing class attributes
if (node.hasAttribute("class")) {
const existingClass = node.getAttribute("class").trim();
if (existingClass) {
const newClass = existingClasses[existingClass] || `svg-class-${uniqueSuffix}-${index++}`;
node.setAttribute("class", newClass);
existingClasses[existingClass] = newClass;
}
}
if (node.hasAttribute('style')) {
const inlineStyle = node.getAttribute('style');
style += `${inlineStyle} `;
node.removeAttribute('style');
hasStyle = true;
}
if (hasStyle) {
const className = `svg-class-${uniqueSuffix}-${index++}`;
node.setAttribute("class", className);
styles += `.${className} { ${style} }\n`;
}
}
// Recursively traverse child nodes
for (let child = node.firstChild; child; child = child.nextSibling) {
traverseNodes(child);
}
}
const modifiedSVG = new XMLSerializer().serializeToString(svgDoc);
return { svg: modifiedSVG, css: styles };
function extractStyleElements(svgDoc) {
// Append existing styles from tags
const existingStyles = svgDoc.getElementsByTagName('style');
for (let i = 0; i < existingStyles.length; i++) {
const styleContent = existingStyles[i].textContent.trim();
styles += styleContent.replace(/(\.)([a-zA-Z0-9_-]+)/g, (match, prefix, className) => {
if (existingClasses.hasOwnProperty(className)) {
return `${prefix}${existingClasses[className]}`;
}
const newClassName = `svg-class-${uniqueSuffix}-${index++}`;
existingClasses[className] = newClassName;
return `${prefix}${newClassName}`;
}) + '\n';
existingStyles[i].parentNode.removeChild(existingStyles[i]);
}
// const styleElement = svgDoc.createElementNS("http://www.w3.org/2000/svg", "style");
// styleElement.textContent = styles;
// svgDoc.documentElement.insertBefore(styleElement, svgDoc.documentElement.firstChild);
}
}
// Function to process SVG files in a directory and save processed files in another directory
function processSVGFiles(inputDirectory, outputDirectory) {
const files = fs.readdirSync(inputDirectory).filter(file => path.extname(file) === '.svg');
let combinedStyles = "";
files.forEach((file, fileIndex) => {
const filePath = path.join(inputDirectory, file);
const svgContent = fs.readFileSync(filePath, 'utf-8');
const uniqueSuffix = `file${fileIndex}`;
const { svg: modifiedSVG, css, existingClasses } = convertSVGStylesToClasses(svgContent, uniqueSuffix);
// combinedStyles += css;
if(existingClasses){
// Replace existing class names in SVG content
Object.keys(existingClasses).forEach(existingClass => {
const regex = new RegExp(`\\.${existingClass}`, 'g');
modifiedSVG = modifiedSVG.replace(regex, `.${existingClasses[existingClass]}`);
});
}
const outputFilePath = path.join(outputDirectory, file); // Use original filename
fs.writeFileSync(outputFilePath, modifiedSVG, 'utf-8');
console.log(`Processed ${file}`);
// Append CSS for this file to combined styles
combinedStyles += css.replace(/(\.)([a-zA-Z0-9_-]+)/g, (match, prefix, className) => {
if (existingClasses && existingClasses.hasOwnProperty(className)) {
return `${prefix}${existingClasses[className]}`;
}
return match;
});
});
const cssFilePath = path.join(outputDirectory, 'combined_styles.css');
fs.writeFileSync(cssFilePath, combinedStyles, 'utf-8');
console.log(`Combined styles written to ${cssFilePath}`);
}
// Specify the input and output directories
const inputDirectory = './svgs';
const outputDirectory = './processed_svgs';
// Create the output directory if it doesn't exist
if (!fs.existsSync(outputDirectory)) {
fs.mkdirSync(outputDirectory);
}
// Process SVG files from inputDirectory and save processed files to outputDirectory
processSVGFiles(inputDirectory, outputDirectory);
каталог-вашего-проекта/
│
├── svgs/
│ ├── svg1.svg
│ ├── svg2.svg
│ ├── svg3.svg
│ └── ... (другие ваши файлы SVG)
│
├── node_modules/
│ └── ... (генерируется после запуска npm install)
│
├── package.json
│
├── имя_скрипта.js
│
└── Combined_styles.css (генерируется сценарием)
Пожалуйста, проверьте, работает это или нет
пробовал несколько способов для
Код: Выделить всё
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { AngularWebpackPlugin } = require('@ngtools/webpack');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body',
}),
new AngularWebpackPlugin({
tsconfig: './tsconfig.app.json',
directTemplateLoading: false,
}),
function () {
this.hooks.compilation.tap('HtmlWebpackPluginHooks', (compilation) => {
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(
'NonceTag',
(data, cb) => {
['scripts', 'headTags'].forEach((section) => {
data[section].forEach((tag) => {
if (tag.tagName === 'script') {
tag.attributes.nonce = 'your_actual_nonce_value'; // Replace with your actual nonce value
}
});
});
cb(null, data);
}
);
});
},
],
};
{
"projects": {
"your-project-name": {
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.config.js"
},
"outputPath": "dist/your-project-name",
"index": "src/index.html",
// other options...
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"customWebpackConfig": {
"path": "./webpack.config.js"
}
}
}
}
}
}
}
Подробнее здесь:
https://stackoverflow.com/questions/787 ... erate-file
1721196562
Anonymous
mkdir каталог-вашего-проекта cd каталог-вашего-проекта mkdir svgs npm init -y npm install xmldom нажмите имя_скрипта.js [code]const fs = require('fs'); const path = require('path'); const { DOMParser, XMLSerializer } = require('xmldom'); // Function to generate unique class names let classCounter = 0; const generateClassName = () => `svg-class-${classCounter++}`; // Function to convert SVG styles to classes and return the modified SVG and extracted CSS function convertSVGStylesToClasses(svgString, uniqueSuffix) { const parser = new DOMParser(); const svgDoc = parser.parseFromString(svgString, "image/svg+xml"); let styles = ""; let index = 0; let existingClasses = {}; traverseNodes(svgDoc.documentElement); extractStyleElements(svgDoc); function traverseNodes(node) { if (node.nodeType === 1) { // Element node const attributes = ["fill", "stroke", "stroke-width"]; let style = ""; let hasStyle = false; attributes.forEach(attr => { if (node.hasAttribute(attr)) { style += `${attr}: ${node.getAttribute(attr)}; `; node.removeAttribute(attr); hasStyle = true; } }); // Process existing class attributes if (node.hasAttribute("class")) { const existingClass = node.getAttribute("class").trim(); if (existingClass) { const newClass = existingClasses[existingClass] || `svg-class-${uniqueSuffix}-${index++}`; node.setAttribute("class", newClass); existingClasses[existingClass] = newClass; } } if (node.hasAttribute('style')) { const inlineStyle = node.getAttribute('style'); style += `${inlineStyle} `; node.removeAttribute('style'); hasStyle = true; } if (hasStyle) { const className = `svg-class-${uniqueSuffix}-${index++}`; node.setAttribute("class", className); styles += `.${className} { ${style} }\n`; } } // Recursively traverse child nodes for (let child = node.firstChild; child; child = child.nextSibling) { traverseNodes(child); } } const modifiedSVG = new XMLSerializer().serializeToString(svgDoc); return { svg: modifiedSVG, css: styles }; function extractStyleElements(svgDoc) { // Append existing styles from tags const existingStyles = svgDoc.getElementsByTagName('style'); for (let i = 0; i < existingStyles.length; i++) { const styleContent = existingStyles[i].textContent.trim(); styles += styleContent.replace(/(\.)([a-zA-Z0-9_-]+)/g, (match, prefix, className) => { if (existingClasses.hasOwnProperty(className)) { return `${prefix}${existingClasses[className]}`; } const newClassName = `svg-class-${uniqueSuffix}-${index++}`; existingClasses[className] = newClassName; return `${prefix}${newClassName}`; }) + '\n'; existingStyles[i].parentNode.removeChild(existingStyles[i]); } // const styleElement = svgDoc.createElementNS("http://www.w3.org/2000/svg", "style"); // styleElement.textContent = styles; // svgDoc.documentElement.insertBefore(styleElement, svgDoc.documentElement.firstChild); } } // Function to process SVG files in a directory and save processed files in another directory function processSVGFiles(inputDirectory, outputDirectory) { const files = fs.readdirSync(inputDirectory).filter(file => path.extname(file) === '.svg'); let combinedStyles = ""; files.forEach((file, fileIndex) => { const filePath = path.join(inputDirectory, file); const svgContent = fs.readFileSync(filePath, 'utf-8'); const uniqueSuffix = `file${fileIndex}`; const { svg: modifiedSVG, css, existingClasses } = convertSVGStylesToClasses(svgContent, uniqueSuffix); // combinedStyles += css; if(existingClasses){ // Replace existing class names in SVG content Object.keys(existingClasses).forEach(existingClass => { const regex = new RegExp(`\\.${existingClass}`, 'g'); modifiedSVG = modifiedSVG.replace(regex, `.${existingClasses[existingClass]}`); }); } const outputFilePath = path.join(outputDirectory, file); // Use original filename fs.writeFileSync(outputFilePath, modifiedSVG, 'utf-8'); console.log(`Processed ${file}`); // Append CSS for this file to combined styles combinedStyles += css.replace(/(\.)([a-zA-Z0-9_-]+)/g, (match, prefix, className) => { if (existingClasses && existingClasses.hasOwnProperty(className)) { return `${prefix}${existingClasses[className]}`; } return match; }); }); const cssFilePath = path.join(outputDirectory, 'combined_styles.css'); fs.writeFileSync(cssFilePath, combinedStyles, 'utf-8'); console.log(`Combined styles written to ${cssFilePath}`); } // Specify the input and output directories const inputDirectory = './svgs'; const outputDirectory = './processed_svgs'; // Create the output directory if it doesn't exist if (!fs.existsSync(outputDirectory)) { fs.mkdirSync(outputDirectory); } // Process SVG files from inputDirectory and save processed files to outputDirectory processSVGFiles(inputDirectory, outputDirectory); [/code] каталог-вашего-проекта/ │ ├── svgs/ │ ├── svg1.svg │ ├── svg2.svg │ ├── svg3.svg │ └── ... (другие ваши файлы SVG) │ ├── node_modules/ │ └── ... (генерируется после запуска npm install) │ ├── package.json │ ├── имя_скрипта.js │ └── Combined_styles.css (генерируется сценарием) Пожалуйста, проверьте, работает это или нет пробовал несколько способов для [code]const HtmlWebpackPlugin = require('html-webpack-plugin'); const { AngularWebpackPlugin } = require('@ngtools/webpack'); module.exports = { plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', inject: 'body', }), new AngularWebpackPlugin({ tsconfig: './tsconfig.app.json', directTemplateLoading: false, }), function () { this.hooks.compilation.tap('HtmlWebpackPluginHooks', (compilation) => { HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync( 'NonceTag', (data, cb) => { ['scripts', 'headTags'].forEach((section) => { data[section].forEach((tag) => { if (tag.tagName === 'script') { tag.attributes.nonce = 'your_actual_nonce_value'; // Replace with your actual nonce value } }); }); cb(null, data); } ); }); }, ], }; { "projects": { "your-project-name": { "architect": { "build": { "builder": "@angular-builders/custom-webpack:browser", "options": { "customWebpackConfig": { "path": "./webpack.config.js" }, "outputPath": "dist/your-project-name", "index": "src/index.html", // other options... } }, "serve": { "builder": "@angular-builders/custom-webpack:dev-server", "options": { "customWebpackConfig": { "path": "./webpack.config.js" } } } } } } }[/code] Подробнее здесь: [url]https://stackoverflow.com/questions/78734755/extract-css-from-svg-and-move-it-to-seperate-file[/url]