From 9bd9ccf887e7aae91265e147e53398053ec4f666 Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:42:27 +0200
Subject: [PATCH 01/10] feat: improvements
---
.eslintignore | 3 +-
.gitignore | 1 +
example/components/ColorModePicker.vue | 6 +-
jest.config.js | 3 +-
lib/module.js | 46 ++++++------
lib/script.js | 72 +++++++++++++++++++
lib/templates/plugin.client.js | 72 +++++++++++++++++++
.../color-mode.server.js => plugin.server.js} | 12 ++--
lib/templates/plugins/color-mode.client.js | 57 ---------------
lib/templates/script.js | 58 ---------------
lib/utils.js | 18 +++++
package.json | 5 ++
rollup.config.js | 18 +++++
yarn.lock | 50 ++++++++++++-
14 files changed, 266 insertions(+), 155 deletions(-)
create mode 100644 lib/script.js
create mode 100644 lib/templates/plugin.client.js
rename lib/templates/{plugins/color-mode.server.js => plugin.server.js} (71%)
delete mode 100644 lib/templates/plugins/color-mode.client.js
delete mode 100644 lib/templates/script.js
create mode 100644 lib/utils.js
create mode 100644 rollup.config.js
diff --git a/.eslintignore b/.eslintignore
index 0c32faf0..2b3360e6 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -4,5 +4,4 @@ dist
.nuxt
coverage
-# Plugin
-lib/templates/*
+*.min.js
diff --git a/.gitignore b/.gitignore
index 915f6ad5..990c8c67 100755
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ node_modules
.DS_Store
coverage
dist
+*.min.js
diff --git a/example/components/ColorModePicker.vue b/example/components/ColorModePicker.vue
index c0337b5f..2446e1c3 100644
--- a/example/components/ColorModePicker.vue
+++ b/example/components/ColorModePicker.vue
@@ -10,10 +10,10 @@
-
+
Color mode: {{ $colorMode.preference }}
({{ $colorMode.value }} mode detected)
-
+
@@ -39,7 +39,7 @@ export default {
methods: {
getClasses (color) {
// Does not set classes on ssr preference is system (because we know them on client-side)
- if (process.server && this.$colorMode.preference === 'system') {
+ if (this.$colorMode.unknown) {
return {}
}
return {
diff --git a/jest.config.js b/jest.config.js
index 7635fb1a..f00a7d1c 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,8 +2,7 @@ module.exports = {
testEnvironment: 'node',
collectCoverage: true,
collectCoverageFrom: [
- 'lib/**/*.js',
- '!lib/templates/**/*.js'
+ 'lib/**/*.js'
],
moduleNameMapper: {
'^~/(.*)$': '/lib/$1',
diff --git a/lib/module.js b/lib/module.js
index b7673fad..d2186ae9 100644
--- a/lib/module.js
+++ b/lib/module.js
@@ -1,12 +1,15 @@
-const { readFile } = require('fs').promises
-const { resolve } = require('path')
-const defu = require('defu')
-const template = require('lodash.template')
+import { resolve } from 'path'
+import { promises as fsp } from 'fs'
+import defu from 'defu'
+import template from 'lodash.template'
+import { addTemplates } from './utils'
-module.exports = async function (moduleOptions) {
+export default async function (moduleOptions) {
const defaults = {
preference: 'system',
fallback: 'light',
+ hid: 'nuxt-color-mode-script',
+ globalName: '__NUXT_COLOR_MODE__',
cookie: {
key: 'nuxt-color-mode',
options: {
@@ -20,32 +23,23 @@ module.exports = async function (moduleOptions) {
...moduleOptions
}, defaults)
- // Add plugin to inject $colorMode
- this.addPlugin({
- src: resolve(__dirname, 'templates', 'plugins', 'color-mode.client.js'),
- fileName: 'plugins/color-mode.client.js',
- options
- })
- this.addPlugin({
- src: resolve(__dirname, 'templates', 'plugins', 'color-mode.server.js'),
- fileName: 'plugins/color-mode.server.js',
- options
- })
+ // Add all templates
+ const templatesDir = resolve(__dirname, 'templates')
+ await addTemplates.call(this, templatesDir, 'color-mode', options)
// Add script to head to detect user or system preference before loading Nuxt (for SSR)
- let script = await readFile(resolve(__dirname, 'templates', 'script.js'), 'utf-8')
- script = template(script)({ options })
- // minify script for production
- if (!this.options.dev) {
- const { minify } = require('terser')
- script = minify(script).code
- }
+ const scriptPath = resolve(__dirname, 'script.min.js')
+ const scriptT = await fsp.readFile(scriptPath, 'utf-8')
+ const script = template(scriptT)({ options })
+
this.options.head.script = this.options.head.script || []
this.options.head.script.push({
- hid: 'nuxt-color-mode-script',
+ hid: options.hid,
innerHTML: script,
pbody: true
})
- this.options.head.__dangerouslyDisableSanitizersByTagID = this.options.head.__dangerouslyDisableSanitizersByTagID || {}
- this.options.head.__dangerouslyDisableSanitizersByTagID['nuxt-color-mode-script'] = ['innerHTML']
+
+ const serializeProp = '__dangerouslyDisableSanitizersByTagID'
+ this.options.head[serializeProp] = this.options.head[serializeProp] || {}
+ this.options.head[serializeProp][options.hid] = ['innerHTML']
}
diff --git a/lib/script.js b/lib/script.js
new file mode 100644
index 00000000..78194023
--- /dev/null
+++ b/lib/script.js
@@ -0,0 +1,72 @@
+// Add dark / light detection that runs before loading Nuxt.js
+
+// Global variable minimizers
+const w = window
+const d = document
+const de = d.documentElement
+
+const globalName = '__NUXT_COLOR_MODE__'
+const knownColorSchemes = ['dark', 'light']
+
+const preference = getCookie('<%= options.cookie.key %>') || '<%= options.preference %>'
+const value = preference === 'system' ? getColorScheme() : preference
+
+addClass(value)
+
+w[globalName] = {
+ preference,
+ value,
+ getColorScheme,
+ addClass,
+ removeClass
+}
+
+function getCookie (name) {
+ const nameEQ = name + '='
+ const cookies = d.cookie.split(';')
+
+ for (let i = 0; i < cookies.length; i++) {
+ let cookie = cookies[i]
+ while (cookie.charAt(0) === ' ') {
+ cookie = cookie.substring(1, cookie.length)
+ }
+ if (cookie.indexOf(nameEQ) === 0) {
+ return cookie.substring(nameEQ.length, cookie.length)
+ }
+ }
+ return null
+}
+
+function addClass (value) {
+ const className = value + '-mode'
+ if (de.classList) {
+ de.classList.add(className)
+ } else {
+ de.className += ' ' + className
+ }
+}
+
+function removeClass (value) {
+ const className = value + '-mode'
+ if (de.classList) {
+ de.classList.remove(className)
+ } else {
+ de.className = de.className.replace(new RegExp(className, 'g'), '')
+ }
+}
+
+function prefersColorScheme (suffix) {
+ return w.matchMedia('(prefers-color-scheme' + suffix + ')')
+}
+
+function getColorScheme () {
+ if (w.matchMedia && prefersColorScheme('').media !== 'not all') {
+ for (const colorScheme of knownColorSchemes) {
+ if (prefersColorScheme(':' + colorScheme).matches) {
+ return colorScheme
+ }
+ }
+ }
+
+ return '<%= options.fallback %>'
+}
diff --git a/lib/templates/plugin.client.js b/lib/templates/plugin.client.js
new file mode 100644
index 00000000..f16da55d
--- /dev/null
+++ b/lib/templates/plugin.client.js
@@ -0,0 +1,72 @@
+import Vue from 'vue'
+import { serialize } from 'cookie'
+
+const cookieKey = '<%= options.cookie.key %>'
+const cookieOptions = JSON.parse('<%= JSON.stringify(options.cookie.options) %>')
+const colorMode = window['<%= options.globalName %>']
+
+export default function (ctx, inject) {
+ const $colorMode = new Vue({
+ data: {
+ preference: colorMode.preference,
+ value: colorMode.value,
+ unknown: false
+ },
+ watch: {
+ preference (preference) {
+ if (preference === 'system') {
+ this.value = colorMode.getColorScheme()
+ this._watchMedia()
+ } else {
+ this.value = preference
+ }
+
+ this._storePreference(preference)
+ },
+ value (newValue, oldValue) {
+ colorMode.removeClass(oldValue)
+ colorMode.addClass(newValue)
+ }
+ },
+ created () {
+ if (this.preference === 'system') {
+ this._watchMedia()
+ }
+ if (window.localStorage) {
+ this._watchStorageChange()
+ }
+ },
+ methods: {
+ _watchMedia () {
+ if (this._mediaWatcher || !window.matchMedia) {
+ return
+ }
+
+ this._darkWatcher = window.matchMedia('(prefers-color-scheme: dark)')
+ this._darkWatcher.addListener((e) => {
+ if (this.preference === 'system') {
+ this.value = colorMode.getColorScheme()
+ }
+ })
+ },
+ _watchStorageChange () {
+ window.addEventListener('storage', (e) => {
+ if (e.key === cookieKey) {
+ this.preference = e.newValue
+ }
+ })
+ },
+ _storePreference (preference) {
+ // Cookies for SSR
+ document.cookie = serialize(cookieKey, preference, cookieOptions)
+
+ // Local storage to sync with other tabs
+ if (window.localStorage) {
+ window.localStorage.setItem(cookieKey, preference)
+ }
+ }
+ }
+ })
+
+ inject('colorMode', $colorMode)
+}
diff --git a/lib/templates/plugins/color-mode.server.js b/lib/templates/plugin.server.js
similarity index 71%
rename from lib/templates/plugins/color-mode.server.js
rename to lib/templates/plugin.server.js
index 94e779e9..0d2c38bd 100644
--- a/lib/templates/plugins/color-mode.server.js
+++ b/lib/templates/plugin.server.js
@@ -3,19 +3,21 @@ import { parse } from 'cookie'
const cookieKey = '<%= options.cookie.key %>'
export default function (ctx, inject) {
- // Read from cookie
let preference = '<%= options.preference %>'
+
+ // Try to read from cookies
if (ctx.req) {
// Check if cookie exist, otherwise TypeError: argument str must be a string
const cookies = parse(ctx.req.headers.cookie || '')
-
- if (cookies[cookieKey] && cookies[cookieKey] !== preference) {
+ if (cookies[cookieKey]) {
preference = cookies[cookieKey]
}
}
+
const colorMode = {
- preference: preference,
- value: preference
+ preference,
+ value: preference,
+ unknown: preference === 'system' /* TODO: Always true for static */
}
inject('colorMode', colorMode)
diff --git a/lib/templates/plugins/color-mode.client.js b/lib/templates/plugins/color-mode.client.js
deleted file mode 100644
index 8ba2f242..00000000
--- a/lib/templates/plugins/color-mode.client.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import Vue from 'vue'
-import { parse, serialize } from 'cookie'
-
-const options = <%= JSON.stringify(options) %>
-const wColorMode = window.__NUXT_COLOR_MODE__
-
-export default function (ctx, inject) {
- const colorMode = new Vue({
- data: {
- preference: wColorMode.preference,
- value: wColorMode.value
- },
- watch: {
- preference (preference) {
- if (preference === 'system') {
- this.value = wColorMode.getColorScheme()
- this._watchMedia()
- } else {
- this.value = preference
- }
- document.cookie = serialize(options.cookie.key, this.preference, options.cookie.options)
- // Tell others tabs to update the preference
- window.localStorage && window.localStorage.setItem(options.cookie.key, preference)
- },
- value (newValue, oldValue) {
- wColorMode.removeClass(oldValue)
- wColorMode.addClass(newValue)
- }
- },
- created () {
- if (this.preference === 'system') {
- this._watchMedia()
- }
- window.localStorage && this._watchCookieChange()
- },
- methods: {
- _watchMedia () {
- if (this._mediaWatcher || !window.matchMedia) return
- this._darkWatcher = window.matchMedia('(prefers-color-scheme: dark)')
- this._darkWatcher.addListener((e) => {
- if (this.preference === 'system') {
- this.value = wColorMode.getColorScheme()
- }
- })
- },
- _watchCookieChange () {
- window.addEventListener('storage', (e) => {
- if (e.key === options.cookie.key) {
- this.preference = e.newValue
- }
- })
- }
- }
- })
-
- inject('colorMode', colorMode)
-}
diff --git a/lib/templates/script.js b/lib/templates/script.js
deleted file mode 100644
index fa8b5394..00000000
--- a/lib/templates/script.js
+++ /dev/null
@@ -1,58 +0,0 @@
-// Add dark / light detection that runs before loading Nuxt.js.
-(function() {
- var getCookie = function (name) {
- var nameEQ = name + '=';
- var cookies = document.cookie.split(';');
-
- for (var i=0; i < cookies.length; i++) {
- var cookie = cookies[i];
- while (cookie.charAt(0) === ' ') {
- cookie = cookie.substring(1, cookie.length);
- }
- if (cookie.indexOf(nameEQ) == 0) {
- return cookie.substring(nameEQ.length, cookie.length);
- }
- }
- return null;
- }
- var addClass = function (value) {
- var className = value + '-mode'
- if (document.documentElement.classList) {
- document.documentElement.classList.add(className);
- } else {
- document.documentElement.className += ' ' + className;
- }
- }
- var removeClass = function (value) {
- var className = value + '-mode'
- if (document.documentElement.classList) {
- document.documentElement.classList.remove(className);
- } else {
- document.documentElement.className = document.documentElement.className.replace(new RegExp(className, 'g'), '')
- }
- }
- var getColorScheme = function () {
- var colorSchemeSupported = window.matchMedia && window.matchMedia('(prefers-color-scheme)').media !== 'not all'
- if (colorSchemeSupported && window.matchMedia('(prefers-color-scheme: dark)').matches) {
- return 'dark';
- } else if (colorSchemeSupported && window.matchMedia('(prefers-color-scheme: light)').matches) {
- return 'light';
- } else {
- return '<%= options.fallback %>';
- }
- }
- var preference = getCookie('<%= options.cookie.key %>') || '<%= options.preference %>';
- var value = preference;
-
- if (preference === 'system') {
- value = getColorScheme()
- }
- window.__NUXT_COLOR_MODE__ = {
- preference,
- value,
- getColorScheme,
- addClass,
- removeClass
- };
- addClass(value)
-})();
diff --git a/lib/utils.js b/lib/utils.js
new file mode 100644
index 00000000..e48f3a43
--- /dev/null
+++ b/lib/utils.js
@@ -0,0 +1,18 @@
+import { promises as fsp } from 'fs'
+import path from 'path'
+
+export async function addTemplates (templatesDir, name, options) {
+ const templates = await fsp.readdir(templatesDir)
+ for (const template of templates) {
+ const opts = {
+ src: path.resolve(templatesDir, template),
+ fileName: path.join(name, template),
+ options
+ }
+ if (template.indexOf('plugin') === 0) {
+ this.addPlugin(opts)
+ } else {
+ this.addTemplate(opts)
+ }
+ }
+}
diff --git a/package.json b/package.json
index fc099a91..fb2e02a8 100755
--- a/package.json
+++ b/package.json
@@ -15,7 +15,9 @@
"main": "lib/module.js",
"scripts": {
"dev": "nuxt example",
+ "build": "rollup -c",
"lint": "eslint --ext .js,.vue .",
+ "prepublish": "yarn build",
"release": "yarn test && standard-version && git push --follow-tags && npm publish",
"test": "yarn lint && jest"
},
@@ -38,6 +40,9 @@
"husky": "latest",
"jest": "latest",
"nuxt-edge": "latest",
+ "rollup": "^2.6.1",
+ "rollup-plugin-babel": "^4.4.0",
+ "rollup-plugin-terser": "^5.3.0",
"standard-version": "latest"
},
"publishConfig": {
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 00000000..30b4c4b2
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,18 @@
+import { terser } from 'rollup-plugin-terser'
+import babel from 'rollup-plugin-babel'
+
+export default {
+ input: './lib/script.js',
+ output: [
+ {
+ file: './lib/script.min.js',
+ format: 'iife',
+ plugins: [
+ terser()
+ ]
+ }
+ ],
+ plugins: [
+ babel()
+ ]
+}
diff --git a/yarn.lock b/yarn.lock
index de6f51f5..cb02e590 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,7 +2,7 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
@@ -4555,6 +4555,11 @@ estraverse@^5.0.0:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.0.0.tgz#ac81750b482c11cca26e4b07e83ed8f75fbcdc22"
integrity sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==
+estree-walker@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
+ integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
+
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -6396,6 +6401,14 @@ jest-watcher@^25.3.0:
jest-util "^25.3.0"
string-length "^3.1.0"
+jest-worker@^24.9.0:
+ version "24.9.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
+ integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==
+ dependencies:
+ merge-stream "^2.0.0"
+ supports-color "^6.1.0"
+
jest-worker@^25.1.0, jest-worker@^25.2.6:
version "25.2.6"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.2.6.tgz#d1292625326794ce187c38f51109faced3846c58"
@@ -9204,6 +9217,39 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
+rollup-plugin-babel@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb"
+ integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ rollup-pluginutils "^2.8.1"
+
+rollup-plugin-terser@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e"
+ integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==
+ dependencies:
+ "@babel/code-frame" "^7.5.5"
+ jest-worker "^24.9.0"
+ rollup-pluginutils "^2.8.2"
+ serialize-javascript "^2.1.2"
+ terser "^4.6.2"
+
+rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2:
+ version "2.8.2"
+ resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
+ integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
+ dependencies:
+ estree-walker "^0.6.1"
+
+rollup@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.6.1.tgz#8354e67caa7b8bf24c2488d9e2f64da2be62eebe"
+ integrity sha512-1RhFDRJeg027YjBO6+JxmVWkEZY0ASztHhoEUEWxOwkh4mjO58TFD6Uo7T7Y3FbmDpRTfKhM5NVxJyimCn0Elg==
+ optionalDependencies:
+ fsevents "~2.1.2"
+
rsvp@^4.8.4:
version "4.8.5"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
@@ -10073,7 +10119,7 @@ terser-webpack-plugin@^2.3.5:
terser "^4.4.3"
webpack-sources "^1.4.3"
-terser@^4.1.2, terser@^4.3.9, terser@^4.4.3, terser@^4.6.11:
+terser@^4.1.2, terser@^4.3.9, terser@^4.4.3, terser@^4.6.11, terser@^4.6.2:
version "4.6.11"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f"
integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==
From bf1e7de9166cd1f6893e9cf1b6e0ce62e05cadac Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:43:15 +0200
Subject: [PATCH 02/10] chore: update deps
---
package.json | 9 ++++-----
yarn.lock | 8 ++++----
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/package.json b/package.json
index fb2e02a8..5dad7b63 100755
--- a/package.json
+++ b/package.json
@@ -23,8 +23,7 @@
},
"dependencies": {
"defu": "^1.0.0",
- "lodash.template": "^4.5.0",
- "terser": "^4.6.11"
+ "lodash.template": "^4.5.0"
},
"devDependencies": {
"@babel/core": "latest",
@@ -40,9 +39,9 @@
"husky": "latest",
"jest": "latest",
"nuxt-edge": "latest",
- "rollup": "^2.6.1",
- "rollup-plugin-babel": "^4.4.0",
- "rollup-plugin-terser": "^5.3.0",
+ "rollup": "latest",
+ "rollup-plugin-babel": "latest",
+ "rollup-plugin-terser": "latest",
"standard-version": "latest"
},
"publishConfig": {
diff --git a/yarn.lock b/yarn.lock
index cb02e590..1eedc6c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9217,7 +9217,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
-rollup-plugin-babel@^4.4.0:
+rollup-plugin-babel@latest:
version "4.4.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb"
integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==
@@ -9225,7 +9225,7 @@ rollup-plugin-babel@^4.4.0:
"@babel/helper-module-imports" "^7.0.0"
rollup-pluginutils "^2.8.1"
-rollup-plugin-terser@^5.3.0:
+rollup-plugin-terser@latest:
version "5.3.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e"
integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==
@@ -9243,7 +9243,7 @@ rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2:
dependencies:
estree-walker "^0.6.1"
-rollup@^2.6.1:
+rollup@latest:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.6.1.tgz#8354e67caa7b8bf24c2488d9e2f64da2be62eebe"
integrity sha512-1RhFDRJeg027YjBO6+JxmVWkEZY0ASztHhoEUEWxOwkh4mjO58TFD6Uo7T7Y3FbmDpRTfKhM5NVxJyimCn0Elg==
@@ -10119,7 +10119,7 @@ terser-webpack-plugin@^2.3.5:
terser "^4.4.3"
webpack-sources "^1.4.3"
-terser@^4.1.2, terser@^4.3.9, terser@^4.4.3, terser@^4.6.11, terser@^4.6.2:
+terser@^4.1.2, terser@^4.3.9, terser@^4.4.3, terser@^4.6.2:
version "4.6.11"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f"
integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==
From 70e4297eaa9cb44495ec519d78cea09ba100797a Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:50:30 +0200
Subject: [PATCH 03/10] fix: use global name for script
---
lib/script.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/script.js b/lib/script.js
index 78194023..e3ffa35f 100644
--- a/lib/script.js
+++ b/lib/script.js
@@ -5,7 +5,6 @@ const w = window
const d = document
const de = d.documentElement
-const globalName = '__NUXT_COLOR_MODE__'
const knownColorSchemes = ['dark', 'light']
const preference = getCookie('<%= options.cookie.key %>') || '<%= options.preference %>'
@@ -13,7 +12,7 @@ const value = preference === 'system' ? getColorScheme() : preference
addClass(value)
-w[globalName] = {
+w['<%= options.globalName %>'] = {
preference,
value,
getColorScheme,
From f560ba90f25c0d0c97e2847a0a5e69a6da05e3fe Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:52:03 +0200
Subject: [PATCH 04/10] test: collect coverage only from module
---
jest.config.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/jest.config.js b/jest.config.js
index f00a7d1c..d0624ccf 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,7 +2,8 @@ module.exports = {
testEnvironment: 'node',
collectCoverage: true,
collectCoverageFrom: [
- 'lib/**/*.js'
+ 'lib/module.js',
+ 'lib/utils.js'
],
moduleNameMapper: {
'^~/(.*)$': '/lib/$1',
From ab80dec908b501ed28afe5b2f3a955c899e4bd2d Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:53:10 +0200
Subject: [PATCH 05/10] docs: add hid and globalName
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 1312ed94..7759554f 100755
--- a/README.md
+++ b/README.md
@@ -96,6 +96,8 @@ You can configure the module by providing the `colorMode` property in your `nuxt
colorMode: {
preference: 'system', // default value of $colorMode.preference
fallback: 'light', // fallback value if not system preference found
+ hid: 'nuxt-color-mode-script',
+ globalName: '__NUXT_COLOR_MODE__',
cookie: {
key: 'nuxt-color-mode',
options: {
From b15d5f8707da1d63a8dc6aeb57fdd8bdd885e1a4 Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 21:54:54 +0200
Subject: [PATCH 06/10] docs: mention uknown state
---
README.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 7759554f..e2df199b 100755
--- a/README.md
+++ b/README.md
@@ -54,8 +54,9 @@ yarn add --dev @nuxtjs/color-mode
## Usage
It injects `$colorMode` helper with:
-- `preference`: actual color-mode selected (can be `'system'`), update it to change the user prefered color mode
-- `value`: useful to know what color mode has been detected when `$colorMode === 'system'`, you should not update it
+- `preference`: Actual color-mode selected (can be `'system'`), update it to change the user prefered color mode
+- `value`: Useful to know what color mode has been detected when `$colorMode === 'system'`, you should not update it
+- `unknown`: Useful to know if during SSR or Generate, we need to render a placeholder
```vue
From 55872e2bb39d591373159e543ffe7be8a84f0c31 Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 22:12:44 +0200
Subject: [PATCH 07/10] feat: `` component
---
README.md | 16 +++++++++++++++-
example/components/ColorModePicker.vue | 4 ++--
lib/module.js | 1 +
lib/templates/color-scheme.js | 17 +++++++++++++++++
lib/templates/plugin.client.js | 3 +++
lib/templates/plugin.server.js | 5 ++++-
6 files changed, 42 insertions(+), 4 deletions(-)
create mode 100644 lib/templates/color-scheme.js
diff --git a/README.md b/README.md
index e2df199b..84a5a9bf 100755
--- a/README.md
+++ b/README.md
@@ -99,6 +99,7 @@ colorMode: {
fallback: 'light', // fallback value if not system preference found
hid: 'nuxt-color-mode-script',
globalName: '__NUXT_COLOR_MODE__',
+ componentName: 'ColorScheme',
cookie: {
key: 'nuxt-color-mode',
options: {
@@ -114,7 +115,20 @@ Notes:
## Caveats
-With `nuxt generate` and using `$colorMode` in your Vue template, you may expect a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page, it will directly set the `fallback` value (or `default` value if no set to `'system'`).
+Using SSR if default value is `system` and also With `nuxt generate` and using `$colorMode` in your Vue template, you may expect a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page, it will directly set the `fallback` value (or `default` value if no set to `'system'`).
+
+You have to guard any rendering path which depends on `$colorMode` with `$colorMode.unknown` to render placeholder or use `` component.
+
+***Example:**
+
+```vue
+
+
+ Color mode: {{ $colorMode.preference }}
+ ({{ $colorMode.value }} mode detected)
+
+
+```
## TailwindCSS Dark Mode
diff --git a/example/components/ColorModePicker.vue b/example/components/ColorModePicker.vue
index 2446e1c3..d7719842 100644
--- a/example/components/ColorModePicker.vue
+++ b/example/components/ColorModePicker.vue
@@ -10,10 +10,10 @@
-
+
Color mode: {{ $colorMode.preference }}
({{ $colorMode.value }} mode detected)
-
+
diff --git a/lib/module.js b/lib/module.js
index d2186ae9..0cd0fb2d 100644
--- a/lib/module.js
+++ b/lib/module.js
@@ -10,6 +10,7 @@ export default async function (moduleOptions) {
fallback: 'light',
hid: 'nuxt-color-mode-script',
globalName: '__NUXT_COLOR_MODE__',
+ componentName: 'ColorScheme',
cookie: {
key: 'nuxt-color-mode',
options: {
diff --git a/lib/templates/color-scheme.js b/lib/templates/color-scheme.js
new file mode 100644
index 00000000..d37ced7b
--- /dev/null
+++ b/lib/templates/color-scheme.js
@@ -0,0 +1,17 @@
+export default {
+ name: '<%= options.componentName %>',
+ functional: true,
+ render (createElement, context) {
+ const tag = context.tag || 'span'
+ const { $colorMode } = context.parent
+
+ if (!$colorMode.unknown) {
+ return createElement(tag, context.data, context.children)
+ }
+
+ return createElement('client-only', {
+ 'placeholder-tag': tag,
+ ...context.data
+ }, context.children)
+ }
+}
diff --git a/lib/templates/plugin.client.js b/lib/templates/plugin.client.js
index f16da55d..509a2f53 100644
--- a/lib/templates/plugin.client.js
+++ b/lib/templates/plugin.client.js
@@ -1,5 +1,8 @@
import Vue from 'vue'
import { serialize } from 'cookie'
+import colorSchemeComponent from './color-scheme'
+
+Vue.component('<%= options.componentName %>', colorSchemeComponent)
const cookieKey = '<%= options.cookie.key %>'
const cookieOptions = JSON.parse('<%= JSON.stringify(options.cookie.options) %>')
diff --git a/lib/templates/plugin.server.js b/lib/templates/plugin.server.js
index 0d2c38bd..13468cf0 100644
--- a/lib/templates/plugin.server.js
+++ b/lib/templates/plugin.server.js
@@ -1,7 +1,10 @@
+import Vue from 'vue'
import { parse } from 'cookie'
-
+import colorSchemeComponent from './color-scheme'
const cookieKey = '<%= options.cookie.key %>'
+Vue.component('<%= options.componentName %>', colorSchemeComponent)
+
export default function (ctx, inject) {
let preference = '<%= options.preference %>'
From 202055cf29b10be69c7356d4c269599d2c40ded1 Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 22:13:33 +0200
Subject: [PATCH 08/10] feat: always enable unknown on static mode for server
plugin
---
lib/templates/plugin.server.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/templates/plugin.server.js b/lib/templates/plugin.server.js
index 13468cf0..c92e550d 100644
--- a/lib/templates/plugin.server.js
+++ b/lib/templates/plugin.server.js
@@ -20,7 +20,7 @@ export default function (ctx, inject) {
const colorMode = {
preference,
value: preference,
- unknown: preference === 'system' /* TODO: Always true for static */
+ unknown: process.static || preference === 'system'
}
inject('colorMode', colorMode)
From dce6fd8a908b6145a65dd33c5041c576d9248741 Mon Sep 17 00:00:00 2001
From: pooya parsa
Date: Wed, 15 Apr 2020 22:14:01 +0200
Subject: [PATCH 09/10] feat: enable unknown if req is not available
---
lib/templates/plugin.server.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/templates/plugin.server.js b/lib/templates/plugin.server.js
index c92e550d..7ce90142 100644
--- a/lib/templates/plugin.server.js
+++ b/lib/templates/plugin.server.js
@@ -20,7 +20,7 @@ export default function (ctx, inject) {
const colorMode = {
preference,
value: preference,
- unknown: process.static || preference === 'system'
+ unknown: process.static || !ctx.req || preference === 'system'
}
inject('colorMode', colorMode)
From 33b61ccdb95752f5308de9aa7ba6a107f87f305f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Chopin?=
Date: Wed, 15 Apr 2020 22:50:22 +0200
Subject: [PATCH 10/10] chore: improve caveats section
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 84a5a9bf..be8f24a8 100755
--- a/README.md
+++ b/README.md
@@ -115,18 +115,18 @@ Notes:
## Caveats
-Using SSR if default value is `system` and also With `nuxt generate` and using `$colorMode` in your Vue template, you may expect a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page, it will directly set the `fallback` value (or `default` value if no set to `'system'`).
+If you are doing SSR (`nuxt start` or `nuxt generate`) and if `$colorMode.preference` is set to `'system'`, using `$colorMode` in your Vue template will lead to a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page since they are detected on client-side.
-You have to guard any rendering path which depends on `$colorMode` with `$colorMode.unknown` to render placeholder or use `` component.
+You have to guard any rendering path which depends on `$colorMode` with `$colorMode.unknown` to render a placeholder or directory use our `` component.
***Example:**
```vue
-
+
Color mode: {{ $colorMode.preference }}
({{ $colorMode.value }} mode detected)
-
+
```