├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── demo.html ├── main.d.ts ├── main.js ├── package.json └── renovate.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-detectable=false -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: jaywcjlove 2 | buy_me_a_coffee: jaywcjlove 3 | custom: ["https://www.paypal.me/kennyiseeyou", "https://jaywcjlove.github.io/#/sponsor"] 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | build-deploy: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: write 12 | id-token: write 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | registry-url: 'https://registry.npmjs.org' 19 | 20 | - run: npm install 21 | - run: npm run build 22 | - run: cp -rp main.js dist/main.js 23 | 24 | - name: 🌐 Generate Documentation Website 25 | uses: jaywcjlove/action-ejs@main 26 | with: 27 | template-file: demo.html 28 | output: dist/index.html 29 | vars-file: | 30 | { "markdownString": "./README.md" } 31 | 32 | - name: Generate Contributors Images 33 | uses: jaywcjlove/github-action-contributors@main 34 | with: 35 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\]) 36 | output: dist/CONTRIBUTORS.svg 37 | avatarSize: 42 38 | 39 | - name: Is a tag created auto? 40 | id: create_tag 41 | uses: jaywcjlove/create-tag-action@main 42 | with: 43 | token: ${{ secrets.GITHUB_TOKEN }} 44 | package-path: ./package.json 45 | 46 | - name: get tag version 47 | id: tag_version 48 | uses: jaywcjlove/changelog-generator@main 49 | 50 | - name: Deploy 51 | uses: peaceiris/actions-gh-pages@v4 52 | with: 53 | user_name: 'github-actions[bot]' 54 | user_email: 'github-actions[bot]@users.noreply.github.com' 55 | commit_message: ${{steps.tag_version.outputs.tag}} ${{ github.event.head_commit.message }} 56 | github_token: ${{ secrets.GITHUB_TOKEN }} 57 | publish_dir: ./dist 58 | 59 | - name: Generate Changelog 60 | id: changelog 61 | uses: jaywcjlove/changelog-generator@main 62 | if: steps.create_tag.outputs.successful 63 | with: 64 | token: ${{ secrets.GITHUB_TOKEN }} 65 | head-ref: ${{ steps.create_tag.outputs.version }} 66 | filter-author: (小弟调调™|Renovate Bot) 67 | filter: '[R|r]elease[d]\s+[v|V]\d(\.\d+){0,2}' 68 | 69 | - name: Create Release 70 | uses: ncipollo/release-action@v1 71 | if: steps.create_tag.outputs.successful 72 | with: 73 | token: ${{ secrets.GITHUB_TOKEN }} 74 | name: ${{ steps.create_tag.outputs.version }} 75 | tag: ${{ steps.create_tag.outputs.version }} 76 | body: | 77 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) [![](https://img.shields.io/badge/Open%20in-unpkg-blue)](https://uiwjs.github.io/npm-unpkg/#/pkg/@wcj/dark-mode@${{steps.create_tag.outputs.versionNumber}}/file/README.md) 78 | 79 | Documentation ${{ steps.changelog.outputs.tag }}: https://raw.githack.com/jaywcjlove/dark-mode/${{ steps.changelog.outputs.gh-pages-short-hash }}/index.html 80 | Comparing Changes: ${{ steps.changelog.outputs.compareurl }} 81 | 82 | ${{ steps.changelog.outputs.changelog }} 83 | 84 | ```bash 85 | npm i @wcj/dark-mode@${{steps.create_tag.outputs.versionNumber}} 86 | ``` 87 | 88 | - run: rm -rf dist/index.html 89 | - run: rm -rf dist/main.js 90 | 91 | - run: npm publish --access public --provenance 92 | name: 📦 compile-less-cli publish to NPM 93 | continue-on-error: true 94 | env: 95 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 96 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | 4 | npm-debug.log* 5 | package-lock.json 6 | yarn.lock 7 | 8 | .DS_Store 9 | .eslintcache 10 | .cache 11 | .rollup.cache 12 | .vscode 13 | 14 | *.log 15 | *.bak 16 | *.tem 17 | *.temp 18 | #.swp 19 | *.*~ 20 | ~*.* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dark-mode 2 | === 3 | 4 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 5 | [![CI](https://github.com/jaywcjlove/dark-mode/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/dark-mode/actions/workflows/ci.yml) 6 | [![jsDelivr CDN](https://data.jsdelivr.com/v1/package/npm/@wcj/dark-mode/badge?style=rounded)](https://www.jsdelivr.com/package/npm/@wcj/dark-mode) 7 | [![NPM Downloads](https://img.shields.io/npm/dm/@wcj/dark-mode.svg?style=flat)](https://www.npmjs.com/package/@wcj/dark-mode) 8 | [![npm version](https://img.shields.io/npm/v/@wcj/dark-mode.svg)](https://www.npmjs.com/package/@wcj/dark-mode) 9 | [![Open in unpkg](https://img.shields.io/badge/Open%20in-unpkg-blue)](https://uiwjs.github.io/npm-unpkg/#/pkg/@wcj/dark-mode/file/README.md) 10 | 11 | A custom element that allows you to easily put a Dark Mode 🌒 toggle. so you can initially adhere to your users' preferences according to [`prefers-color-scheme`](https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme), but also allow them to (optionally permanently) override their system setting for just your site. 12 | 13 | ## Installation 14 | 15 | Install from npm: 16 | 17 | ```bash 18 | npm install --save @wcj/dark-mode 19 | ``` 20 | 21 | Or, alternatively, use a ` 27 | ``` 28 | 29 | ## Usage 30 | 31 | There are two ways how you can use ``: 32 | 33 | ```html 34 | 35 | 36 | 37 | ``` 38 | 39 | Use in [React](https://github.com/facebook/react): 40 | 41 | ```jsx 42 | import React from 'react'; 43 | import '@wcj/dark-mode'; 44 | 45 | function Demo() { 46 | return ( 47 |
48 | 49 |
50 | ); 51 | } 52 | ``` 53 | 54 | Toggle in JavaScript: 55 | 56 | ```js 57 | const toggle = document.querySelector('dark-mode'); 58 | const button = document.createElement('button'); 59 | button.textContent = 'Change Theme'; 60 | button.onclick = () => { 61 | const theme = document.documentElement.dataset.colorMode; 62 | // or => const theme = toggle.mode 63 | document.documentElement.setAttribute('data-color-mode', theme === 'light' ? 'dark' : 'light'); 64 | } 65 | document.body.appendChild(button); 66 | // Listen for toggle changes 67 | // and toggle the `dark` class accordingly. 68 | document.addEventListener('colorschemechange', (e) => { 69 | console.log(`Color scheme changed to "${e.detail.colorScheme}" or "${toggle.mode}".`); 70 | button.textContent = toggle.mode === 'dark' ? 'Change Theme 🌞' : 'Change Theme 🌒'; 71 | }); 72 | ``` 73 | 74 | Interacting with the custom element: 75 | 76 | ```js 77 | const darkMode = document.querySelector('dark-mode'); 78 | 79 | // Set the mode to dark 80 | darkMode.mode = 'dark'; 81 | // Set the mode to light 82 | darkMode.mode = 'light'; 83 | // Set the mode to dark 84 | document.documentElement.setAttribute('data-color-mode', 'dark'); 85 | // Set the mode to light 86 | document.documentElement.setAttribute('data-color-mode', 'light'); 87 | 88 | // Set the light label to "off" 89 | darkMode.light = 'off'; 90 | // Set the dark label to "on" 91 | darkMode.dark = 'on'; 92 | 93 | // Set a "remember the last selected mode" label 94 | darkMode.permanent = true; 95 | 96 | // Remember the user's last color scheme choice 97 | darkModeToggle.setAttribute('permanent', false); 98 | // Forget the user's last color scheme choice 99 | darkModeToggle.removeAttribute('permanent'); 100 | ``` 101 | 102 | Reacting on color scheme changes: 103 | 104 | ```js 105 | /* On the page */ 106 | document.addEventListener('colorschemechange', (e) => { 107 | console.log(`Color scheme changed to ${e.detail.colorScheme}.`); 108 | }); 109 | ``` 110 | 111 | Reacting on "remember the last selected mode" functionality changes: 112 | 113 | ```js 114 | /* On the page */ 115 | document.addEventListener('permanentcolorscheme', (e) => { 116 | console.log(`${e.detail.permanent ? 'R' : 'Not r'}emembering the last selected mode.`); 117 | }); 118 | ``` 119 | 120 | ## Hide Text and Icons 121 | 122 | You can use the following CSS selectors to hide the text and icon parts of the `dark-mode` component: 123 | 124 | ```css 125 | dark-mode::part(text) { 126 | display: none; 127 | } 128 | dark-mode::part(icon) { 129 | display: none; 130 | } 131 | ``` 132 | 133 | ## Properties 134 | 135 | Properties can be set directly on the custom element at creation time, or dynamically via JavaScript. 136 | 137 | ```typescript 138 | export type ColorScheme = 'light' | 'dark'; 139 | export class DarkMode extends HTMLElement { 140 | mode?: ColorScheme; 141 | /** 142 | * Defaults to not remember the last choice. 143 | * If present remembers the last selected mode (`dark` or `light`), 144 | * which allows the user to permanently override their usual preferred color scheme. 145 | */ 146 | permanent?: boolean; 147 | /** 148 | * Any string value that represents the label for the "dark" mode. 149 | */ 150 | dark?: string; 151 | /** 152 | * Any string value that represents the label for the "light" mode. 153 | */ 154 | light?: string; 155 | style?: React.CSSProperties; 156 | } 157 | ``` 158 | 159 | ## Events 160 | 161 | - `colorschemechange`: Fired when the color scheme gets changed. 162 | - `permanentcolorscheme`: Fired when the color scheme should be permanently remembered or not. 163 | 164 | ## Alternatives 165 | 166 | - [dark-mode-toggle](https://github.com/GoogleChromeLabs/dark-mode-toggle) A custom element that allows you to easily put a Dark Mode 🌒 toggle or switch on your site 167 | - [Darkmode.js](https://github.com/sandoche/Darkmode.js) Add a dark-mode / night-mode to your website in a few seconds 168 | - [darken](https://github.com/ColinEspinas/darken) Dark mode made easy 169 | - [use-dark-mode](https://github.com/donavon/use-dark-mode) A custom React Hook to help you implement a "dark mode" component. 170 | - [Dark Mode Switch](https://github.com/coliff/dark-mode-switch) Add a dark-mode theme toggle with a Bootstrap Custom Switch 171 | 172 | ## Contributors 173 | 174 | As always, thanks to our amazing contributors! 175 | 176 | 177 | 178 | 179 | 180 | Made with [github-action-contributors](https://github.com/jaywcjlove/github-action-contributors). 181 | 182 | ## License 183 | 184 | Licensed under the [MIT License](https://opensource.org/licenses/MIT). 185 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | dark-mode 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 |

Hi there!

25 |
I'm your cool new webpage! Use the toggle in the 👈 button to switch my theme.
26 | 27 | 28 |

29 | Github: @jaywcjlove/dark-mode 30 |
31 |
32 | 52 | 53 | 54 |
55 |
56 | 57 | 👈 The mode is remembered after clicking it. 58 |

59 | 68 |

69 |
loading...
70 | 71 | 72 | 82 | 83 | -------------------------------------------------------------------------------- /main.d.ts: -------------------------------------------------------------------------------- 1 | export type ColorScheme = 'light' | 'dark'; 2 | export type ColorSchemeChangeEvent = CustomEvent<{ colorScheme: ColorScheme }>; 3 | export type PermanentColorSchemeEvent = CustomEvent<{ colorScheme: ColorScheme, permanent: boolean }>; 4 | 5 | export class DarkMode extends HTMLElement { 6 | mode?: ColorScheme; 7 | /** 8 | * Defaults to not remember the last choice. 9 | * If present remembers the last selected mode (`dark` or `light`), 10 | * which allows the user to permanently override their usual preferred color scheme. 11 | */ 12 | permanent?: boolean; 13 | /** 14 | * Any string value that represents the label for the "dark" mode. 15 | */ 16 | dark?: string; 17 | /** 18 | * Any string value that represents the label for the "light" mode. 19 | */ 20 | light?: string; 21 | } 22 | 23 | declare global { 24 | interface HTMLElementTagNameMap { 25 | 'dark-mode': DarkMode; 26 | } 27 | interface GlobalEventHandlersEventMap { 28 | /** 29 | * Fired when the color scheme gets changed. 30 | * 31 | * ```js 32 | * const toggle = document.querySelector('dark-mode'); 33 | * document.addEventListener('colorschemechange', (e) => { 34 | * console.log(`Color scheme changed to "${e.detail.colorScheme}".`); 35 | * console.log(toggle.mode === 'dark' ? 'Change Theme 🌞' : 'Change Theme 🌒') 36 | * }); 37 | * ``` 38 | */ 39 | 'colorschemechange': ColorSchemeChangeEvent; 40 | /** 41 | * Fired when the color scheme should be permanently remembered or not. 42 | * 43 | * ```js 44 | * document.addEventListener('permanentcolorscheme', (e) => { 45 | * console.log(`~: Color scheme changed to "${e.detail.colorScheme}" , "${e.detail.permanent}" .`); 46 | * }); 47 | * ``` 48 | */ 49 | 'permanentcolorscheme': PermanentColorSchemeEvent; 50 | } 51 | namespace JSX { 52 | interface IntrinsicElements { 53 | 'dark-mode': Partial | { 54 | style?: Partial | React.CSSProperties; 55 | }; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @package @wcj/dark-mode 3 | * Web Component that toggles dark mode 🌒 4 | * Github: https://github.com/jaywcjlove/dark-mode.git 5 | * Website: https://jaywcjlove.github.io/dark-mode 6 | * 7 | * Licensed under the MIT license. 8 | * @license Copyright © 2022. Licensed under the MIT License 9 | * @author kenny wong 10 | */ 11 | const doc = document; 12 | const LOCAL_NANE = '_dark_mode_theme_' 13 | const PERMANENT = 'permanent'; 14 | const COLOR_SCHEME_CHANGE = 'colorschemechange'; 15 | const PERMANENT_COLOR_SCHEME = 'permanentcolorscheme'; 16 | const LIGHT = 'light'; 17 | const DARK = 'dark'; 18 | 19 | // See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html ↵ 20 | // #reflecting-content-attributes-in-idl-attributes. 21 | const installStringReflection = (obj, attrName, propName = attrName) => { 22 | Object.defineProperty(obj, propName, { 23 | enumerable: true, 24 | get() { 25 | const value = this.getAttribute(attrName); 26 | return value === null ? '' : value; 27 | }, 28 | set(v) { 29 | this.setAttribute(attrName, v); 30 | }, 31 | }); 32 | }; 33 | 34 | const installBoolReflection = (obj, attrName, propName = attrName) => { 35 | Object.defineProperty(obj, propName, { 36 | enumerable: true, 37 | get() { 38 | return this.hasAttribute(attrName); 39 | }, 40 | set(v) { 41 | if (v) { 42 | this.setAttribute(attrName, ''); 43 | } else { 44 | this.removeAttribute(attrName); 45 | } 46 | }, 47 | }); 48 | }; 49 | 50 | class DarkMode extends HTMLElement { 51 | static get observedAttributes() { 52 | return ['mode', LIGHT, DARK, PERMANENT]; 53 | } 54 | LOCAL_NANE = LOCAL_NANE; 55 | constructor() { 56 | super(); 57 | this._initializeDOM(); 58 | } 59 | connectedCallback() { 60 | installStringReflection(this, 'mode'); 61 | installStringReflection(this, DARK); 62 | installStringReflection(this, LIGHT); 63 | installBoolReflection(this, PERMANENT); 64 | 65 | const rememberedValue = localStorage.getItem(LOCAL_NANE); 66 | if (rememberedValue && [LIGHT, DARK].includes(rememberedValue)) { 67 | this.mode = rememberedValue; 68 | this.permanent = true; 69 | } 70 | if (this.permanent && !rememberedValue) { 71 | localStorage.setItem(LOCAL_NANE, this.mode); 72 | } 73 | const hasNativePrefersColorScheme = [LIGHT, DARK].includes(rememberedValue); 74 | 75 | if (this.permanent && rememberedValue) { 76 | this._changeThemeTag(); 77 | } else { 78 | if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { 79 | this.mode = DARK; 80 | this._changeThemeTag(); 81 | } 82 | if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) { 83 | this.mode = LIGHT; 84 | this._changeThemeTag(); 85 | } 86 | } 87 | if (!this.permanent && !hasNativePrefersColorScheme) { 88 | window.matchMedia('(prefers-color-scheme: light)').onchange = (event) => { 89 | this.mode = event.matches ? LIGHT : DARK; 90 | this._changeThemeTag(); 91 | } 92 | window.matchMedia('(prefers-color-scheme: dark)').onchange = (event) => { 93 | this.mode = event.matches ? DARK : LIGHT; 94 | this._changeThemeTag(); 95 | } 96 | } 97 | const observer = new MutationObserver((mutationsList, observer) => { 98 | this.mode = doc.documentElement.dataset.colorMode; 99 | if (this.permanent && hasNativePrefersColorScheme) { 100 | localStorage.setItem(LOCAL_NANE, this.mode); 101 | this._dispatchEvent(PERMANENT_COLOR_SCHEME, { 102 | permanent: this.permanent, 103 | }); 104 | } 105 | this._changeContent(); 106 | this._dispatchEvent(COLOR_SCHEME_CHANGE, { colorScheme: this.mode }); 107 | }); 108 | // Start observing the target node with the above configuration 109 | observer.observe(doc.documentElement, { attributes: true }); 110 | // After that, stop observing 111 | // observer.disconnect(); 112 | this._dispatchEvent(COLOR_SCHEME_CHANGE, { colorScheme: this.mode }); 113 | 114 | this._changeContent(); 115 | } 116 | attributeChangedCallback(name, oldValue, newValue) { 117 | if (name === 'mode' && oldValue !== newValue && [LIGHT, DARK].includes(newValue)) { 118 | const rememberedValue = localStorage.getItem(LOCAL_NANE); 119 | if (this.mode === rememberedValue) { 120 | this.mode = newValue; 121 | this._changeContent(); 122 | this._changeThemeTag(); 123 | } else if (this.mode && this.mode !== rememberedValue) { 124 | this._changeContent(); 125 | this._changeThemeTag(); 126 | } 127 | } else if ((name === LIGHT || name === DARK) && oldValue !== newValue) { 128 | this._changeContent(); 129 | } 130 | if (name === 'permanent' && typeof this.permanent === 'boolean') { 131 | this.permanent ? localStorage.setItem(LOCAL_NANE, this.mode) : localStorage.removeItem(LOCAL_NANE); 132 | } 133 | } 134 | _changeThemeTag() { 135 | doc.documentElement.setAttribute('data-color-mode', this.mode); 136 | } 137 | _changeContent() { 138 | this.icon.textContent = this.mode === LIGHT ? '🌒' : '🌞'; 139 | this.text.textContent = this.mode === LIGHT ? this.getAttribute(DARK) : this.getAttribute(LIGHT); 140 | if (!this.text.textContent && this.text.parentElement && this.text) { 141 | this.text.parentElement.removeChild(this.text) 142 | } 143 | } 144 | _initializeDOM() { 145 | var shadow = this.attachShadow({ mode: 'open' }); 146 | this.label = doc.createElement('span'); 147 | this.label.setAttribute('class', 'wrapper'); 148 | this.label.onclick = () => { 149 | this.mode = this.mode === LIGHT ? DARK : LIGHT; 150 | if (this.permanent) { 151 | localStorage.setItem(LOCAL_NANE, this.mode); 152 | } 153 | this._changeThemeTag(); 154 | this._changeContent(); 155 | } 156 | shadow.appendChild(this.label); 157 | this.icon = doc.createElement('span'); 158 | this.icon.part = 'icon'; 159 | this.label.appendChild(this.icon); 160 | 161 | this.text = doc.createElement('span'); 162 | this.text.part = 'text'; 163 | this.label.appendChild(this.text); 164 | 165 | const textContent = ` 166 | [data-color-mode*='dark'], [data-color-mode*='dark'] body { 167 | color-scheme: dark; 168 | --color-theme-bg: #0d1117; 169 | --color-theme-text: #c9d1d9; 170 | background-color: var(--color-theme-bg); 171 | color: var(--color-theme-text); 172 | } 173 | 174 | [data-color-mode*='light'], [data-color-mode*='light'] body { 175 | color-scheme: light; 176 | --color-theme-bg: #fff; 177 | --color-theme-text: #24292f; 178 | background-color: var(--color-theme-bg); 179 | color: var(--color-theme-text); 180 | }`; 181 | 182 | const STYLE_ID = '_dark_mode_style_'; 183 | const styleDom = doc.getElementById(STYLE_ID); 184 | 185 | if (!styleDom) { 186 | var initstyle = doc.createElement('style'); 187 | initstyle.id = STYLE_ID; 188 | initstyle.textContent = textContent; 189 | doc.head.appendChild(initstyle); 190 | } 191 | 192 | var style = doc.createElement('style'); 193 | style.textContent = ` 194 | .wrapper { cursor: pointer; user-select: none; position: relative; } 195 | .wrapper > span + span { margin-left: .4rem; } 196 | `; 197 | shadow.appendChild(style); 198 | } 199 | _dispatchEvent(type, value) { 200 | this.dispatchEvent(new CustomEvent(type, { 201 | bubbles: true, 202 | composed: true, 203 | detail: value, 204 | })); 205 | } 206 | } 207 | 208 | customElements.define('dark-mode', DarkMode); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wcj/dark-mode", 3 | "version": "1.1.0", 4 | "description": "Web Component that toggles dark mode 🌒", 5 | "homepage": "https://jaywcjlove.github.io/dark-mode", 6 | "funding": "https://jaywcjlove.github.io/#/sponsor", 7 | "author": "jaywcjlove", 8 | "license": "MIT", 9 | "main": "./main.js", 10 | "browser": "./dist/dark-mode.min.js", 11 | "module": "./dist/dark-mode.min.js", 12 | "exports": "./dist/dark-mode.min.js", 13 | "unpkg": "./dist/dark-mode.min.js", 14 | "types": "./main.d.ts", 15 | "scripts": { 16 | "clean": "shx rm -rf ./dist && mkdir dist", 17 | "build": "npm run clean && npx terser ./main.js --toplevel --mangle-props regex=\\\"^_\\\" --comments /@license/ --ecma=8 -o ./dist/dark-mode.min.js" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/jaywcjlove/dark-mode.git" 22 | }, 23 | "files": [ 24 | "main.d.ts", 25 | "main.js", 26 | "dist" 27 | ], 28 | "keywords": [ 29 | "dark", 30 | "mode" 31 | ], 32 | "devDependencies": { 33 | "shx": "^0.3.4", 34 | "terser": "^5.10.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "packageRules": [ 6 | { 7 | "matchPackagePatterns": ["*"], 8 | "rangeStrategy": "replace" 9 | } 10 | ] 11 | } 12 | --------------------------------------------------------------------------------