Issue
I have a project where part of the code is written in SASS. I want to get rid of SASS and work with vanilla CSS, so I'm trying to find a programatic way to turn all my SASS parts into CSS, or at least having a way to do it programatically in each component that I'm working on. At the end of the process, I would remove all SASS dependencies and have just CSS in my code.
Any hints will be appreciated, thanks in advance!
Edit:
The SASS/SCSS is written in component, pages and layout .vue files inside a <style lang="sass"> or <style lang="scss"> tag. Inside them, there are some imports with the format
@import './folder/css/stuff';
.head-navigation
Edit 2: Proposed solution doesn't work due to error
Error: Invalid CSS after "@import './folder/css/stuff';": expected 1 selector or at-rule, was ".head-navigation"\n
check live example here
Solution
As per your comment and code, I can surmise, you want to conver only the part of vue file which has sass/scss code inside of it. If I had to achieve this requirement, I would write a custom script which:
- would iterate over all the
.vuefiles. - find if there is a style tag with language as
sass. - Replace the content with compiled
csscode.
For achieving above steps I will be using three packages.
- node-sass: For converting
sass/scsscode tocss. - fs-extra: For file-handling and as an alternative to native
fsmodule. You can go ahead withfsmodule as well. - vue-template-compiler: A parser which understands Vue components. Here, I could have used
regexas well but usually it's not a good idea to parse a language using regular expressions. Why? It has to do with some theoretical concepts of computation. Please read this post.
This is how it looks in code:
// convert-sass.js
const fs = require('fs-extra');
const path = require('path');
const sass = require('node-sass');
const compiler = require('vue-template-compiler');
const vueDirectory = './src'; // path to all your .vue files.
function convertSASSinVueFiles(dir) {
// 1. iterate over all files inside the directory with .vue extension
fs.readdirSync(dir).forEach(file => {
const filePath = path.join(dir, file);
if (fs.lstatSync(filePath).isDirectory()) {
convertSASSinVueFiles(filePath);
} else if (path.extname(file) === '.vue') {
convertSASSinVueComponent(filePath);
}
});
}
function convertSASSinVueComponent(file) {
const content = fs.readFileSync(file, 'utf8');
// Parse the vue file
const parsedComponent = compiler.parseComponent(content);
/* 2. Find if there is a style tag with the lang attribute as sass.
You can modify this as per your need. */
if (parsedComponent.styles.length > 0 &&
(parsedComponent.styles[0].lang === 'sass' ||
parsedComponent.styles[0].lang === 'scss')) {
const sassCode = parsedComponent.styles[0].content;
// convert the sass code to css.
const cssCode = sass.renderSync(
{
data: sassCode,
includePaths: ['./path/to/your/partials']
}
).css.toString();
// Replace the sass content with css code.
const updatedContent = content.
replace(/<style.*lang="s[ac]ss".*>([\s\S]*?)<\/style>/,
`<style>${cssCode}</style>`);
fs.writeFileSync(file, updatedContent);
}
}
convertSASSinVueFiles(vueDirectory);
NOTE 1: The replace regex i.e. /<style.*lang="s[ac]ss".*>([\s\S]*?)<\/style>/ currently checks for both scss and sass syntaxes. You can adjust it as per your need.
NOTE 2: In case you're using partials, you just need to include one of the properties which is provided by scss-compiler i.e. includePaths option to the compiler.
EDIT:
Initially, the code that I provided would convert all .scss syntax to .css one. Now looking at your latest comment, it can be seen that you're using .sass syntax and not .scss syntax. You can refer this post to read the difference between their syntax. In short, one uses indentation and other uses curly braces just like our css rules do.
However, a good news is that there is a single compiler which can convert both the syntaxes and we're already using that initially. You just need to provide an extra option to renderSync() function i.e. indentedSyntax and set it's value to true. Something like:
const isSass = parsedComponent.styles[0].lang === 'sass';
const cssCode = sass.renderSync(
{
data: sassCode,
includePaths: ['./path/to/your/partials'],
indentedSyntax: isSass // set to true for sass syntax
}
).css.toString();
NOTE 3: You might also want to tweak the path of partials inside your includePaths option as per your requirement. Note, if you provide includePath option with paths, the compiler would look inside that specific directory for the partials and would ignore the relative path inside your @import rule. For example, say I provided ./src/sass to the array of includePaths option and in my scss/sass code if the partial is imported as @import './src/sass/someDir/typography'; I would get an error of file not found. For this particular case you might want to remove the includePaths option from the script.
Answered By - mandy8055
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.