├── .eslintrc.js ├── .gitignore ├── README.md ├── package.json ├── src ├── index.js ├── module.js └── templates │ └── plugin.js └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: "babel-eslint", 5 | sourceType: "module" 6 | }, 7 | extends: [ 8 | "@nuxtjs" 9 | ], 10 | rules: { 11 | "comma-dangle": ["error", "always-multiline"], 12 | "semi": ["error", "always"] 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt* 6 | .vscode 7 | .DS_STORE 8 | coverage 9 | dist 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt Quasar Module 2 | 3 | [![npm](https://img.shields.io/npm/v/nuxt-quasar.svg)](https://www.npmjs.com/package/nuxt-quasar) 4 | 5 | A Nuxt module for the [Quasar Framework](https://quasar.dev). 6 | 7 | > Note this module only supports Quasar >= 1.0 8 | 9 | **This is currently very early in development, 10 | so use with caution. There are currently no tests, but this module 11 | is currently used in production on a few of my Nuxt apps, however they 12 | all follow the roughly same configuration, so there are likely bugs lurking 13 | that I haven't found due to the limited usage at the time, so if you find a bug, 14 | please create an issue so I (or maybe someone else) can get it fixed.** 15 | 16 | ## Install 17 | 18 | ```bash 19 | $ npm install --save nuxt-quasar 20 | 21 | # Or with Yarn 22 | 23 | $ yarn add nuxt-quasar 24 | ``` 25 | 26 | Then add it to your `nuxt.config.js`: 27 | 28 | ```js 29 | export default { 30 | // ... 31 | modules: [ 32 | 'nuxt-quasar', 33 | ], 34 | // ... 35 | }; 36 | ``` 37 | 38 | Then start it up to load Quasar with everything loaded and the default configuration, or start adding your own [configuration](#Configuration) via the `nuxt.config.js` or by creating a `quasar.conf.js`. 39 | 40 | ## Features 41 | 42 | * Allows for configuring the Quasar Framework through `nuxt.config.js` or 43 | `quasar.conf.js` (Currently only supports a subset of Quasar's configuration options) 44 | * Brings some features that are only available when using Quasar CLI/Vue CLI 45 | like automatically importing Quasar's theme and your custom Stylus variables into 46 | your Vue components 47 | * Tree Shaking 48 | * Supports Nuxt's Universal mode for SPAs or SSR, as well as Nuxt's static generation 49 | 50 | ### Roadmap 51 | 52 | * Support [Quasar App Extensions](https://quasar.dev/app-extensions/introduction), 53 | Nuxt's module API exposes a similar interface to Quasars App Extensions API which 54 | will allow for utilizing Quasar's App Extensions in the exact same manner as 55 | Quasar CLI. 56 | * Use Nuxt's module package commands to emulate some of the functionality 57 | of Quasar CLI. 58 | 59 | ## Configuration 60 | 61 | `nuxt-quasar` currently supports the following [Quasar Config Options](https://quasar.dev/quasar-cli/quasar-conf-js): 62 | 63 | * animations 64 | * extras 65 | * framework 66 | * config 67 | * brand 68 | * components 69 | * directives 70 | * plugins 71 | * iconSet 72 | * cssAddon 73 | * supportIE 74 | 75 | You can configure these options in your `nuxt.config.js`: 76 | 77 | ```js 78 | export default { 79 | quasar: { 80 | animations: ["fadeIn", "fadeOut"], 81 | extras: ["fontawesome-v5"], 82 | framework: { 83 | config: { 84 | brand: { 85 | primary: "#ffffff", 86 | // ... 87 | }, 88 | }, 89 | components: [ 90 | "QAvatar", 91 | "QBtn", 92 | // ... 93 | ], 94 | directives: ["ClosePopup"], 95 | plugins: ["Cookies"], 96 | iconSet: "fontawesome-v5", 97 | cssAddon: true 98 | }, 99 | supportIE: true 100 | }, 101 | }; 102 | ``` 103 | 104 | Or you can alternatively use a `quasar.conf.js`: 105 | 106 | ```js 107 | // Note ctx will be undefined currently, eventually 108 | // support will be added to emulate the Quasar Context object 109 | // allowing for dyanmic configuration 110 | module.exports = function(ctx) { 111 | return { 112 | animations: ["fadeIn", "fadeOut"], 113 | extras: ["fontawesome-v5"], 114 | framework: { 115 | config: { 116 | brand: { 117 | primary: "#ffffff", 118 | // ... 119 | }, 120 | }, 121 | components: [ 122 | "QAvatar", 123 | "QBtn", 124 | // ... 125 | ], 126 | directives: ["ClosePopup"], 127 | plugins: ["Cookies"], 128 | iconSet: "fontawesome-v5", 129 | cssAddon: true 130 | }, 131 | supportIE: true 132 | }; 133 | }; 134 | ``` 135 | 136 | Then for your custom theme/Quasar Variable overrides, you can create a 137 | `quasar.variables.styl` file in `./assets`. These variables along with 138 | all of Quasars other variables will automatically be imported into your 139 | Vue components with a stylus style block: 140 | 141 | ```stylus 142 | // ./assets/quasar.variables.styl 143 | 144 | $primary = #ffffff 145 | // etc... 146 | ``` 147 | 148 | ```html 149 | // ./components/MyComponent.vue 150 | 155 | ``` 156 | 157 | ### Why/Who's this For 158 | 159 | This was created because I have a few existing Nuxt projects, most of which 160 | were originally created while Quasar while still in early beta, and while 161 | I had wanted to use Quasar orginally on a few of them, I decided to use 162 | alternatives while Quasar matured. 163 | 164 | However, now that Quasar is out of beta, and offers one of the best UI 165 | Frameworks available (in my opinion), I found myself wanting to start migrating 166 | those Nuxt apps over. Unfortunately though, Quasar only offers three ways to 167 | integrate it into your project (UMD, Quasar CLI, or Vue CLI). Quasar CLI 168 | is great, but can't be integrated into existing projects. Vue CLI is also 169 | a great tool, but yet again, can't easily be integrated into an existing Nuxt project. 170 | So, that leaves the UMD build, which while convinient, it doesn't offer all 171 | the benefits that Quasar/Vue CLI have (mainly treeshaking and configuration). 172 | 173 | What I really wanted was an option to slowly integrate Quasar into a Nuxt 174 | project, as for some of the projects I would also like to eventually migrate 175 | to use Quasar CLI rather than Nuxt due to the features Quasar CLI offers like 176 | building for Electron/Cordova that are lacking in Nuxt. But, in addition to 177 | migrating the actual code to use the Quasar components, that would require 178 | also restructuring the entire project, and doing both at the same time sounds 179 | like a recipe for disaster. However, some of the projects (the ones that use 180 | Nuxt's static generation -- a feature unavailable in Quasar), I don't plan 181 | on migrating from Nuxt, but would like to be able to use the same config/files 182 | as I would when I'm working on a Quasar CLI project. Thus, this module was created. 183 | 184 | So, if you want to use Quasar with Nuxt, incrementally migrate your Nuxt 185 | app to Quasar CLI, or just don't want to have the bloat of the UMD build, 186 | you may find this module useful. 187 | 188 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-quasar", 3 | "version": "0.1.3", 4 | "description": "Nuxt module for the Quasar Framework", 5 | "main": "src/index.js", 6 | "repository": "https://github.com/NickHurst/nuxt-quasar.git", 7 | "author": "Nick Hurst", 8 | "license": "MIT", 9 | "private": false, 10 | "eslintIgnore": [ 11 | "src/templates/*.*" 12 | ], 13 | "files": [ 14 | "src" 15 | ], 16 | "keywords": [ 17 | "nuxtjs", 18 | "nuxt", 19 | "nuxt-module", 20 | "quasar", 21 | "quasar-framework", 22 | "vue", 23 | "vue.js" 24 | ], 25 | "engines": { 26 | "node": ">=8.0.0", 27 | "npm": ">=5.0.0" 28 | }, 29 | "scripts": { 30 | "lint": "eslint src" 31 | }, 32 | "devDependencies": { 33 | "@nuxtjs/eslint-config": "^0.0.1", 34 | "babel-eslint": "^10.0.1", 35 | "eslint": "^5.16.0", 36 | "eslint-config-standard": "^12.0.0", 37 | "eslint-plugin-import": "^2.17.3", 38 | "eslint-plugin-jest": "^22.6.4", 39 | "eslint-plugin-node": "^9.1.0", 40 | "eslint-plugin-promise": "^4.1.1", 41 | "eslint-plugin-standard": "^4.0.0", 42 | "eslint-plugin-vue": "^5.2.2", 43 | "nuxt": "^2.8.1", 44 | "stylus": "^0.54.5", 45 | "stylus-loader": "^3.0.2" 46 | }, 47 | "dependencies": { 48 | "glob-all": "^3.1.0", 49 | "quasar": "^1.0.0-rc.4" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import nuxtQuasar from './module'; 2 | 3 | export default nuxtQuasar; 4 | module.exports.meta = require('../package.json'); 5 | -------------------------------------------------------------------------------- /src/module.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const glob = require('glob-all'); 4 | 5 | const QUASAR_CONF_PATH = `${process.cwd()}/quasar.conf.js`; 6 | 7 | const QUASAR_EXTRAS_PATH = '@quasar/extras'; 8 | const QUASAR_ANIMATION_CSS_PATH = `${QUASAR_EXTRAS_PATH}/animate`; 9 | const QUASAR_FLEX_ADDON_PATH = 'quasar/src/css/flex-addon.styl'; 10 | const QUASAR_VARIABLES_PATH = 'quasar/src/css/variables.styl'; 11 | const QUASAR_VARIABLES_OVERRIDES_PATH = '~/assets/quasar.variables.styl'; 12 | 13 | const QUASAR_STYLUS_FILES = [ 14 | 'quasar/dist/quasar.styl', 15 | QUASAR_VARIABLES_PATH, 16 | QUASAR_VARIABLES_OVERRIDES_PATH, 17 | ]; 18 | 19 | const STYLUS_AUTO_IMPORTS = [ 20 | QUASAR_VARIABLES_PATH, 21 | QUASAR_VARIABLES_OVERRIDES_PATH, 22 | ]; 23 | 24 | const mergeOptions = (moduleOptions, nuxtOptions, resolver) => { 25 | const options = Object.assign({}, nuxtOptions, moduleOptions); 26 | 27 | if (!fs.existsSync(QUASAR_CONF_PATH)) return options; 28 | 29 | const quasarConfBuilder = resolver.requireModule(QUASAR_CONF_PATH); 30 | 31 | return Object.assign({}, options, quasarConfBuilder({})); 32 | }; 33 | 34 | export default function nuxtQuasar(moduleOptions) { 35 | const resolver = this.nuxt.resolver || this.nuxt; 36 | const resolvePath = path => 37 | resolver.resolveModule(path) || resolver.resolveAlias(path) 38 | 39 | const pushCSS = file => 40 | resolvePath(file) && this.options.css.push(file); 41 | 42 | const options = mergeOptions(moduleOptions, this.options.quasar, resolver); 43 | 44 | const { animations = [], extras = [] } = options; 45 | 46 | animations.map(name => `${QUASAR_ANIMATION_CSS_PATH}/${name}.css`).forEach(pushCSS); 47 | extras.map(extra => `${QUASAR_EXTRAS_PATH}/${extra}/${extra}.css`).forEach(pushCSS); 48 | 49 | if (options.framework && options.framework.cssAddon) { 50 | pushCSS(QUASAR_FLEX_ADDON_PATH); 51 | } 52 | 53 | QUASAR_STYLUS_FILES.forEach(pushCSS); 54 | 55 | const { build: { loaders: { stylus: stylusLoader } } } = this.options; 56 | 57 | const stylusLoaderImports = STYLUS_AUTO_IMPORTS.reduce((paths, path) => { 58 | const modulePath = resolver.resolveModule(path); 59 | if (modulePath) return [...paths, modulePath]; 60 | 61 | const aliasPath = resolver.resolveAlias(path); 62 | const globPaths = glob.sync(aliasPath); 63 | 64 | return [...paths, ...globPaths]; 65 | }, []); 66 | 67 | stylusLoader.import = stylusLoader.import 68 | ? [...stylusLoader.import, ...stylusLoaderImports] 69 | : stylusLoaderImports; 70 | 71 | this.addPlugin({ 72 | src: path.resolve(__dirname, 'templates', 'plugin.js'), 73 | fileName: 'nuxt-quasar-plugin.js', 74 | options, 75 | }); 76 | }; 77 | -------------------------------------------------------------------------------- /src/templates/plugin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | <% var framework = options.framework || {} %> 4 | 5 | <% if (!framework || framework === 'all') { %> 6 | import Quasar from 'quasar'; 7 | Vue.use(Quasar, {}); 8 | <% } else { %> 9 | <% var components = framework.components || [] %> 10 | <% var directives = framework.directives || [] %> 11 | <% var plugins = framework.plugins || [] %> 12 | <% var config = framework.config %> 13 | 14 | import Quasar, { 15 | <%= components 16 | .concat(directives) 17 | .concat(plugins) 18 | .map(s => '\t' + s) 19 | .join(',\n') + ',\n' %> 20 | } from 'quasar/src/index.esm'; 21 | 22 | <% if (framework.iconSet) { %> 23 | import iconSet from 'quasar/icon-set/<%= framework.iconSet %>.js'; 24 | <% } else { %> 25 | import iconSet from 'quasar/icon-set/material-icons.js'; 26 | <% } %> 27 | 28 | Vue.use(Quasar, { 29 | <% if (config) { %> 30 | config: <%= JSON.stringify(config, null, '\t') %>, 31 | <% } %> 32 | <% if (components && components.length) { %> 33 | components: { 34 | <%= components.map(s => '\t\t' + s).join(',\n') + ',\n' %> 35 | }, 36 | <% } %> 37 | <% if (directives && directives.length) { %> 38 | directives: { 39 | <%= directives.map(s => '\t\t' + s).join(',\n') + ',\n' %> 40 | }, 41 | <% } %> 42 | <% if (plugins && plugins.length) { %> 43 | plugins: { 44 | <%= plugins.map(s => '\t\t' + s).join(',\n') + ',\n' %> 45 | }, 46 | <% } %> 47 | iconSet, 48 | }); 49 | <% } %> 50 | 51 | <% if (options.supportIE) { %> 52 | import 'quasar/dist/quasar.ie.polyfills.js'; 53 | <% } %> 54 | --------------------------------------------------------------------------------