Skip to content

Commit 5d248ea

Browse files
authored
feat: add material presets (#143)
* feat: add basil material preset * chore: rename plugin * chore: add semver package, clean up helpers * refactor: update files when installing preset now imports preset and updates vuetify object, bootstraps sass variables and updates public.html for fonts * refactor(basil): update preset export case * refactor(basil): clean-up preset * chore: change author email * feat(crane): add new preset * chore: add comments on Vuetify object update code * chore: move vuetify shared utils to deps * chore: add LICENSE files and update all READMEs * refactor(presets): add onCreateComplete arg for generatePreset * chore: remove comment * fix: add missing callback parameter in function * refactor: rename utils package, make public * chore: change package versions * chore: remove test script * chore: revert version changes * chore: remove private from lerna * chore(release): publish %s - @vuetify/[email protected] - [email protected] - [email protected] - [email protected] * chore(release): publish %s - @vuetify/[email protected] - [email protected] - [email protected] - [email protected] * chore: change util version * chore: update package.json files for all packages * chore(release): publish %s - @vuetify/[email protected] - [email protected] - [email protected] - [email protected] * chore: add back private to lerna * chore: update lock file * fix: move shelljs to dependencies * chore: move shelljs dependency to specific package * fix(generator): add correct google font href * feat(fortnightly): add new preset * feat(owl): add new preset * feat(reply): add new preset * refactor: remove component style import * feat(rally): add new preset * refactor(basil): clean-up styles, fix visual design inconsistencies * refactor(fortnightly): clean-up styles and fix visual disparities from the study * refactor(owl): clean-up styles and fix spec issues * refactor(reply): clean-up preset, improve styles * feat(shrine): create new preset * refactor(@vuetify/cli-plugin-utils): update naming convention of multiple methods * chore(README): update information * chore(README): update information for root and plugin utils
1 parent ec7577a commit 5d248ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1986
-2857
lines changed

LICENSE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Released under MIT License
22

3-
Copyright (c) 2016-present Vuetify LLC
3+
Copyright (c) 2016-present Vuetify, LLC
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
66

README.md

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Vuetify CLI Plugins [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/)
2+
3+
> A collection of Vuetify plugins for Vue CLI
4+
5+
### Available Packages
6+
<table>
7+
<thead>
8+
<tr>
9+
<th>Project</th>
10+
<th>Version</th>
11+
<th>Description</th>
12+
</tr>
13+
</thead>
14+
<tbody>
15+
<tr>
16+
<td>
17+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify">@vuetify/cli-plugin-utils</a>
18+
</td>
19+
<td>
20+
<a href="https://www.npmjs.com/package/@vuetify/cli-plugin-utils">
21+
<img src="https://img.shields.io/npm/v/@vuetify/cli-plugin-utils.svg" alt="Version">
22+
</a>
23+
</td>
24+
<td>
25+
A collection of helper utilities for creating Vue CLI plugins
26+
</td>
27+
</tr>
28+
<tr>
29+
<td>
30+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify">vue-cli-plugin-vuetify</a>
31+
</td>
32+
<td>
33+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
34+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify.svg" alt="Version">
35+
</a>
36+
</td>
37+
<td>
38+
A Vue CLI plugin for installing and configuring Vuetify
39+
</td>
40+
</tr>
41+
<tr>
42+
<td>
43+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-basil">vue-cli-plugin-vuetify-preset-basil</a>
44+
</td>
45+
<td>
46+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
47+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-basil.svg" alt="Version">
48+
</a>
49+
</td>
50+
<td>
51+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/basil.html">Basil Material Study</a>
52+
</td>
53+
</tr>
54+
<tr>
55+
<td>
56+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-crane">vue-cli-plugin-vuetify-preset-crane</a>
57+
</td>
58+
<td>
59+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
60+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-crane.svg" alt="Version">
61+
</a>
62+
</td>
63+
<td>
64+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/crane.html">Crane Material Study</a>
65+
</td>
66+
</tr>
67+
<tr>
68+
<td>
69+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-fortnightly">vue-cli-plugin-vuetify-preset-fortnightly</a>
70+
</td>
71+
<td>
72+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
73+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-fortnightly.svg" alt="Version">
74+
</a>
75+
</td>
76+
<td>
77+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/fortnightly.html">Fortnightly Material Study</a>
78+
</td>
79+
</tr>
80+
<tr>
81+
<td>
82+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-owl">vue-cli-plugin-vuetify-preset-owl</a>
83+
</td>
84+
<td>
85+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
86+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-owl.svg" alt="Version">
87+
</a>
88+
</td>
89+
<td>
90+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/owl.html">Owl Material Study</a>
91+
</td>
92+
</tr>
93+
<tr>
94+
<td>
95+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-rally">vue-cli-plugin-vuetify-preset-rally</a>
96+
</td>
97+
<td>
98+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
99+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-rally.svg" alt="Version">
100+
</a>
101+
</td>
102+
<td>
103+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/rally.html">Rally Material Study</a>
104+
</td>
105+
</tr>
106+
<tr>
107+
<td>
108+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-reply">vue-cli-plugin-vuetify-preset-reply</a>
109+
</td>
110+
<td>
111+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
112+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-reply.svg" alt="Version">
113+
</a>
114+
</td>
115+
<td>
116+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/reply.html">Reply Material Study</a>
117+
</td>
118+
</tr>
119+
<tr>
120+
<td>
121+
<a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify/tree/master/packages/vue-cli-plugin-vuetify-preset-shrine">vue-cli-plugin-vuetify-preset-shrine</a>
122+
</td>
123+
<td>
124+
<a href="https://www.npmjs.com/package/vue-cli-plugin-vuetify">
125+
<img src="https://img.shields.io/npm/v/vue-cli-plugin-vuetify-preset-shrine.svg" alt="Version">
126+
</a>
127+
</td>
128+
<td>
129+
A Vuetify Preset for the <a href="https://material.io/design/material-studies/shrine.html">Shrine Material Study</a>
130+
</td>
131+
</tr>
132+
</tbody>
133+
</table>
134+
135+
### 🔮 About Presets
136+
Vuetify Presets are an in progress feature that will be enhanced as Vuetify gains new functionality in the future, such as global component defaults. They are our _best-guess_ implementation of the official [Material Design Studies](https://material.io/design/material-studies/about-our-material-studies.html). The studies are more visual than they are technical and in many cases must have aspects of their specification inferred. There are also cases in which part of a study _**will not**_ be supported:
137+
138+
You can find more information about presets in the [Vuetify preset documentation](https://vuetifyjs.com/customization/presets).
139+
140+
### 📑 License
141+
[MIT](http://opensource.org/licenses/MIT)
142+
143+
Copyright (c) 2016-present Vuetify, LLC

package.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"private": true,
32
"workspaces": [
43
"packages/*"
54
],
5+
"private": true,
66
"husky": {
77
"hooks": {
88
"pre-commit": "yarn lerna run test"
@@ -11,6 +11,11 @@
1111
"devDependencies": {
1212
"husky": "^3.1.0",
1313
"lerna": "^3.19.0",
14-
"lerna-changelog": "^0.8.3"
14+
"lerna-changelog": "^0.8.3",
15+
"semver": "^6.3.0",
16+
"vue": "^2.6.4",
17+
"vue-template-compiler": "^2.5.0",
18+
"vuetify": "^2.1.13",
19+
"webpack": "^4.0.0"
1520
}
1621
}

packages/cli-plugin-utils/LICENSE.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Released under MIT License
2+
3+
Copyright (c) 2016-present Vuetify, LLC
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

packages/cli-plugin-utils/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `@vuetify/cli-plugin-utils`
2+
3+
> This package provides shared utility helper functions for all plugin packages
4+
5+
For more information on how to use these utilities, checkout the preset [Plugin development guide](https://dev.vuetifyjs.com/en/customization/presets#plugin-development-guide).

packages/cli-plugin-utils/index.js

+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
// Utilities
2+
const semver = require('semver')
3+
const fs = require('fs')
4+
5+
// Injects a <link> element into ./public/index.html
6+
function injectHtmlLink (api, font, attrs) {
7+
updateFile(api, './public/index.html', lines => {
8+
const lastLink = lines.reverse().findIndex(line => line.match(/^\s*<\/head>/))
9+
const link = `<link ${attrs} href="${font}&display=swap">`
10+
11+
if (lines.join('').indexOf(link) > -1) {
12+
return lines.reverse()
13+
}
14+
15+
lines.splice(lastLink + 1, 0, ` ${link}`)
16+
17+
return lines.reverse()
18+
})
19+
}
20+
21+
// Injects a font <link> into ./public/index.html
22+
function injectGoogleFontLink (api, font) {
23+
font = !Array.isArray(font) ? [font] : font
24+
25+
const url = font.map(str => {
26+
const {
27+
family = str,
28+
weights = '100,300,400,500,700,900',
29+
} = str.split(':')
30+
31+
return `${family}:${weights}`
32+
}).join('|')
33+
34+
return injectHtmlLink(api, `https://fonts.googleapis.com/css?family=${url}`, 'rel="stylesheet"')
35+
}
36+
37+
// Injects target SASS variables file
38+
function injectSassVariables (
39+
api,
40+
file,
41+
modules = ['vue-modules', 'vue', 'normal-modules', 'normal']
42+
) {
43+
api.chainWebpack(config => {
44+
modules.forEach(match => {
45+
for (let i = 0; i < 2; i++) {
46+
const boolean = Boolean(i)
47+
const rule = boolean ? 'sass' : 'scss'
48+
const end = boolean ? "'" : "';"
49+
50+
config.module
51+
.rule(rule)
52+
.oneOf(match)
53+
.use('sass-loader')
54+
.tap(opt => mergeSassVariables(opt, `'${file}${end}`))
55+
}
56+
})
57+
})
58+
}
59+
60+
function generatePreset (api, preset, onCreateComplete) {
61+
if (!api.hasPlugin('vuetify')) {
62+
console.error('Vuetify presets require the `vue-cli-plugin-vuetify` package.')
63+
64+
return
65+
}
66+
67+
const file = 'src/plugins/vuetify.js'
68+
const plugin = api.resolve(file)
69+
70+
if (!fs.existsSync(plugin)) {
71+
console.warn('Unable to locate `vuetify.js` plugin file in `src/plugins`.')
72+
73+
return
74+
}
75+
76+
api.injectImports(file, `import { preset } from ${preset}`)
77+
78+
api.onCreateComplete(() => {
79+
updateVuetifyObject(api, 'preset')
80+
81+
typeof onCreateComplete === 'function' && onCreateComplete()
82+
})
83+
}
84+
85+
// Check if file exists in user project
86+
function fileExists (api, file) {
87+
return fs.existsSync(api.resolve(file))
88+
}
89+
90+
// Create an import statement
91+
// to bootstrap a users variables
92+
function mergeSassVariables (opt, file) {
93+
const variables = `@import ${file}`
94+
95+
let sassLoaderVersion
96+
try {
97+
sassLoaderVersion = semver.major(require('sass-loader/package.json').version)
98+
} catch (e) {}
99+
100+
// Merge with user-defined loader data config
101+
if (sassLoaderVersion < 8) opt.data = variables
102+
else opt.prependData = variables
103+
104+
return opt
105+
}
106+
107+
// Update local file with supplied callback
108+
function updateFile (api, file, callback) {
109+
const { EOL } = require('os')
110+
file = api.resolve(file)
111+
let content = fs.existsSync(file)
112+
? fs.readFileSync(file, { encoding: 'utf8' })
113+
: ''
114+
115+
content = callback(content.split(/\r?\n/g)).join(EOL)
116+
117+
fs.writeFileSync(file, content, { encoding: 'utf-8' })
118+
}
119+
120+
// Add new property to the Vuetify object
121+
function updateVuetifyObject (api, value) {
122+
updateFile(api, 'src/plugins/vuetify.js', content => {
123+
const existingValue = str => (
124+
str.indexOf(`${value},`) > -1 ||
125+
str.indexOf(`${value}:`) > -1
126+
)
127+
128+
// If content already exists, skip update
129+
if (content.find(existingValue)) {
130+
return content
131+
}
132+
133+
const index = content.findIndex(str => {
134+
return str.indexOf('new Vuetify(') > -1
135+
})
136+
const vuetify = content[index]
137+
138+
if (!vuetify) {
139+
console.warn('Unable to locate Vuetify instantiation in `src/plugins/vuetify.js`.')
140+
141+
return
142+
}
143+
144+
const optionsStartIndex = vuetify.indexOf('({')
145+
const optionsStopIndex = vuetify.indexOf('})')
146+
const hasMultilineObject = optionsStartIndex > -1
147+
const hasInlineObject = (
148+
hasMultilineObject &&
149+
optionsStopIndex > -1
150+
)
151+
152+
// new Vuetify({ ... })
153+
if (hasInlineObject) {
154+
const start = vuetify.slice(0, optionsStartIndex + 2)
155+
const stop = vuetify.slice(optionsStartIndex + 2)
156+
157+
content[index] = `${start} ${value} ${stop}`
158+
// new Vuetify({
159+
// ...
160+
// })
161+
} else if (hasMultilineObject) {
162+
content.splice(index + 1, 0, ` ${value},`)
163+
// new Vuetify()
164+
} else {
165+
const vuetifyStartIndex = vuetify.indexOf('(')
166+
const start = vuetify.slice(0, vuetifyStartIndex + 2)
167+
168+
content[index] = `${start}{ ${value} })`
169+
}
170+
// TODO: Handle new Vuetify(options) - user options being passed
171+
172+
return content
173+
})
174+
}
175+
176+
// Helper functions for Vuetify presets
177+
function VuetifyPresetService (api, preset) {
178+
injectSassVariables(api, `~vue-cli-plugin-vuetify-preset-${preset}/preset/variables.scss`)
179+
}
180+
181+
function VuetifyPresetGenerator (api, preset, onCreateComplete) {
182+
generatePreset(api, `'vue-cli-plugin-vuetify-preset-${preset}/preset'`, onCreateComplete)
183+
}
184+
185+
module.exports = {
186+
fileExists,
187+
generatePreset,
188+
injectGoogleFontLink,
189+
injectHtmlLink,
190+
injectSassVariables,
191+
mergeSassVariables,
192+
updateFile,
193+
updateVuetifyObject,
194+
VuetifyPresetGenerator,
195+
VuetifyPresetService,
196+
}

0 commit comments

Comments
 (0)