Webpack compilation issue with sass template in vue single file component - vue.js

I am upgrading to webpack-4 from webpack 2.
It is breaking at places where my vue single file component has sass template in it.
It seems like sass loader is not coming into picture when file extension is vue.
I tried addidng sass as an extension in the webpack config, but it started treating vue files as sass files and compilation started breaking.
This is the generated error.
All the files having error have sass template in vue SFC.
ERROR in ./public/vue/applicationform/Academic.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/Academic.vue?vue&type=style&index=0&lang=sass&) 51:0
Module parse failed: Unexpected character '#' (51:0)
You may need an appropriate loader to handle this file type.
|
|
> #situation
| font-family: 'Avenir', Helvetica, Arial, sans-serif
| -webkit-font-smoothing: antialiased
# ./public/vue/applicationform/Academic.vue?vue&type=style&index=0&lang=sass& 1:0-135 1:151-154 1:156-288 1:156-288
# ./public/vue/applicationform/Academic.vue
# ./node_modules/babel-loader/lib??ref--0!./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue
# ./public/vue/applicationform.js
ERROR in ./public/vue/applicationform/Workex.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/Workex.vue?vue&type=style&index=0&lang=sass&) 715:0
Module parse failed: Unexpected character '#' (715:0)
You may need an appropriate loader to handle this file type.
|
|
> #situation
| font-family: 'Avenir', Helvetica, Arial, sans-serif
| -webkit-font-smoothing: antialiased
# ./public/vue/applicationform/Workex.vue?vue&type=style&index=0&lang=sass& 1:0-133 1:149-152 1:154-284 1:154-284
# ./public/vue/applicationform/Workex.vue
# ./node_modules/babel-loader/lib??ref--0!./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue
# ./public/vue/applicationform.js
ERROR in ./public/vue/applicationform/Kra.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/Kra.vue?vue&type=style&index=0&lang=sass&) 73:0
Module parse failed: Unexpected character '#' (73:0)
You may need an appropriate loader to handle this file type.
|
|
> #situation
| font-family: 'Avenir', Helvetica, Arial, sans-serif
| -webkit-font-smoothing: antialiased
# ./public/vue/applicationform/Kra.vue?vue&type=style&index=0&lang=sass& 1:0-130 1:146-149 1:151-278 1:151-278
# ./public/vue/applicationform/Kra.vue
# ./node_modules/babel-loader/lib??ref--0!./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue?vue&type=script&lang=js&
# ./public/vue/applicationform/App.vue
# ./public/vue/applicationform.js
ERROR in ./public/vue/applicationform/App.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/applicationform/App.vue?vue&type=style&index=0&lang=sass&) 1062:0
Module parse failed: Unexpected token (1062:0)
You may need an appropriate loader to handle this file type.
|
|
> .passive-day
| pointer-events: none;
| #app
# ./public/vue/applicationform/App.vue?vue&type=style&index=0&lang=sass& 1:0-130 1:146-149 1:151-278 1:151-278
# ./public/vue/applicationform/App.vue
# ./public/vue/applicationform.js
ERROR in ./public/vue/onboard/Onboard.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/onboard/Onboard.vue?vue&type=style&index=0&lang=sass&) 1065:0
Module parse failed: Unexpected token (1065:0)
You may need an appropriate loader to handle this file type.
|
|
> .cov-datepicker:hover
| border: 2px solid #d3d3d3 !important;
| .cov-datepicker:focus
# ./public/vue/onboard/Onboard.vue?vue&type=style&index=0&lang=sass& 1:0-134 1:150-153 1:155-286 1:155-286
# ./public/vue/onboard/Onboard.vue
# ./public/vue/onboard.js
ERROR in ./public/vue/reconboard/RecOnboard.vue?vue&type=style&index=1&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/reconboard/RecOnboard.vue?vue&type=style&index=1&lang=sass&) 1090:0
Module parse failed: Unexpected token (1090:0)
You may need an appropriate loader to handle this file type.
|
|
> .class1
| background-color: red;
| .class2
# ./public/vue/reconboard/RecOnboard.vue?vue&type=style&index=1&lang=sass& 1:0-137 1:153-156 1:158-292 1:158-292
# ./public/vue/reconboard/RecOnboard.vue
# ./public/vue/reconboard.js
ERROR in ./public/vue/console/Console.vue?vue&type=style&index=0&lang=sass& (./node_modules/vue-loader/lib??vue-loader-options!./public/vue/console/Console.vue?vue&type=style&index=0&lang=sass&) 1787:0
Module parse failed: Unexpected token (1787:0)
You may need an appropriate loader to handle this file type.
|
|
> .class1
| border: solid !important
| border-color: red !important
# ./public/vue/console/Console.vue?vue&type=style&index=0&lang=sass& 1:0-134 1:150-153 1:155-286 1:155-286
# ./public/vue/console/Console.vue
# ./public/vue/editp.js
This is my webpack configuration file
module.exports = {
mode : process.env.NODE_ENV || 'development',
context: __dirname + "/public/vue",
entry: {kras: "./applicationform.js", edit: "./editp.js", reconboard: "./reconboard.js", jobpost: "./jobPost.js", register: "./register.js",
onboard: "./onboard.js", signin: "./signin.js", recdash : "./recDash.js", consent : "./consent.js", onboardconsent : "./onboardconsent.js",
projectscreen: "./projectscreen.js" },
plugins: [
new CleanWebpackPlugin(['public/dist']),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "[name].bundle.js",
chunkFilename: "[name].[chunkhash].js"
}),
],
output: {
path: __dirname + "/public/dist",
filename: "[name].bundle.js",
chunkFilename: "[name].[chunkhash].js"
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins : ['lodash'],
}
},
{
test: /\.pug$/,
oneOf: [
{
resourceQuery: /^\?vue/,
use: ['pug-plain-loader']
},
{
use: ['raw-loader', 'pug-plain-loader']
}
],
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.(scss|css)$/,
oneOf: [
{
resourceQuery: /lang=sass/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader',
]
},
{
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
},
{
test: /\.vue$/,
loader : 'vue-loader',
options : {
loaders : {
scss: 'vue-style-loader!css-loader!sass-loader',
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}
}
},
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['.js', '.jsx', '.css'],
modules: [
__dirname + '/public/vue',
'./node_modules'
]
},
devServer: {
historyApiFallback: true,
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 3000,
disableHostCheck: true,
hot: true
},
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
},
minimizer: [new UglifyJsPlugin()]
}
}
This is my vue code
<template lang="pug">
// My pug Code over her
</template>
<script>
// My script over here
</script>
<style lang="sass">
#app
font-family: 'Avenir', Helvetica, Arial, sans-serif
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
text-align: center
color: #2c3e50
margin-top: 60px
h1, h2
font-weight: normal
ul
list-style-type: none
padding: 0
li
display: inline-block
margin: 0 10px
a
color: #42b983
.list-enter-active, .list-leave-active
transition: all 1s
.list-enter, .list-leave-to
opacity: 0
transform: translateY(30px)
</style>

Related

How to use sass global variables from other components in vite/vue3

I want to use and change global variables from other components, my files structure looks like this...
I have my variables in global.sass file, but I can't access variables in other components.
You need to set configuration file vite.config.js :
css: {
preprocessorOptions: {
scss: {
additionalData: `#import "#/assets/global.scss";`
}
}
},
also for local fonts you can add another configuration there, set alias:
resolve: {
alias: {
'#': path.resolve(__dirname, 'src'),
}
},
and then use it something like:
#font-face {
font-family: 'Opensans-Bold';
font-style: normal;
src: local('Opensans-Bold'), url(#/assets/fonts/OpenSans-Bold.woff2) format('woff2');
}
Nikola's answer is correct. For any Nuxt3 users out there I'd like to add you need to make sure you don't have explicit css config in your nuxt config file at the same time. Otherwise you might get file already imported error
A new sass module system
Note: The Sass team discourages the continued use of the #import rule. Sass
will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the #use rule instead. (Note that only Dart Sass currently supports #use. Users of other implementations must use the #import rule instead.)
More details: Here
Below is the best way to global scss at that time.
vite.config.js
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `#use "~/styles/_main.scss" as *;`,
},
},
},
plugins: [vue()],
});
styles/abstracts/_colors.scss
$default: #000000;
$default-light: #333333;
$default-dark: #000000;
styles/abstracts/index.scss
#forward './colors';
#forward ...
styles/_main.scss
#forward './abstracts';
#forward './components';
#forward './layouts';
src/index.scss => don't forget to add this import "./index.scss" in App.vue
#forward './styles/abstracts';
#use './styles/abstracts' as *;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
font-family: $font-primary;
font-size: 1.6rem;
line-height: 1.5;
text-rendering: optimizespeed;
color: $text;
overflow-y: overlay;
}

Storybook with vue - SassError: Undefined variable

I am using storybook with Vue. I have some common SCSS I want to use.
I am using the addon in **main.js**
addons: [
'#storybook/preset-scss'
],
This seems to automatically pick up ./src/scss/variables.scss which for testing I have added
body {
border: 10px solid green;
}
This works and hot reloads too the issue is any variables are not found in my components.
So my story list.stories.js imports the list component
import List from '../components/List.vue'
but within the style block I am trying use a var from the variables.scss.
<style lang="scss" scoped>
.list {
border: 1px solid $light-blue;
}
</style>
And get the error
SassError: Undefined variable: "$light-blue".
on line 204 of components/src/components/List.vue
>> border: 2px solid $light-blue;
In main.js add sass-loader to webpack config:
module.exports = {
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: '../src/scss/variables.scss',
},
},
],
});
return config;
}
}
It works with installed css-loader#5, sass-loader#10 and style-loader#2.
If scss is not working, then you can load styles by creating preview-head.html file at config/storybook/preview-head.html
And then just load your CSS there. For example:
<link rel="stylesheet" href="./assets/css/style.css">
<link rel="stylesheet" href="./assets/css/media-screen.css">
Make sure to restart Storybook dev server. npm run storybook:serve

Vuetify how to override sass variable for pagination component

I am having some issue while modifying the existing sass variables inside my vue application.
I have gone through a few SO questions where there are good amount of information on overriding the existing sass variables but nothing seems be working for me. I am pretty sure I am doing some thing wrong.
I have implemented a custom pagination control which works fine but I want to override the sass variables for it so that the size of pagination control button would be little smaller than the default button size.
This is my webpack.config.js
//webapack.config.js
module.exports = {
module: {
rules: [
// SASS has different line endings than SCSS
// and cannot use semicolons in the markup
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
// Requires sass-loader#^7.0.0
options: {
// This is the path to your variables
data: "#import '#/scss/variables.scss'"
},
// Requires sass-loader#^8.0.0
options: {
// This is the path to your variables
prependData: "#import '#/scss/variables.scss'"
},
},
],
},
// SCSS has different line endings than SASS
// and needs a semicolon after the import.
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
// Requires sass-loader#^7.0.0
options: {
// This is the path to your variables
data: "#import '#/scss/variables.scss';"
},
// Requires sass-loader#^8.0.0
options: {
// This is the path to your variables
prependData: "#import '#/scss/variables.scss';"
},
},
],
},
],
},
}
Following is the variables.scss inside src/scss directory, I use it to override the font-family and stuff.
// src/scss/variables.scss
#import url("https://fonts.googleapis.com/css?family=Hind+Siliguri:400,500,600,700&display=swap");
$body-font-family: "Hind Siliguri", sans-serif !important;
$typoOptions: display-4, display-3, display-2, display-1, headline, title,
subtitle-1, subtitle-2, body-1, body-2, caption, overline;
#app {
font-family: $body-font-family, sans-serif !important;
#each $typoOption in $typoOptions {
.#{$typoOption} {
font-family: $body-font-family, sans-serif !important;
}
}
}
// $pagination-item-font-size: 2px !important;
// $pagination-item-height: 10px !important;
// $pagination-item-margin: 1px !important;
// $pagination-item-min-width: 10px !important;
// $pagination-item-padding: 0 10px !important;
// $pagination-more-height: x !important;
// $pagination-navigation-height: 10px !important;
// $pagination-navigation-width: 10px !important;
#import "~vuetify/src/styles/styles.sass";
I want to override the sass variables given by vuetify but when I add them variables.scss (commented line on the above code), it doesn't work for some reason. Any help or pointer is much appreciated.
.v-pagination__item {
height: 25px;
min-width: 25px;
margin: 0px !important;
padding: 0px !important;
font-size: 14px;
}
try use this class, and for nav
.v-pagination__navigation
it work for me
I faced a similar problem with the total visible pages not being consistent. A work around is to create logic based upon data set size and update a reactive property for the column size.

NUXTJS + Vuetify - Colors in SCSS

I'm trying to get the colors from the nuxt.config.js file and put them directly in variables.scss
Currently my variables.scss look like this
#import '~vuetify/src/styles/styles.sass';
.button-blue {
background-color: map-get($blue, darken-2) !important;
color: map-get($blue-grey, lighten-5) !important;
}
I would like to assign the color directly from nuxt.config, more or less this way:
#import '~vuetify/src/styles/styles.sass';
.button-blue {
background-color: primary!important;
color: seconday !important;
}
My nuxt.config.js
css: ['~/assets/variables.scss'],
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: false,
themes: {
light: {
primary: colors.blue.darken2,
secondary: colors.orange.darken1,
tertiary: colors.green.darken1,
accent: colors.shades.black,
error: colors.red.accent3,
info: colors.green.darken3,
background: '#EAEBEE'
},
dark: {
primary: colors.blue.darken2,
accent: colors.orange.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3,
background: colors.red.accent3
}
}
}
}
Any suggestion? I'm using Vue + Vuetify + Nuxt
Like this:
.default-box-layout {
padding: 15px;
border: 1px solid var(--v-primary);
background-color: var(--v-background);
width: 100%;
margin: 0;
}
From the docs:
Enabling customProperties will also generate a css variable for each theme color, which you can then use in your components’ blocks.
So, when you add:
theme: {
options: { customProperties: true }, // this line
},
to your Vuetify config, variables will get injected at the css root variables. Now, you can use things like --v-primary-base, like this:
.button-blue {
background-color: var(--v-primary-base);
color: var(--v-secondary-base) !important;
}
More?
See https://vuetifyjs.com/en/features/theme/#custom-properties

How to use custom fonts in TinyMCE using tinymce-vue package for VueJS?

I'm trying to use custom fonts stored in my assets/fonts folder with TinyMCE, but it seems like it can't render the font, except for the format selector. The content doesn't display the font correctly, although the font selector shows the font is being applied (in the title, for example).
Here's the code so far:
<template>
<tinymce-editor
:key="id"
:initial-value="initialValue"
:resize="false"
:init="{
selector: 'textarea#format-custom',
height: height,
plugins: 'table wordcount link lists',
menubar : false,
statusbar : false,
toolbar: 'undo redo | bold italic| styleselect | alignleft aligncenter alignright alignjustify | numlist bullist | fontselect',
content_css: [ '//www.tiny.cloud/css/codepen.min.css' ],
content_style: 'body { font-family: Roboto Light; font-size: 16px; }' + '.left { text-align: left; }' + 'img.left { float: left; }' + 'table.left { float: left; }' + '.right { text-align: right; }' + 'img.right { float: right; }' + 'table.right { float: right; }' + '.center { text-align: center; }' + 'img.center { display: block; margin: 0 auto; }' + 'table.center { display: block; margin: 0 auto; }' + '.full { text-align: justify; }' + 'img.full { display: block; margin: 0 auto; }' + 'table.full { display: block; margin: 0 auto; }' + '.bold { font-weight: bold; }' + '.italic { font-style: italic; }' + '.underline { text-decoration: underline; }' + '.title { font-family: Raleway Bold; font-size: 26px; }' + '.subtitle { font-family: Roboto Medium; font-size: 20px; }',
formats: {
alignleft: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'left' },
aligncenter: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'center' },
alignright: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'right' },
alignfull: { selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'full' },
bold: { inline: 'span', classes: 'bold' }, italic: { inline: 'span', classes: 'italic' },
titleformat: { inline: 'span', attributes: { title: 'Title'} , classes: 'title', },
subtitleformat: { inline: 'span', attributes: { title: 'SubTitle'} , classes: 'subtitle' } },
style_formats: [ { title: 'Title', format: 'titleformat' }, { title: 'SubTitle', format: 'subtitleformat' } ]
}"
api-key="no-api-key"
model-events="change keydown blur focus paste"
#input="handleInput"
#error="handleError"
/>
</template>
<script>
import Editor from '#tinymce/tinymce-vue'
export default {
components: {
'tinymce-editor': Editor
},
props: {
initialValue: {
type: String,
default: null
},
id: {
type: String,
default: null
},
height: {
type: String,
default: '100%'
}
},
methods: {
handleInput (value) {
this.$emit('input', value)
},
handleError (err) {
console.error(err)
}
}
}
</script>
Here's a print:
If you want to use custom fonts you need to:
Load them into TinyMCE via content_css
Include the fonts via the font_formats configuration option: https://www.tiny.cloud/docs/configure/editor-appearance/#font_formats
You appear to be loading the CSS from the TinyMCE demo site:
content_css: [ '//www.tiny.cloud/css/codepen.min.css' ],
This is likely not something you want to do as our demo CSS would likely not be appropriate for your web site/application. I would change that to use an appropriate CSS for your site. In that CSS you can load a custom font. For example:
#import url('https://fonts.googleapis.com/css?family=Lato');
Note: The reason the TinyMCE menu can render the font is you are likely loading the font on the page that includes TinyMCE but not in TinyMCE itself. The editor content is in its own iframe but the menus are part of the main page. If you inspect the DOM you will be able to see this layout. Using content_css allows you to inject CSS into the editor's iframe.