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
.vue
files. - find if there is a style tag with language as
sass
. - Replace the content with compiled
css
code.
For achieving above steps I will be using three packages.
- node-sass: For converting
sass/scss
code tocss
. - fs-extra: For file-handling and as an alternative to native
fs
module. You can go ahead withfs
module as well. - vue-template-compiler: A parser which understands Vue components. Here, I could have used
regex
as 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.