diff --git a/generator/helpers.js b/generator/helpers.js
deleted file mode 100644
index 9cf07c91..00000000
--- a/generator/helpers.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const fs = require('fs')
-
-module.exports = function (api) {
- return {
- getMain() {
- return api.hasPlugin('typescript')
- ? api.resolve('src/main.ts')
- : api.resolve('src/main.js')
- },
-
- updateBabelConfig (callback) {
- let config, configPath
-
- const rcPath = api.resolve('./babel.config.js')
- const pkgPath = api.resolve('./package.json')
- if (fs.existsSync(rcPath)) {
- configPath = rcPath
- config = callback(require(rcPath))
- } else if (fs.existsSync(pkgPath)) {
- configPath = pkgPath
- config = JSON.parse(fs.readFileSync(pkgPath, { encoding: 'utf8' }))
-
- if (config.babel) {
- config.babel = callback(config.babel)
- } else {
- // TODO: error handling here?
- }
- }
-
- if (configPath) {
- const moduleExports = configPath !== pkgPath ? 'module.exports = ' : ''
-
- fs.writeFileSync(
- configPath,
- `${moduleExports}${JSON.stringify(config, null, 2)}`,
- { encoding: 'utf8' }
- )
- } else {
- // TODO: handle if babel config doesn't exist
- }
- },
-
- updateFile (file, callback) {
- let content = fs.existsSync(file)
- ? fs.readFileSync(file, { encoding: 'utf8' })
- : ''
-
- content = callback(content.split(/\r?\n/g)).join('\n')
-
- fs.writeFileSync(file, content, { encoding: 'utf8' })
- }
- }
-}
diff --git a/generator/index.js b/generator/index.js
index b2a07921..6f8e178f 100755
--- a/generator/index.js
+++ b/generator/index.js
@@ -1,153 +1,23 @@
module.exports = (api, opts, rootOpts) => {
- const helpers = require('./helpers')(api)
-
- api.extendPackage({
- dependencies: {
- vuetify: "^1.1.11"
- }
- })
-
- if (opts.useAlaCarte) {
- api.extendPackage({
- devDependencies: {
- "babel-plugin-transform-imports": "^1.4.1",
- "stylus": "^0.54.5",
- "stylus-loader": "^3.0.1",
- }
- })
- }
-
- if (opts.usePolyfill) {
- api.extendPackage({
- devDependencies: {
- "@babel/polyfill": "^7.0.0-beta.49",
- }
- })
- }
-
- if (api.hasPlugin('electron-builder') === true) {
- // material icons pkg for electron
- api.extendPackage({
- devDependencies: {
- "material-design-icons-iconfont": "^3.0.3",
- }
- })
-
- try {
- api.injectImports(helpers.getMain(),
- `import 'material-design-icons-iconfont/dist/material-design-icons.css'`
- )
- } catch(e) {
- console.error(e)
- }
- }
-
-
- // Render vuetify plugin file
- api.render(api.hasPlugin('typescript') ? {
- './src/plugins/vuetify.ts': './templates/default/src/plugins/vuetify.ts'
- } : {
- './src/plugins/vuetify.js': './templates/default/src/plugins/vuetify.js'
- }, opts)
-
- // Render files if we're replacing
- const fs = require('fs')
- const routerPath = api.resolve('./src/router.js')
- opts.router = fs.existsSync(routerPath)
-
- if (opts.replaceComponents) {
- const files = {
- './src/App.vue': './templates/default/src/App.vue',
- './src/assets/logo.png': './templates/default/src/assets/logo.png'
- }
-
- if (opts.router) {
- files['./src/views/Home.vue'] = './templates/default/src/views/Home.vue'
- } else {
- api.render('./templates/hw')
- }
-
- api.render(files, opts)
- }
+ const alaCarte = require('./tools/alaCarte')
+ const fonts = require('./tools/fonts')
+ const polyfill = require('./tools/polyfill')
+ const vuetify = require('./tools/vuetify')
+
+ vuetify.addDependencies(api)
+ opts.useAlaCarte && alaCarte.addDependencies(api)
+ opts.usePolyfill && polyfill.addDependencies(api)
+ opts.installFonts && fonts.addDependencies(api, opts.iconFont)
+ opts.installFonts && fonts.addImports(api, opts.iconFont)
+ vuetify.renderFiles(api, opts)
// adapted from https://github.com/Akryum/vue-cli-plugin-apollo/blob/master/generator/index.js#L68-L91
api.onCreateComplete(() => {
- // Modify main.js
- helpers.updateFile(helpers.getMain(), lines => {
- const vueImportIndex = lines.findIndex(line => line.match(/^import Vue/))
-
- lines.splice(vueImportIndex + 1, 0, 'import \'./plugins/vuetify\'')
-
- return lines
- })
-
- // Add polyfill
- if (opts.usePolyfill) {
- helpers.updateBabelConfig(cfg => {
- if (!cfg.presets) return cfg
-
- const vuePresetIndex = cfg.presets.findIndex(p => Array.isArray(p) ? p[0] === '@vue/app' : p === '@vue/app')
- const isArray = Array.isArray(cfg.presets[vuePresetIndex])
-
- if (vuePresetIndex < 0) return cfg
-
- if (isArray) {
- cfg.presets[vuePresetIndex][1]['useBuiltIns'] = 'entry'
- } else {
- cfg.presets[vuePresetIndex] = [
- '@vue/app',
- {
- useBuiltIns: 'entry'
- }
- ]
- }
-
- return cfg
- })
-
- helpers.updateFile(helpers.getMain(), lines => {
- if (!lines.find(l => l.match(/^(import|require).*@babel\/polyfill.*$/))) {
- lines.unshift('import \'@babel/polyfill\'')
- }
-
- return lines
- })
- }
-
- // If a-la-carte, update babel
- if (opts.useAlaCarte) {
- helpers.updateBabelConfig(cfg => {
- if (cfg.plugins === undefined) {
- cfg.plugins = []
- }
-
- cfg.plugins.push([
- 'transform-imports',
- {
- vuetify: {
- transform: 'vuetify/es5/components/${member}',
- preventFullImport: true
- }
- }
- ])
-
- return cfg
- })
- }
-
- // Add Material Icons (unless electron)
- if(api.hasPlugin('electron-builder') === false) {
- const indexPath = api.resolve('./public/index.html')
-
- let content = fs.readFileSync(indexPath, { encoding: 'utf8' })
-
- const lines = content.split(/\r?\n/g).reverse()
-
- const lastLink = lines.findIndex(line => line.match(/^\s*'
-
- content = lines.reverse().join('\n')
- fs.writeFileSync(indexPath, content, { encoding: 'utf8' })
- }
+ vuetify.addImports(api)
+ opts.usePolyfill && polyfill.updateBabelConfig(api)
+ opts.usePolyfill && polyfill.addImports(api)
+ opts.useAlaCarte && alaCarte.updateBabelConfig(api)
+ !opts.installFonts && fonts.addLinks(api, opts.iconFont)
+ vuetify.setHtmlLang(api, opts.locale)
})
}
diff --git a/generator/templates/default/src/App.vue b/generator/templates/default/src/App.vue
index 4ffc1b2e..13ed329d 100644
--- a/generator/templates/default/src/App.vue
+++ b/generator/templates/default/src/App.vue
@@ -30,18 +30,50 @@
>
+ <%_ if (options.iconFont === 'md') { _%>
+ <%_ } else if (options.iconFont === 'mdi') { _%>
+
+ <%_ } else if (options.iconFont === 'fa') { _%>
+
+ <%_ } else if (options.iconFont === 'fa4') { _%>
+
+ <%_ } _%>
+ <%_ if (options.iconFont === 'md') { _%>
web
+ <%_ } else if (options.iconFont === 'mdi') { _%>
+ mdi-web
+ <%_ } else if (options.iconFont === 'fa') { _%>
+ fas fa-globe
+ <%_ } else if (options.iconFont === 'fa4') { _%>
+ fa-globe
+ <%_ } _%>
- remove
+ <%_ if (options.iconFont === 'md') { _%>
+ web
+ <%_ } else if (options.iconFont === 'mdi') { _%>
+ mdi-minus
+ <%_ } else if (options.iconFont === 'fa') { _%>
+ fas fa-minus
+ <%_ } else if (options.iconFont === 'fa4') { _%>
+ fa-minus
+ <%_ } _%>
+ <%_ if (options.iconFont === 'md') { _%>
menu
+ <%_ } else if (options.iconFont === 'mdi') { _%>
+ mdi-menu
+ <%_ } else if (options.iconFont === 'fa') { _%>
+ fas fa-bars
+ <%_ } else if (options.iconFont === 'fa4') { _%>
+ fa-bars
+ <%_ } _%>
@@ -61,7 +93,15 @@
+ <%_ if (options.iconFont === 'md') { _%>
compare_arrows
+ <%_ } else if (options.iconFont === 'mdi') { _%>
+ mdi-arrows-left-right-bold-outline
+ <%_ } else if (options.iconFont === 'fa') { _%>
+ fas fa-exchange-alt
+ <%_ } else if (options.iconFont === 'fa4') { _%>
+ fa-exchange
+ <%_ } _%>
Switch drawer (click me)
@@ -91,7 +131,15 @@ export default {
drawer: true,
fixed: false,
items: [{
+<%_ if (options.iconFont === 'md') { _%>
icon: 'bubble_chart',
+<%_ } else if (options.iconFont === 'mdi') { _%>
+ icon: 'mdi-chart-bubble',
+<%_ } else if (options.iconFont === 'fa') { _%>
+ icon: 'fas fa-shapes',
+<%_ } else if (options.iconFont === 'fa4') { _%>
+ icon: 'fa-bullseye',
+<%_ } _%>
title: 'Inspire'
}],
miniVariant: false,
diff --git a/generator/templates/default/src/plugins/vuetify.js b/generator/templates/default/src/plugins/vuetify.js
index 5db9bf37..a3f82dc1 100644
--- a/generator/templates/default/src/plugins/vuetify.js
+++ b/generator/templates/default/src/plugins/vuetify.js
@@ -1,46 +1,60 @@
-import Vue from 'vue'
-<%_ if (options.useAlaCarte) { _%>
-import {
- Vuetify,
- VApp,
- VNavigationDrawer,
- VFooter,
- VList,
- VBtn,
- VIcon,
- VGrid,
- VToolbar,
- transitions
-} from 'vuetify'
-import 'vuetify/src/stylus/app.styl'
-<%_ } else { _%>
-import Vuetify from 'vuetify'
-import 'vuetify/dist/vuetify.min.css'
-<%_ } _%>
-
-Vue.use(Vuetify, {
-<%_ if (options.useAlaCarte) { _%>
- components: {
- VApp,
- VNavigationDrawer,
- VFooter,
- VList,
- VBtn,
- VIcon,
- VGrid,
- VToolbar,
- transitions
- },
-<%_ } _%>
-<%_ if (options.useTheme) { _%>
- theme: {
- primary: '#ee44aa',
- secondary: '#424242',
- accent: '#82B1FF',
- error: '#FF5252',
- info: '#2196F3',
- success: '#4CAF50',
- warning: '#FFC107'
- },
-<%_ } _%>
-})
+import Vue from 'vue'
+<%_ if (useAlaCarte) { _%>
+import {
+ Vuetify,
+ VApp,
+ VNavigationDrawer,
+ VFooter,
+ VList,
+ VBtn,
+ VIcon,
+ VGrid,
+ VToolbar,
+ transitions
+} from 'vuetify'
+import 'vuetify/src/stylus/app.styl'
+<%_ } else { _%>
+import Vuetify from 'vuetify'
+import 'vuetify/dist/vuetify.min.css'
+<%_ } _%>
+<%_ if (locale !== 'en') { _%>
+import <%= locale.replace(/-/g, '') %> from 'vuetify/<%= typescript ? 'src' : 'es5' %>/locale/<%= locale %>'
+<%_ } _%>
+
+Vue.use(Vuetify, {
+<%_ if (useAlaCarte) { _%>
+ components: {
+ VApp,
+ VNavigationDrawer,
+ VFooter,
+ VList,
+ VBtn,
+ VIcon,
+ VGrid,
+ VToolbar,
+ transitions
+ },
+<%_ } _%>
+<%_ if (useTheme) { _%>
+ theme: {
+ primary: '#ee44aa',
+ secondary: '#424242',
+ accent: '#82B1FF',
+ error: '#FF5252',
+ info: '#2196F3',
+ success: '#4CAF50',
+ warning: '#FFC107'
+ },
+<%_ } _%>
+<%_ if (useCustomProperties) { _%>
+ customProperties: true,
+<%_ } _%>
+ iconfont: '<%= iconFont %>',
+<%_ if (locale !== 'en') { _%>
+ lang: {
+ locales: { <%= locale.replace(/-/g, '') %> },
+ current: '<%= locale %>'
+ },
+<%_ } _%>
+})
+
diff --git a/generator/templates/default/src/plugins/vuetify.ts b/generator/templates/default/src/plugins/vuetify.ts
deleted file mode 100644
index 7ecb4203..00000000
--- a/generator/templates/default/src/plugins/vuetify.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import Vue from 'vue'
-<%_ if (options.useAlaCarte) { _%>
-import {
- Vuetify,
- VApp,
- VNavigationDrawer,
- VFooter,
- VList,
- VBtn,
- VIcon,
- VGrid,
- VToolbar,
- transitions
-} from 'vuetify'
-import 'vuetify/src/stylus/app.styl'
-<%_ } else { _%>
-import Vuetify from 'vuetify'
-import 'vuetify/dist/vuetify.min.css'
-<%_ } _%>
-
-Vue.use(Vuetify, {
-<%_ if (options.useAlaCarte) { _%>
- components: {
- VApp,
- VNavigationDrawer,
- VFooter,
- VList,
- VBtn,
- VIcon,
- VGrid,
- VToolbar,
- transitions
- },
-<%_ } _%>
-<%_ if (options.useTheme) { _%>
- theme: {
- primary: '#ee44aa',
- secondary: '#424242',
- accent: '#82B1FF',
- error: '#FF5252',
- info: '#2196F3',
- success: '#4CAF50',
- warning: '#FFC107'
- },
-<%_ } _%>
-})
diff --git a/generator/tools/alaCarte.js b/generator/tools/alaCarte.js
new file mode 100644
index 00000000..a3b03f4e
--- /dev/null
+++ b/generator/tools/alaCarte.js
@@ -0,0 +1,43 @@
+const helpers = require('./helpers')
+
+function addDependencies (api) {
+ api.extendPackage({
+ devDependencies: {
+ "babel-plugin-transform-imports": "^1.5.0",
+ "stylus": "^0.54.5",
+ "stylus-loader": "^3.0.1",
+ }
+ })
+}
+
+function updateBabelConfig (api) {
+ helpers.updateBabelConfig(api, cfg => {
+ if (cfg.plugins === undefined) {
+ cfg.plugins = []
+ }
+
+ cfg.plugins.push([
+ 'transform-imports',
+ {
+ vuetify: {
+ transform: 'vuetify/es5/components/${member}',
+ preventFullImport: true
+ }
+ }
+ ])
+
+ return cfg
+ })
+
+
+ helpers.updateFile(api, './babel.config.js', lines => {
+ const index = lines.findIndex(line => line.indexOf('vuetify/es5/components/${member}') !== -1)
+ index && (lines[index] += ' // eslint-disable-line no-template-curly-in-string')
+ return lines
+ })
+}
+
+module.exports = {
+ addDependencies,
+ updateBabelConfig,
+}
diff --git a/generator/tools/fonts.js b/generator/tools/fonts.js
new file mode 100644
index 00000000..bac167ca
--- /dev/null
+++ b/generator/tools/fonts.js
@@ -0,0 +1,73 @@
+const helpers = require('./helpers')
+const fonts = {
+ md: {
+ 'package': {
+ 'material-design-icons-iconfont': '^3.0.3',
+ },
+ 'import': 'material-design-icons-iconfont/dist/material-design-icons.css',
+ link: '',
+ },
+ mdi: {
+ 'package': {
+ '@mdi/font': '^2.6.95',
+ },
+ 'import': '@mdi/font/css/materialdesignicons.css',
+ link: '',
+ },
+ fa: {
+ 'package': {
+ '@fortawesome/fontawesome-free': '^5.2.0',
+ },
+ 'import': '@fortawesome/fontawesome-free/css/all.css',
+ link: '',
+ },
+ fa4: {
+ 'package': {
+ 'font-awesome': '^4.7.0',
+ },
+ 'import': 'font-awesome/css/font-awesome.css',
+ link: '',
+ },
+ roboto: {
+ 'package': {
+ 'roboto-fontface': '*',
+ },
+ 'import': 'roboto-fontface/css/roboto/roboto-fontface.css',
+ link: '',
+ }
+}
+
+function addDependencies (api, iconFont) {
+ api.extendPackage({
+ dependencies: {
+ ...fonts['roboto']['package'],
+ ...fonts[iconFont]['package'],
+ }
+ })
+}
+
+function addImports (api, iconFont) {
+ try {
+ api.injectImports(api.entryFile, `import '${fonts['roboto']['import']}'`)
+ api.injectImports(api.entryFile, `import '${fonts[iconFont]['import']}'`)
+ } catch(e) {
+ console.error(e)
+ }
+}
+
+function addLinks (api, iconFont) {
+ helpers.updateFile(api, './public/index.html', lines => {
+ const lastLink = lines.reverse().findIndex(line => line.match(/^\s*<\/head>/))
+
+ lines.splice(lastLink + 1, 0, ` ${fonts['roboto'].link}`)
+ lines.splice(lastLink + 1, 0, ` ${fonts[iconFont].link}`)
+
+ return lines.reverse()
+ })
+}
+
+module.exports = {
+ addDependencies,
+ addImports,
+ addLinks,
+}
diff --git a/generator/tools/helpers.js b/generator/tools/helpers.js
new file mode 100644
index 00000000..545c2316
--- /dev/null
+++ b/generator/tools/helpers.js
@@ -0,0 +1,49 @@
+const fs = require('fs')
+
+function updateBabelConfig (api, callback) {
+ let config, configPath
+
+ const rcPath = api.resolve('./babel.config.js')
+ const pkgPath = api.resolve('./package.json')
+ if (fs.existsSync(rcPath)) {
+ configPath = rcPath
+ config = callback(require(rcPath))
+ } else if (fs.existsSync(pkgPath)) {
+ configPath = pkgPath
+ config = JSON.parse(fs.readFileSync(pkgPath, { encoding: 'utf8' }))
+
+ if (config.babel) {
+ config.babel = callback(config.babel)
+ } else {
+ // TODO: error handling here?
+ }
+ }
+
+ if (configPath) {
+ const moduleExports = configPath !== pkgPath ? 'module.exports = ' : ''
+
+ fs.writeFileSync(
+ configPath,
+ `${moduleExports}${JSON.stringify(config, null, 2)}`,
+ { encoding: 'utf8' }
+ )
+ } else {
+ // TODO: handle if babel config doesn't exist
+ }
+}
+
+function updateFile (api, file, callback) {
+ file = api.resolve(file)
+ let content = fs.existsSync(file)
+ ? fs.readFileSync(file, { encoding: 'utf8' })
+ : ''
+
+ content = callback(content.split(/\r?\n/g)).join('\n')
+
+ fs.writeFileSync(file, content, { encoding: 'utf8' })
+}
+
+module.exports = {
+ updateBabelConfig,
+ updateFile,
+}
diff --git a/generator/tools/polyfill.js b/generator/tools/polyfill.js
new file mode 100644
index 00000000..cba1f4c4
--- /dev/null
+++ b/generator/tools/polyfill.js
@@ -0,0 +1,49 @@
+const helpers = require('./helpers')
+
+function addDependencies (api) {
+ api.extendPackage({
+ dependencies: {
+ "@babel/polyfill": "^7.0.0-rc.1",
+ }
+ })
+}
+
+function updateBabelConfig (api) {
+ helpers.updateBabelConfig(api, cfg => {
+ if (!cfg.presets) return cfg
+
+ const vuePresetIndex = cfg.presets.findIndex(p => Array.isArray(p) ? p[0] === '@vue/app' : p === '@vue/app')
+ const isArray = Array.isArray(cfg.presets[vuePresetIndex])
+
+ if (vuePresetIndex < 0) return cfg
+
+ if (isArray) {
+ cfg.presets[vuePresetIndex][1]['useBuiltIns'] = 'entry'
+ } else {
+ cfg.presets[vuePresetIndex] = [
+ '@vue/app',
+ {
+ useBuiltIns: 'entry'
+ }
+ ]
+ }
+
+ return cfg
+ })
+}
+
+function addImports (api) {
+ helpers.updateFile(api, api.entryFile, lines => {
+ if (!lines.find(l => l.match(/^(import|require).*@babel\/polyfill.*$/))) {
+ lines.unshift('import \'@babel/polyfill\'')
+ }
+
+ return lines
+ })
+}
+
+module.exports = {
+ addDependencies,
+ updateBabelConfig,
+ addImports,
+}
diff --git a/generator/tools/vuetify.js b/generator/tools/vuetify.js
new file mode 100755
index 00000000..8f1edcbe
--- /dev/null
+++ b/generator/tools/vuetify.js
@@ -0,0 +1,69 @@
+const helpers = require('./helpers')
+
+function addDependencies (api) {
+ api.extendPackage({
+ dependencies: {
+ vuetify: "^1.2.0"
+ }
+ })
+}
+
+function renderFiles (api, opts) {
+ const pluginFilename = api.hasPlugin('typescript') ? 'vuetify.ts' : 'vuetify.js'
+ const pluginSourceFilename = 'vuetify.js'
+ api.render({
+ [`./src/plugins/${pluginFilename}`]: `../templates/default/src/plugins/${pluginSourceFilename}`
+ }, {
+ ...opts,
+ typescript: api.hasPlugin('typescript')
+ })
+
+ // Render files if we're replacing
+ const fs = require('fs')
+ const routerPath = api.resolve('./src/router.js')
+ opts.router = fs.existsSync(routerPath)
+
+ if (opts.replaceComponents) {
+ const files = {
+ './src/App.vue': '../templates/default/src/App.vue',
+ './src/assets/logo.png': '../templates/default/src/assets/logo.png'
+ }
+
+ if (opts.router) {
+ files['./src/views/Home.vue'] = '../templates/default/src/views/Home.vue'
+ } else {
+ api.render('../templates/hw')
+ }
+
+ api.render(files, opts)
+ }
+}
+
+function addImports (api) {
+ helpers.updateFile(api, api.entryFile, lines => {
+ const vueImportIndex = lines.findIndex(line => line.match(/^import Vue/))
+
+ lines.splice(vueImportIndex + 1, 0, `import './plugins/vuetify'`)
+
+ return lines
+ })
+}
+
+function setHtmlLang (api, locale) {
+ helpers.updateFile(api, './public/index.html', lines => {
+ const htmlIndex = lines.findIndex(line => line.match(/]+(\s|>)/))
+
+ if (htmlIndex !== -1) {
+ lines[htmlIndex] = lines[htmlIndex].replace(/(]+)(\s|>)/, `$1$3"${locale}"$5`)
+ }
+
+ return lines
+ })
+}
+
+module.exports = {
+ addDependencies,
+ addImports,
+ renderFiles,
+ setHtmlLang,
+}
diff --git a/prompts.js b/prompts.js
index 653c3e9b..c9a36dc8 100644
--- a/prompts.js
+++ b/prompts.js
@@ -11,6 +11,38 @@ module.exports = [
message: 'Use custom theme?',
default: false,
},
+ {
+ name: 'useCustomProperties',
+ type: 'confirm',
+ message: 'Use custom properties (CSS variables)?',
+ default: false,
+ },
+ {
+ name: 'iconFont',
+ type: 'rawlist',
+ message: 'Select icon font',
+ choices: [
+ 'Material Icons (default)',
+ 'Material Design Icons',
+ 'Font Awesome 5',
+ 'Font Awesome 4',
+ ],
+ default: 0,
+ filter: function (val) {
+ return {
+ 'Material Icons (default)': 'md',
+ 'Material Design Icons': 'mdi',
+ 'Font Awesome 5': 'fa',
+ 'Font Awesome 4': 'fa4',
+ }[val]
+ }
+ },
+ {
+ name: 'installFonts',
+ type: 'confirm',
+ message: 'Use fonts as a dependency (for Electron or offline)?',
+ default: false,
+ },
{
name: 'useAlaCarte',
type: 'confirm',
@@ -22,5 +54,43 @@ module.exports = [
type: 'confirm',
message: 'Use babel/polyfill?',
default: true
+ },
+ {
+ name: 'locale',
+ type: 'rawlist',
+ message: 'Select locale',
+ choices: [
+ 'English (default)',
+ 'Catalan',
+ 'Chinese (simplified)',
+ 'Chinese (traditional)',
+ 'Dutch',
+ 'Farsi',
+ 'French',
+ 'German',
+ 'Greek',
+ 'Polish',
+ 'Portuguese',
+ 'Russian',
+ 'Ukrainian',
+ ],
+ default: 0,
+ filter: function (val) {
+ return {
+ 'English (default)': 'en',
+ 'Catalan': 'ca',
+ 'Chinese (simplified)': 'zh-Hans',
+ 'Chinese (traditional)': 'zh-Hant',
+ 'Dutch': 'nl',
+ 'Farsi': 'fa',
+ 'French': 'fr',
+ 'German': 'de',
+ 'Greek': 'gr',
+ 'Polish': 'pl',
+ 'Portuguese': 'pt',
+ 'Russian': 'ru',
+ 'Ukrainian': 'uk',
+ }[val]
+ }
}
]
diff --git a/vue.config.js b/vue.config.js
new file mode 100644
index 00000000..877fbbba
--- /dev/null
+++ b/vue.config.js
@@ -0,0 +1,11 @@
+const path = require('path')
+
+module.exports = {
+ configureWebpack: {
+ resolve: {
+ alias: {
+ 'vue$': path.resolve('./node_modules/vue/dist/vue.common.js'),
+ },
+ },
+ },
+}