├── .dockerignore
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmrc
├── .vscode
├── extensions.json
└── settings.json
├── Dockerfile
├── LICENSE
├── README.md
├── cypress.config.ts
├── cypress
├── e2e
│ └── basic.spec.ts
├── screenshots
│ └── index page.png
├── support
│ ├── commands.ts
│ ├── component-index.html
│ └── component.ts
└── tsconfig.json
├── index.html
├── locales
├── en.yml
└── zh-CN.yml
├── netlify.toml
├── package.json
├── pnpm-lock.yaml
├── public
├── _headers
├── background-dark.png
├── background.png
├── favicon-dark.svg
├── favicon.svg
├── img
│ └── wx.png
├── logo.png
├── page_not_found.svg
├── pwa-192x192.png
├── pwa-512x512.png
└── safari-pinned-tab.svg
├── src
├── App.vue
├── assets
│ ├── font
│ │ └── DS-DIGIT.TTF
│ └── js
│ │ ├── cet4.js
│ │ └── waterMark.js
├── auto-imports.d.ts
├── components.d.ts
├── components
│ ├── CloseHandler.vue
│ ├── CollapseTransition.vue
│ ├── Loading.vue
│ ├── Showcase.cy.ts
│ ├── Showcase.vue
│ ├── SourceCode.vue
│ ├── Svg
│ │ └── HiddenSourceSvg.vue
│ ├── TheFooter.vue
│ └── TheSidebar.vue
├── composables
│ ├── dark.ts
│ ├── display.ts
│ └── hiddenSidebar.ts
├── layouts
│ ├── 404.vue
│ ├── default.vue
│ ├── demo.vue
│ └── home.vue
├── main.ts
├── modules
│ ├── i18n.ts
│ ├── nprogress.ts
│ ├── pinia.ts
│ └── pwa.ts
├── pages
│ ├── [...all].vue
│ ├── about.md
│ ├── example
│ │ ├── aircraft.vue
│ │ ├── annular-progress.vue
│ │ ├── bottom-navigation.vue
│ │ ├── button.vue
│ │ ├── carousel.vue
│ │ ├── claymorphism.vue
│ │ ├── click.vue
│ │ ├── clip-path.vue
│ │ ├── congratulations.vue
│ │ ├── digital-clock.vue
│ │ ├── glassmorphism.vue
│ │ ├── gradient-background.vue
│ │ ├── gradient-border.vue
│ │ ├── gradient-shadow.vue
│ │ ├── loading-pac-man.vue
│ │ ├── mac-terminal.vue
│ │ ├── multilayer-border.vue
│ │ ├── neumorphism.vue
│ │ ├── profile.vue
│ │ ├── siderbar-navigation.vue
│ │ ├── srcoll.vue
│ │ ├── tabs.vue
│ │ ├── tag-surround.vue
│ │ ├── text-overflow.vue
│ │ ├── text.vue
│ │ ├── typewriter.vue
│ │ ├── watermark.vue
│ │ └── weather.vue
│ └── index.vue
├── shims.d.ts
├── styles
│ ├── main.css
│ ├── markdown.css
│ └── prism.css
├── types.ts
└── utils
│ └── highlight.ts
├── test
├── __snapshots__
│ └── component.test.ts.snap
├── basic.test.ts
└── component.test.ts
├── tsconfig.json
├── unocss.config.ts
└── vite.config.ts
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@antfu",
3 | "rules": {
4 | "@typescript-eslint/no-namespace": "off"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .vite-ssg-dist
3 | .vite-ssg-temp
4 | *.local
5 | dist
6 | dist-ssr
7 | node_modules
8 | .idea/
9 | *.log
10 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
2 | strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "antfu.iconify",
4 | "antfu.unocss",
5 | "antfu.vite",
6 | "antfu.goto-alias",
7 | "csstools.postcss",
8 | "dbaeumer.vscode-eslint",
9 | "vue.volar",
10 | "lokalise.i18n-ally"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "i18n-ally.sourceLanguage": "zh-CN",
3 | "i18n-ally.keystyle": "nested",
4 | "i18n-ally.localesPaths": "locales",
5 | "i18n-ally.sortKeys": true,
6 | "prettier.enable": false,
7 | "editor.codeActionsOnSave": {
8 | "source.fixAll.eslint": true
9 | },
10 | "files.associations": {
11 | "*.css": "postcss"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine as build-stage
2 |
3 | WORKDIR /app
4 | RUN corepack enable
5 |
6 | COPY .npmrc package.json pnpm-lock.yaml ./
7 | RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
8 | pnpm install --frozen-lockfile
9 |
10 | COPY . .
11 | RUN pnpm build
12 |
13 | FROM nginx:stable-alpine as production-stage
14 |
15 | COPY --from=build-stage /app/dist /usr/share/nginx/html
16 | EXPOSE 80
17 |
18 | CMD ["nginx", "-g", "daemon off;"]
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Kuizuo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 前端示例代码库
2 |
3 | 在线演示: [https://example.kuizuo.cn](https://example.kuizuo.cn/)
4 |
5 |
6 |
7 |
8 |
9 | 整理前端样式和功能的实现代码,可以用来寻找灵感,或直接使用示例中的代码。
10 |
11 | 所有演示代码均存放在 [src/pages/example](https://github.com/kuizuo/example/tree/main/src/pages/example) 下,均使用 [vue3 setup](https://cn.vuejs.org/api/sfc-script-setup.html#script-setup) 语法进行编写。
12 |
13 | ### 特点
14 |
15 | - 基于 [vitesse](https://github.com/antfu/vitesse) 模板,使用Vue3 + Vite + UnoCSS
16 |
17 | - 在 [src/pages/example](https://github.com/kuizuo/example/tree/main/src/pages/example) 下的组件通过 [SFC](https://cn.vuejs.org/api/sfc-spec.html#sfc-syntax-specification) 使用 [\ 标签块](https://github.com/hannoeru/vite-plugin-pages#sfc-custom-block-for-route-data) 定义组件信息,无需额外定义数据。
18 |
19 | - 两种演示组件方式,方便预览的同时,还可以查看或复制组件相关代码。
20 |
--------------------------------------------------------------------------------
/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress'
2 |
3 | export default defineConfig({
4 | e2e: {
5 | baseUrl: 'http://localhost:3333',
6 | chromeWebSecurity: false,
7 | specPattern: 'cypress/e2e/**/*.{spec,cy}.*',
8 | supportFile: false,
9 | },
10 | component: {
11 | devServer: {
12 | framework: 'vue',
13 | bundler: 'vite',
14 | },
15 | },
16 | })
17 |
--------------------------------------------------------------------------------
/cypress/e2e/basic.spec.ts:
--------------------------------------------------------------------------------
1 | context('Basic', () => {
2 | beforeEach(() => {
3 | cy.visit('/')
4 | })
5 |
6 | it('basic nav', () => {
7 | cy.url()
8 | .should('eq', 'http://localhost:3333/')
9 |
10 | cy.contains('前端示例代码库')
11 | .should('exist')
12 |
13 | cy.screenshot('index page')
14 | })
15 |
16 | it('switch display', () => {
17 | cy.get('[data-example="clip-path 裁剪图形"]')
18 | .click()
19 | .url()
20 | .should('eq', 'http://localhost:3333/example/clip-path')
21 |
22 | cy.get('.example-showcase')
23 | .should('exist')
24 |
25 | cy.get('[title="切换显示"]')
26 | .click()
27 | .get('.example-showcase')
28 | .should('not.exist')
29 |
30 | cy.get('.close-handler')
31 | .click()
32 | .get('aside')
33 | .should('have.class', '!w-0')
34 | })
35 |
36 | it('show source code', () => {
37 | cy.get('[data-example="clip-path 裁剪图形"]')
38 | .click()
39 | .url()
40 | .should('eq', 'http://localhost:3333/example/clip-path')
41 |
42 | cy.get('[i-carbon-code=""]')
43 | .click()
44 | .get('.prism-editor-wrapper')
45 | .should('not.be.hidden')
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/cypress/screenshots/index page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/cypress/screenshots/index page.png
--------------------------------------------------------------------------------
/cypress/support/commands.ts:
--------------------------------------------------------------------------------
1 | ///
2 | // ***********************************************
3 | // This example commands.ts shows you how to
4 | // create various custom commands and overwrite
5 | // existing commands.
6 | //
7 | // For more comprehensive examples of custom
8 | // commands please read more here:
9 | // https://on.cypress.io/custom-commands
10 | // ***********************************************
11 | //
12 | //
13 | // -- This is a parent command --
14 | // Cypress.Commands.add('login', (email, password) => { ... })
15 | //
16 | //
17 | // -- This is a child command --
18 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
19 | //
20 | //
21 | // -- This is a dual command --
22 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
23 | //
24 | //
25 | // -- This will overwrite an existing command --
26 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
27 | //
28 | // declare global {
29 | // namespace Cypress {
30 | // interface Chainable {
31 | // login(email: string, password: string): Chainable
32 | // drag(subject: string, options?: Partial): Chainable
33 | // dismiss(subject: string, options?: Partial): Chainable
34 | // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable
35 | // }
36 | // }
37 | // }
38 |
--------------------------------------------------------------------------------
/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/cypress/support/component.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/component.ts is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
22 | import { mount } from 'cypress/vue'
23 |
24 | // Augment the Cypress namespace to include type definitions for
25 | // your custom command.
26 | // Alternatively, can be defined in cypress/support/component.d.ts
27 | // with a at the top of your spec.
28 | declare global {
29 | namespace Cypress {
30 | interface Chainable {
31 | mount: typeof mount
32 | }
33 | }
34 | }
35 |
36 | Cypress.Commands.add('mount', mount)
37 |
38 | // Example use:
39 | // cy.mount(MyComponent)
40 |
--------------------------------------------------------------------------------
/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "types": [
5 | "cypress"
6 | ]
7 | },
8 | "exclude": [],
9 | "include": [
10 | "**/*.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/locales/en.yml:
--------------------------------------------------------------------------------
1 | profile:
2 | hi: Hi! I'm
3 | kuizuo: kuizuo
4 | look: Let’s Look It
5 |
--------------------------------------------------------------------------------
/locales/zh-CN.yml:
--------------------------------------------------------------------------------
1 | profile:
2 | hi: 你好!我是
3 | kuizuo: 愧怍
4 | look: 瞧瞧看
5 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build.environment]
2 | # bypass npm auto install
3 | NPM_FLAGS = "--version"
4 | NODE_VERSION = "16"
5 |
6 | [build]
7 | publish = "dist"
8 | command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run build"
9 |
10 | [[redirects]]
11 | from = "/*"
12 | to = "/index.html"
13 | status = 200
14 |
15 | [[headers]]
16 | for = "/manifest.webmanifest"
17 | [headers.values]
18 | Content-Type = "application/manifest+json"
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web-example",
3 | "type": "module",
4 | "version": "0.1.0",
5 | "private": true,
6 | "packageManager": "pnpm@8.7.6",
7 | "description": "前端示例代码库",
8 | "author": {
9 | "url": "https://kuizuo.cn",
10 | "email": "hi@kuizuo.cn",
11 | "name": "Kuizuo"
12 | },
13 | "license": "MIT",
14 | "repository": {
15 | "url": "https://github.com/kuizuo/example",
16 | "type": "git"
17 | },
18 | "engines": {
19 | "node": ">=18"
20 | },
21 | "scripts": {
22 | "build": "vite-ssg build",
23 | "dev": "vite --port 3333 --open",
24 | "lint": "eslint .",
25 | "preview": "vite preview",
26 | "preview-https": "serve dist",
27 | "test": "vitest",
28 | "test:e2e": "cypress open",
29 | "test:unit": "vitest",
30 | "typecheck": "vue-tsc --noEmit",
31 | "up": "taze major -I"
32 | },
33 | "dependencies": {
34 | "@vueuse/core": "^10.4.1",
35 | "@vueuse/head": "^2.0.0",
36 | "js-confetti": "^0.11.0",
37 | "nprogress": "^0.2.0",
38 | "pinia": "^2.1.6",
39 | "prism-theme-vars": "^0.2.4",
40 | "prismjs": "^1.29.0",
41 | "sass": "^1.67.0",
42 | "vue": "^3.3.4",
43 | "vue-demi": "^0.14.6",
44 | "vue-i18n": "^9.4.1",
45 | "vue-prism-editor": "^2.0.0-alpha.2",
46 | "vue-router": "^4.2.4"
47 | },
48 | "devDependencies": {
49 | "@antfu/eslint-config": "^0.42.0",
50 | "@iconify-json/carbon": "^1.1.21",
51 | "@iconify-json/mdi": "^1.1.54",
52 | "@iconify-json/ri": "^1.1.12",
53 | "@intlify/unplugin-vue-i18n": "^1.2.0",
54 | "@kuizuo/eslint-config": "^1.0.1",
55 | "@types/markdown-it-link-attributes": "^3.0.1",
56 | "@types/nprogress": "^0.2.0",
57 | "@types/prismjs": "^1.26.0",
58 | "@vitejs/plugin-vue": "^4.3.4",
59 | "@vue-macros/volar": "^0.14.3",
60 | "@vue/test-utils": "^2.4.1",
61 | "critters": "^0.0.20",
62 | "cross-env": "^7.0.3",
63 | "cypress": "13.2.0",
64 | "eslint": "^8.49.0",
65 | "eslint-plugin-cypress": "^2.14.0",
66 | "https-localhost": "^4.7.1",
67 | "markdown-it-link-attributes": "^4.0.1",
68 | "markdown-it-shiki": "^0.9.0",
69 | "pnpm": "^8.7.6",
70 | "shiki": "^0.14.4",
71 | "taze": "^0.11.2",
72 | "typescript": "^5.2.2",
73 | "unocss": "^0.55.7",
74 | "unplugin-auto-import": "^0.16.6",
75 | "unplugin-vue-components": "^0.25.2",
76 | "unplugin-vue-macros": "^2.5.1",
77 | "vite": "^4.4.9",
78 | "vite-plugin-inspect": "^0.7.38",
79 | "vite-plugin-pages": "^0.31.0",
80 | "vite-plugin-pwa": "^0.16.5",
81 | "vite-plugin-vue-devtools": "1.0.0-rc.4",
82 | "vite-plugin-vue-layouts": "^0.8.0",
83 | "vite-plugin-vue-markdown": "^0.23.8",
84 | "vite-ssg": "^0.23.2",
85 | "vite-ssg-sitemap": "^0.5.1",
86 | "vitest": "^0.34.4",
87 | "vue-tsc": "^1.8.11"
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/public/_headers:
--------------------------------------------------------------------------------
1 | /assets/*
2 | cache-control: max-age=31536000
3 | cache-control: immutable
4 |
--------------------------------------------------------------------------------
/public/background-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/background-dark.png
--------------------------------------------------------------------------------
/public/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/background.png
--------------------------------------------------------------------------------
/public/favicon-dark.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/img/wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/img/wx.png
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/logo.png
--------------------------------------------------------------------------------
/public/page_not_found.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/pwa-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/pwa-192x192.png
--------------------------------------------------------------------------------
/public/pwa-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/public/pwa-512x512.png
--------------------------------------------------------------------------------
/public/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
42 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/assets/font/DS-DIGIT.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kuizuo/example/0314a18757b100db466c48b5b13857fc4e29efda/src/assets/font/DS-DIGIT.TTF
--------------------------------------------------------------------------------
/src/assets/js/cet4.js:
--------------------------------------------------------------------------------
1 | const words = [
2 | 'mood',
3 | 'static',
4 | 'senator',
5 | 'hobby',
6 | 'lad',
7 | 'equip',
8 | 'frown',
9 | 'fasten',
10 | 'software',
11 | 'stir',
12 | 'distribution',
13 | 'flexible',
14 | 'solution',
15 | 'panel',
16 | 'ministry',
17 | 'supreme',
18 | 'describe',
19 | 'limb',
20 | 'circumstance',
21 | 'core',
22 | 'assistant',
23 | 'mess',
24 | 'minus',
25 | 'statistic',
26 | 'pregnant',
27 | 'sector',
28 | 'detection',
29 | 'statue',
30 | 'bride',
31 | 'cycle',
32 | 'saucer',
33 | 'skillful',
34 | 'civilization',
35 | 'overhead',
36 | 'clash',
37 | 'grant',
38 | 'bond',
39 | 'staff',
40 | 'intermediate',
41 | 'guitar',
42 | 'comprehensive',
43 | 'presence',
44 | 'appliance',
45 | 'cushion',
46 | 'emergency',
47 | 'solve',
48 | 'label',
49 | 'slim',
50 | 'status',
51 | 'steady',
52 | 'include',
53 | 'resistance',
54 | 'prime',
55 | 'ambassador',
56 | 'derive',
57 | 'sponsor',
58 | 'proportion',
59 | 'mental',
60 | 'punch',
61 | 'result',
62 | 'client',
63 | 'steamer',
64 | 'option',
65 | 'dormitory',
66 | 'attitude',
67 | 'steep',
68 | 'agency',
69 | 'steer',
70 | 'scandal',
71 | 'definite',
72 | 'cautious',
73 | 'prayer',
74 | 'nest',
75 | 'domestic',
76 | 'chest',
77 | 'airline',
78 | 'rebel',
79 | 'satisfactory',
80 | 'stem',
81 | 'render',
82 | 'object',
83 | 'gardener',
84 | 'shrink',
85 | 'parade',
86 | 'rumour',
87 | 'rug',
88 | 'establish',
89 | 'primarily',
90 | 'kindness',
91 | 'breast',
92 | 'sticky',
93 | 'boost',
94 | 'fund',
95 | 'incredible',
96 | 'abroad',
97 | 'detective',
98 | 'stiff',
99 | 'stimulate',
100 | 'fame',
101 | 'consume',
102 | 'accelerate',
103 | 'lightning',
104 | 'sting',
105 | 'bound',
106 | 'rouse',
107 | 'cultivate',
108 | 'material',
109 | 'personnel',
110 | 'display',
111 | 'particle',
112 | 'frog',
113 | 'impression',
114 | 'biology',
115 | 'drunk',
116 | 'barrier',
117 | 'stock',
118 | 'fisherman',
119 | 'politician',
120 | 'royal',
121 | 'barber',
122 | 'stocking',
123 | 'delegate',
124 | 'highlight',
125 | 'depression',
126 | 'signature',
127 | 'atmosphere',
128 | 'evaluate',
129 | 'rescue',
130 | 'personality',
131 | 'latter',
132 | 'parliament',
133 | 'input',
134 | 'partial',
135 | 'loyalty',
136 | 'calendar',
137 | 'overlook',
138 | 'debate',
139 | 'stoop',
140 | 'cube',
141 | 'submerge',
142 | 'credit',
143 | 'surrounding',
144 | 'stove',
145 | 'submit',
146 | 'carrier',
147 | 'imply',
148 | 'strain',
149 | 'consist',
150 | 'strap',
151 | 'efficient',
152 | 'accommodation、',
153 | 'strategic',
154 | 'layer',
155 | 'exclaim',
156 | 'representative',
157 | 'forecast',
158 | 'discipline',
159 | 'neutral',
160 | 'interpret',
161 | 'knot',
162 | 'desirable',
163 | 'promote',
164 | 'acceptance',
165 | 'mayor',
166 | 'equation',
167 | 'routine',
168 | 'ripe',
169 | 'prove',
170 | 'likewise',
171 | 'chap',
172 | 'explore',
173 | 'overnight',
174 | 'strategy',
175 | 'straw',
176 | 'bind',
177 | 'stream',
178 | 'bearing',
179 | 'suppose',
180 | 'access',
181 | 'remain',
182 | 'abstract',
183 | 'stretch',
184 | 'approximate',
185 | 'striking',
186 | 'abuse',
187 | 'critic',
188 | 'interpretation',
189 | 'string',
190 | 'illustrate',
191 | 'helpful',
192 | 'leak',
193 | 'accountant',
194 | 'crude',
195 | 'product',
196 | 'strip',
197 | 'stripe',
198 | 'communicate',
199 | 'following',
200 | 'hedge',
201 | 'consumer',
202 | 'emotional',
203 | 'craft',
204 | 'institute',
205 | 'indispensable',
206 | 'scheme',
207 | 'scale',
208 | 'replace',
209 | 'bark',
210 | 'gramme',
211 | 'congress',
212 | 'bump',
213 | 'stroke',
214 | 'ingredient',
215 | 'arbitrary',
216 | 'pinch',
217 | 'exploit',
218 | 'action',
219 | 'ash',
220 | 'rope',
221 | 'bulk',
222 | 'strengthen',
223 | 'independent',
224 | 'board',
225 | 'recall',
226 | 'studio',
227 | 'grave',
228 | 'eve',
229 | 'formal',
230 | 'absorb',
231 | 'sensitive',
232 | 'ability',
233 | 'fairy',
234 | 'talent',
235 | 'comparison',
236 | 'stuff',
237 | 'brow',
238 | 'infer',
239 | 'invasion',
240 | 'grand',
241 | 'stress',
242 | 'journalist',
243 | 'supply',
244 | 'penetrate',
245 | 'subject',
246 | 'pole',
247 | 'raw',
248 | 'embassy',
249 | 'carpenter',
250 | 'appropriate',
251 | 'socialist',
252 | 'protein',
253 | 'enlarge',
254 | 'inherit',
255 | 'chemist',
256 | 'conflict',
257 | 'drain',
258 | 'architecture',
259 | 'charity',
260 | 'entitle',
261 | 'subsequent',
262 | 'span',
263 | 'pea',
264 | 'instruct',
265 | 'spite',
266 | 'slender',
267 | 'automobile',
268 | 'behavior',
269 | 'envy',
270 | 'substance',
271 | 'contest',
272 | 'spit',
273 | 'mutual',
274 | 'dorm',
275 | 'substantial',
276 | 'meanwhile',
277 | 'desire',
278 | 'conviction',
279 | 'interaction',
280 | 'menu',
281 | 'frustrate',
282 | 'belief',
283 | 'confusion',
284 | 'civilize',
285 | 'preface',
286 | 'chemical',
287 | 'horizontal',
288 | 'invitation',
289 | 'auto',
290 | 'electric',
291 | 'purse',
292 | 'blank',
293 | 'courtyard',
294 | 'rural',
295 | 'discourage',
296 | 'reflection',
297 | 'rainbow',
298 | 'slide',
299 | 'removal',
300 | 'missing',
301 | 'graph',
302 | 'fortnight14',
303 | 'disgust',
304 | 'offense',
305 | 'allow',
306 | 'proportional',
307 | 'devote',
308 | 'empire',
309 | 'microphone',
310 | 'subtract',
311 | 'pace',
312 | 'gesture',
313 | 'loop',
314 | 'sheer',
315 | 'cupboard',
316 | 'sore',
317 | 'raid',
318 | 'lower',
319 | 'comment',
320 | 'distress',
321 | 'publicity',
322 | 'spin',
323 | 'museum',
324 | 'outstanding',
325 | 'rack',
326 | 'rent',
327 | 'housing',
328 | 'complain',
329 | 'evidently',
330 | 'lung',
331 | 'deny',
332 | 'ownership',
333 | 'rid',
334 | 'harness',
335 | 'acknowledge',
336 | 'passion',
337 | 'genuine',
338 | 'imaginary',
339 | 'prompt',
340 | 'invention',
341 | 'lucky',
342 | 'confidence',
343 | 'suburb',
344 | 'industrialize',
345 | 'fearful',
346 | 'intelligence',
347 | 'childhood',
348 | 'crush',
349 | 'intention',
350 | 'finding',
351 | 'subway',
352 | 'magnet',
353 | 'defect',
354 | 'attribute',
355 | 'release',
356 | 'succession',
357 | 'chip',
358 | 'similar',
359 | 'maintain',
360 | 'advertisement',
361 | 'privilege',
362 | 'dull',
363 | 'provoke',
364 | 'function',
365 | 'substitute',
366 | 'extreme',
367 | 'orbit',
368 | 'correspondent',
369 | 'fashionable',
370 | 'allowance',
371 | 'component',
372 | 'interrupt',
373 | 'successive',
374 | 'external',
375 | 'somehow',
376 | 'declaration',
377 | 'distribute',
378 | 'specialist',
379 | 'rotate',
380 | 'rod',
381 | 'suck',
382 | 'negative',
383 | 'suffer',
384 | 'sufficient',
385 | 'court',
386 | 'curl',
387 | 'bureau',
388 | 'moist',
389 | 'relative',
390 | 'suggestion',
391 | 'restless',
392 | 'delivery',
393 | 'claim',
394 | 'suicide',
395 | 'dip',
396 | 'profit',
397 | 'lease',
398 | 'disposal',
399 | 'appeal',
400 | 'cart',
401 | 'stable',
402 | 'married',
403 | 'reckon',
404 | 'practically',
405 | 'reception',
406 | 'jury',
407 | 'glory',
408 | 'mist',
409 | 'congratulate',
410 | 'sum',
411 | 'execute',
412 | 'essay',
413 | 'route',
414 | 'merit',
415 | 'local',
416 | 'compromise',
417 | 'rally',
418 | 'feather',
419 | 'characterize',
420 | 'explode',
421 | 'aware',
422 | 'grain',
423 | 'kettle',
424 | 'summarize',
425 | 'faulty',
426 | 'highly',
427 | 'summary',
428 | 'conservation',
429 | 'summit',
430 | 'reward',
431 | 'available',
432 | 'specialize',
433 | 'structure',
434 | 'resident',
435 | 'boundary',
436 | 'radical',
437 | 'leading',
438 | 'rag',
439 | 'prescribe',
440 | 'demonstrate',
441 | 'manner',
442 | 'sunrise',
443 | 'construct',
444 | 'railway',
445 | 'opportunity',
446 | 'lag',
447 | 'fade',
448 | 'sunset',
449 | 'singular',
450 | 'broom',
451 | 'beneath',
452 | 'recreation',
453 | 'procession',
454 | 'tackle',
455 | 'combination',
456 | 'hell',
457 | 'proof',
458 | 'resort',
459 | 'recruit',
460 | 'contrast',
461 | 'sunshine',
462 | 'introduction',
463 | 'ancestor',
464 | 'split',
465 | 'painful',
466 | 'superb',
467 | 'interest',
468 | 'noticeable',
469 | 'graduate',
470 | 'glance',
471 | 'bloody',
472 | 'fierce',
473 | 'paragraph',
474 | 'enquire',
475 | 'preparation',
476 | 'justice',
477 | 'drip',
478 | 'emit',
479 | 'superficial',
480 | 'recommendation',
481 | 'sole',
482 | 'folk',
483 | 'rank',
484 | 'motor',
485 | 'airport',
486 | 'enclose',
487 | 'bounce',
488 | 'occasion',
489 | 'determine',
490 | 'advisable',
491 | 'permission',
492 | 'statement',
493 | 'award',
494 | 'bold',
495 | 'so-called',
496 | 'superior',
497 | 'sunlight',
498 | 'alternative',
499 | 'kingdom',
500 | 'mobile',
501 | 'damn',
502 | 'storage',
503 | 'supplement',
504 | 'locate',
505 | 'cabin',
506 | 'majority',
507 | 'receiver',
508 | 'support',
509 | 'Bible',
510 | 'assign',
511 | 'episode',
512 | 'fatal',
513 | 'pad',
514 | 'excursion',
515 | 'ignorant',
516 | 'county',
517 | 'condense',
518 | 'heal',
519 | 'asset',
520 | 'involve',
521 | 'rear',
522 | 'hollow',
523 | 'charter',
524 | 'leadership',
525 | 'shallow',
526 | 'procedure',
527 | 'impressive',
528 | 'controversial',
529 | 'curve',
530 | 'spiritual',
531 | 'astonish',
532 | 'fold',
533 | 'alert',
534 | 'condition',
535 | 'segment',
536 | 'cabbage',
537 | 'condemn',
538 | 'mild',
539 | 'surgery',
540 | 'leisure',
541 | 'accomplish',
542 | 'plug',
543 | 'presentation',
544 | 'surplus',
545 | 'cassette',
546 | 'surround',
547 | 'private',
548 | 'bulb',
549 | 'meaning',
550 | 'annual',
551 | 'expansion',
552 | 'eliminate',
553 | 'horn',
554 | 'responsibility',
555 | 'dam',
556 | 'challenge',
557 | 'alike',
558 | 'phenomenon',
559 | 'survey',
560 | 'curtain',
561 | 'household',
562 | 'survival',
563 | 'medal',
564 | 'invest',
565 | 'survive',
566 | 'awkward',
567 | 'synthetic',
568 | 'manufacture',
569 | 'curse',
570 | 'suspect',
571 | 'suspend',
572 | 'tide',
573 | 'crossing',
574 | 'tour',
575 | 'barely',
576 | 'cope',
577 | 'gap',
578 | 'oppose',
579 | 'deadline',
580 | 'automatic',
581 | 'joint',
582 | 'surrender',
583 | 'rude',
584 | 'faint',
585 | 'conference',
586 | 'issue',
587 | 'swallow',
588 | 'interior',
589 | 'calculator',
590 | 'analyse',
591 | 'hazard',
592 | 'miracle',
593 | 'sway',
594 | 'editorial',
595 | 'recognition',
596 | 'librarian',
597 | 'analysis',
598 | 'kid',
599 | 'partner',
600 | 'swear',
601 | 'center',
602 | 'tidy',
603 | 'passport',
604 | 'swell',
605 | 'link',
606 | 'brave',
607 | 'swift',
608 | 'prohibit',
609 | 'approve',
610 | 'swing',
611 | 'ideal',
612 | 'arrest',
613 | 'landscape',
614 | 'represent',
615 | 'audience',
616 | 'switch',
617 | 'sword',
618 | 'spot',
619 | 'symbol',
620 | 'sanction',
621 | 'bucket',
622 | 'poetry',
623 | 'fibre',
624 | 'pension',
625 | 'beggar',
626 | 'illustration',
627 | 'liable',
628 | 'bunch',
629 | 'management',
630 | 'sympathize',
631 | 'session',
632 | 'delicious',
633 | 'breeze',
634 | 'imitate',
635 | 'infant',
636 | 'sympathy',
637 | 'advantage',
638 | 'considerable',
639 | 'spur',
640 | 'religious',
641 | 'banner',
642 | 'nylon',
643 | 'exceedingly',
644 | 'symptom',
645 | 'pillar',
646 | 'outcome',
647 | 'journey',
648 | 'forehead',
649 | 'conscience',
650 | 'precise',
651 | 'cable',
652 | 'screw',
653 | 'gang',
654 | 'favour',
655 | 'constitute',
656 | 'squeeze',
657 | 'system',
658 | 'culture',
659 | 'missile',
660 | 'cast',
661 | 'Marxist',
662 | 'prior',
663 | 'dye',
664 | 'graceful',
665 | 'onion',
666 | 'seal',
667 | 'saint',
668 | 'hesitate',
669 | 'crawl',
670 | 'contribute',
671 | 'fascinating',
672 | 'entertainment',
673 | 'cigarette',
674 | 'immense',
675 | 'outer',
676 | 'revolutionary',
677 | 'fabric',
678 | 'ridge',
679 | 'mass',
680 | 'competent',
681 | 'conclusion',
682 | 'bang',
683 | 'curious',
684 | 'pulse',
685 | 'encounter',
686 | 'concern',
687 | 'preposition',
688 | 'pond',
689 | 'provision',
690 | 'reinforce',
691 | 'systematic(al)',
692 | 'rail',
693 | 'pat',
694 | 'rational',
695 | 'flee',
696 | 'response',
697 | 'executive',
698 | 'tag',
699 | 'means',
700 | 'nephew',
701 | 'motivate',
702 | 'failure',
703 | 'consistent',
704 | 'nowhere',
705 | 'sympathetic',
706 | 'sketch',
707 | 'calm',
708 | 'tame',
709 | 'cancel',
710 | 'pray',
711 | 'target',
712 | 'camel',
713 | 'technician',
714 | 'setting',
715 | 'technique',
716 | 'tax',
717 | 'emerge',
718 | 'capable',
719 | 'technology',
720 | 'selfish',
721 | 'definition',
722 | 'per',
723 | 'participate',
724 | 'tedious',
725 | 'anxious',
726 | 'famine',
727 | 'fundamental',
728 | 'plural',
729 | 'anticipate',
730 | 'teenager',
731 | 'compress',
732 | 'pepper',
733 | 'discharge',
734 | 'telescope',
735 | 'temper',
736 | 'extensive',
737 | 'amuse',
738 | 'current',
739 | 'mask',
740 | 'musician',
741 | 'temple',
742 | 'decay',
743 | 'criticism',
744 | 'feedback',
745 | 'accordance',
746 | 'perceive',
747 | 'scarcely',
748 | 'clay',
749 | 'intelligent',
750 | 'conductor',
751 | 'frequency',
752 | 'attractive',
753 | 'garlic',
754 | 'temporary',
755 | 'recognize',
756 | 'puzzle',
757 | 'elevator',
758 | 'acquisition',
759 | 'absolute',
760 | 'frank',
761 | 'hip',
762 | 'polish',
763 | 'democratic',
764 | 'temptation',
765 | 'disguise',
766 | 'glue',
767 | 'solemn',
768 | 'tend',
769 | 'ancient',
770 | 'effective',
771 | 'channel',
772 | 'primitive',
773 | 'consent',
774 | 'organize',
775 | 'drama',
776 | 'miserable',
777 | 'fur',
778 | 'antique',
779 | 'replacement',
780 | 'inner',
781 | 'clerk',
782 | 'liquor',
783 | 'presently',
784 | 'gene',
785 | 'security',
786 | 'nerve',
787 | 'greedy',
788 | 'essential',
789 | 'decorate',
790 | 'excess',
791 | 'compare',
792 | 'command',
793 | 'fuel',
794 | 'plastic',
795 | 'characteristic',
796 | 'pressure',
797 | 'nearby',
798 | 'environment',
799 | 'crime',
800 | 'pigeon',
801 | 'cement',
802 | 'magnificent',
803 | 'tendency',
804 | 'investigate',
805 | 'infinite',
806 | 'painter',
807 | 'tender',
808 | 'legal',
809 | 'moderate',
810 | 'atomic',
811 | 'anchor',
812 | 'mystery',
813 | 'associate',
814 | 'reaction',
815 | 'affect',
816 | 'tense',
817 | 'flour',
818 | 'comedy',
819 | 'directly',
820 | 'collision',
821 | 'absent',
822 | 'critical',
823 | 'paw',
824 | 'crew',
825 | 'congratulation',
826 | 'interference',
827 | 'flesh',
828 | 'innocent',
829 | 'excitement',
830 | 'adult',
831 | 'enhance',
832 | 'arrival',
833 | 'brief',
834 | 'ambition',
835 | 'outline',
836 | 'aeroplane',
837 | 'fertilizer',
838 | 'tension',
839 | 'petrol',
840 | 'distinguish',
841 | 'shortcoming',
842 | 'propose',
843 | 'former',
844 | 'consumption',
845 | 'terminal',
846 | 'casual',
847 | 'tough',
848 | 'pursue',
849 | 'unexpected',
850 | 'governor',
851 | 'oral',
852 | 'territory',
853 | 'mere',
854 | 'gross',
855 | 'tone',
856 | 'indication',
857 | 'concerning',
858 | 'embrace',
859 | 'numerous',
860 | 'launch',
861 | 'discount',
862 | 'maintenance',
863 | 'incline',
864 | 'liberal',
865 | 'lavatory',
866 | 'marry',
867 | 'constitution',
868 | 'tolerate',
869 | 'intellectual',
870 | 'amateur',
871 | 'mushroom',
872 | 'millimetre',
873 | 'mate',
874 | 'elbow',
875 | 'textile',
876 | 'frame',
877 | 'blend',
878 | 'misunderstand',
879 | 'lap',
880 | 'notion',
881 | 'hatred',
882 | 'slippery',
883 | 'durable',
884 | 'inference',
885 | 'employee',
886 | 'sausage',
887 | 'theme',
888 | 'colleague',
889 | 'dramatic',
890 | 'patience',
891 | 'spacecraft',
892 | 'preserve',
893 | 'import',
894 | 'bankrupt',
895 | 'cartoon',
896 | 'alliance',
897 | 'romantic',
898 | 'barrel',
899 | 'theoretical',
900 | 'stack',
901 | 'settle',
902 | 'hopeful',
903 | 'criminal',
904 | 'insert',
905 | 'specifically',
906 | 'accuse',
907 | 'reveal',
908 | 'pack',
909 | 'guilty',
910 | 'payment',
911 | 'offensive',
912 | 'elect',
913 | 'downward',
914 | 'liquid',
915 | 'clue',
916 | 'jazz',
917 | 'conjunction',
918 | 'lord',
919 | 'therapy',
920 | 'cease',
921 | 'variable',
922 | 'identity',
923 | 'obligation',
924 | 'relativity',
925 | 'consult',
926 | 'anyway',
927 | 'indirect',
928 | 'agent',
929 | 'scan',
930 | 'lemon',
931 | 'opponent',
932 | 'climate',
933 | 'addition',
934 | 'architect',
935 | 'integrate',
936 | 'exterior',
937 | 'thereby',
938 | 'therefore',
939 | 'handful',
940 | 'loyal',
941 | 'furthermore',
942 | 'insurance',
943 | 'category',
944 | 'refine',
945 | 'thick',
946 | 'minority',
947 | 'sorrow',
948 | 'thinking',
949 | 'quiz',
950 | 'airplane',
951 | 'thirsty',
952 | 'objection',
953 | 'platform',
954 | 'merchant',
955 | 'fertile',
956 | 'particularly',
957 | 'division',
958 | 'crisis',
959 | 'thorough',
960 | 'forth',
961 | 'observer',
962 | 'retreat',
963 | 'relevant',
964 | 'precision',
965 | 'admit',
966 | 'jungle',
967 | 'thoughtful',
968 | 'apartment',
969 | 'afterward',
970 | 'entire',
971 | 'carbon',
972 | 'chamber',
973 | 'realm',
974 | 'ratio',
975 | 'capture',
976 | 'baseball',
977 | 'boring',
978 | 'crowd',
979 | 'sample',
980 | 'estate',
981 | 'threat',
982 | 'reliable',
983 | 'constant',
984 | 'sustain',
985 | 'horsepower',
986 | 'suspicion',
987 | 'prospect',
988 | 'conduct',
989 | 'lawn',
990 | 'transmit',
991 | 'pollution',
992 | 'slip',
993 | 'influential',
994 | 'handle',
995 | 'threaten',
996 | 'aircraft',
997 | 'thrive',
998 | 'harm',
999 | 'similarly',
1000 | 'prominent',
1001 | 'signal',
1002 | 'encourage',
1003 | 'recession',
1004 | 'commitment',
1005 | 'monitor',
1006 | 'spark',
1007 | 'mug',
1008 | 'absence',
1009 | 'appreciate',
1010 | 'bean',
1011 | 'elastic',
1012 | 'presumably',
1013 | 'bargain',
1014 | 'significant',
1015 | 'throat',
1016 | 'extend',
1017 | 'comparable',
1018 | 'container',
1019 | 'chief',
1020 | 'instant',
1021 | 'thrust',
1022 | 'thumb',
1023 | 'honey',
1024 | 'enforce',
1025 | 'ease',
1026 | 'thunder',
1027 | 'livingroom',
1028 | 'monument',
1029 | 'assess',
1030 | 'panic',
1031 | 'blanket',
1032 | 'drift',
1033 | 'normally',
1034 | 'dismiss',
1035 | 'deputy',
1036 | 'acre',
1037 | 'contract',
1038 | 'anniversary',
1039 | 'mainland',
1040 | 'expose',
1041 | 'policy',
1042 | 'machinery',
1043 | 'exert',
1044 | 'collection',
1045 | 'gasoline',
1046 | 'dispose',
1047 | 'arouse',
1048 | 'rage',
1049 | 'inward',
1050 | 'series',
1051 | 'roast',
1052 | 'timber',
1053 | 'reluctant',
1054 | 'license',
1055 | 'upright',
1056 | 'author',
1057 | 'mission',
1058 | 'growth',
1059 | 'attack',
1060 | 'furnish',
1061 | 'pretend',
1062 | 'concentrate',
1063 | 'institution',
1064 | 'flat',
1065 | 'tissue',
1066 | 'delicate',
1067 | 'upper',
1068 | 'gram',
1069 | 'crown',
1070 | 'title',
1071 | 'convey',
1072 | 'mount',
1073 | 'toast',
1074 | 'tolerance',
1075 | 'amongst',
1076 | 'slice',
1077 | 'dairy',
1078 | 'consultant',
1079 | 'multiply',
1080 | 'naked',
1081 | 'centigrade',
1082 | 'measurement',
1083 | 'precaution',
1084 | 'allocate',
1085 | 'certificate',
1086 | ]
1087 | const translations = ['心情',
1088 | '静态的',
1089 | '参议员',
1090 | '爱好',
1091 | '小伙子',
1092 | '装备',
1093 | '皱眉',
1094 | '系',
1095 | '软件',
1096 | '搅拌',
1097 | '分配',
1098 | '灵活',
1099 | '解',
1100 | '面板',
1101 | '部',
1102 | '最高',
1103 | '描述',
1104 | '肢',
1105 | '环境',
1106 | '核心',
1107 | '助理',
1108 | '乱',
1109 | '减去',
1110 | '统计',
1111 | '孕',
1112 | '部门',
1113 | '检测',
1114 | '雕像',
1115 | '新娘',
1116 | '周期',
1117 | '飞碟',
1118 | '熟练',
1119 | '文明',
1120 | '高架',
1121 | '冲突',
1122 | '批',
1123 | '键',
1124 | '员工',
1125 | '中间',
1126 | '吉他',
1127 | '全面',
1128 | '存在',
1129 | '器具',
1130 | '坐垫',
1131 | '紧急',
1132 | '解决',
1133 | '标签',
1134 | '瘦',
1135 | '状态',
1136 | '稳定',
1137 | '包括',
1138 | '抵抗性',
1139 | '主要',
1140 | '大使',
1141 | '派生',
1142 | '赞助',
1143 | '比例',
1144 | '心理',
1145 | '冲床',
1146 | '结果',
1147 | '客户',
1148 | '汽船',
1149 | '选项',
1150 | '宿舍',
1151 | '态度',
1152 | '陡',
1153 | '机构',
1154 | '引导',
1155 | '丑闻',
1156 | '定',
1157 | '谨慎',
1158 | '祷告',
1159 | '巢',
1160 | '国内',
1161 | '胸部',
1162 | '航空公司',
1163 | '反叛',
1164 | '满意的',
1165 | '干',
1166 | '渲染',
1167 | '目的',
1168 | '园丁',
1169 | '收缩',
1170 | '游行',
1171 | '谣言',
1172 | '地毯',
1173 | '建立',
1174 | '主要',
1175 | '善良',
1176 | '乳房',
1177 | '黏',
1178 | '促进',
1179 | '基金',
1180 | '难以置信',
1181 | '国外',
1182 | '侦探',
1183 | '僵硬',
1184 | '刺激',
1185 | '名气',
1186 | '消耗',
1187 | '加速',
1188 | '闪电',
1189 | '刺',
1190 | '界',
1191 | '唤醒',
1192 | '培育',
1193 | '材料',
1194 | '人员',
1195 | '显示',
1196 | '粒子',
1197 | '青蛙',
1198 | '印象',
1199 | '生物学',
1200 | '醉',
1201 | '屏障',
1202 | '股票',
1203 | '渔夫',
1204 | '政治家',
1205 | '皇家',
1206 | '理发师',
1207 | '袜',
1208 | '代表',
1209 | '突出',
1210 | '萧条',
1211 | '签名',
1212 | '大气层',
1213 | '评估',
1214 | '拯救',
1215 | '个性',
1216 | '后者',
1217 | '议会',
1218 | '输入',
1219 | '部分',
1220 | '忠诚',
1221 | '日历',
1222 | '俯瞰',
1223 | '辩论',
1224 | '哈腰',
1225 | '立方体',
1226 | '淹没',
1227 | '信用',
1228 | '周围',
1229 | '火炉',
1230 | '提交',
1231 | '载体',
1232 | '意味着',
1233 | '应变',
1234 | '组成',
1235 | '背带',
1236 | '高效',
1237 | '住所,',
1238 | '战略',
1239 | '层',
1240 | '惊呼',
1241 | '代表',
1242 | '预测',
1243 | '学科',
1244 | '中性',
1245 | '解释',
1246 | '结',
1247 | '期望',
1248 | '促进',
1249 | '验收',
1250 | '市长',
1251 | '方程',
1252 | '常规',
1253 | '成熟',
1254 | '证明',
1255 | '同样',
1256 | '第一章',
1257 | '探索',
1258 | '过夜',
1259 | '战略',
1260 | '稻草',
1261 | '绑定',
1262 | '流',
1263 | '轴承',
1264 | '假设',
1265 | '访问',
1266 | '保持',
1267 | '抽象',
1268 | '伸展',
1269 | '近似',
1270 | '引人注目',
1271 | '滥用',
1272 | '评论家',
1273 | '解释',
1274 | '串',
1275 | '说明',
1276 | '有帮助的',
1277 | '泄漏',
1278 | '会计',
1279 | '原油',
1280 | '产品',
1281 | '跳闸',
1282 | '条纹',
1283 | '通信',
1284 | '以下',
1285 | '树篱',
1286 | '消费者',
1287 | '情感',
1288 | '手艺',
1289 | '研究所',
1290 | '必不可少',
1291 | '方案',
1292 | '规模',
1293 | '更换',
1294 | '吠',
1295 | '克',
1296 | '国会',
1297 | '磕碰',
1298 | '行程',
1299 | '成分',
1300 | '任意',
1301 | '捏',
1302 | '利用',
1303 | '行动',
1304 | '灰',
1305 | '绳',
1306 | '块',
1307 | '加强',
1308 | '独立',
1309 | '板',
1310 | '召回',
1311 | '工作室',
1312 | '坟',
1313 | '前夕',
1314 | '正式',
1315 | '吸收',
1316 | '敏感',
1317 | '能力',
1318 | '仙女',
1319 | '天赋',
1320 | '比较',
1321 | '东东',
1322 | '眉头',
1323 | '推断',
1324 | '入侵',
1325 | '盛大',
1326 | '强调',
1327 | '记者',
1328 | '供应',
1329 | '穿透',
1330 | '学科',
1331 | '极',
1332 | '生的',
1333 | '大使馆',
1334 | '木匠',
1335 | '适当',
1336 | '社会主义',
1337 | '蛋白',
1338 | '放大',
1339 | '继承',
1340 | '化学家',
1341 | '冲突',
1342 | '排水',
1343 | '建筑',
1344 | '慈善机构',
1345 | '有权',
1346 | '后续',
1347 | '跨度',
1348 | '豌豆',
1349 | '指导',
1350 | '尽管',
1351 | '苗条',
1352 | '汽车',
1353 | '行为',
1354 | '羡慕',
1355 | '物质',
1356 | '比赛',
1357 | '吐',
1358 | '相互',
1359 | '宿舍',
1360 | '实质',
1361 | '与此同时',
1362 | '欲望',
1363 | '定罪',
1364 | '相互作用',
1365 | '菜单',
1366 | '阻挠',
1367 | '信仰',
1368 | '混乱',
1369 | '教化',
1370 | '前言',
1371 | '化学',
1372 | '水平',
1373 | '邀请函',
1374 | '汽车',
1375 | '电动',
1376 | '钱包',
1377 | '空白',
1378 | '庭院',
1379 | '乡村',
1380 | '不鼓励',
1381 | '反射',
1382 | '彩虹',
1383 | '滑动',
1384 | '清除',
1385 | '失踪',
1386 | '图形',
1387 | 'fortnight14',
1388 | '厌恶',
1389 | '罪行',
1390 | '允许',
1391 | '成比例的',
1392 | '奉献',
1393 | '帝国',
1394 | '麦克风',
1395 | '减去',
1396 | '步伐',
1397 | '手势',
1398 | '循环',
1399 | '纯粹的',
1400 | '橱柜',
1401 | '疮',
1402 | '袭击',
1403 | '降低',
1404 | '评论',
1405 | '窘迫',
1406 | '宣传',
1407 | '旋',
1408 | '博物馆',
1409 | '优秀',
1410 | '架',
1411 | '出租',
1412 | '住房',
1413 | '抱怨',
1414 | '显然',
1415 | '肺',
1416 | '拒绝',
1417 | '所有权',
1418 | '摆脱',
1419 | '马具',
1420 | '确认',
1421 | '激情',
1422 | '真正',
1423 | '假想',
1424 | '提示',
1425 | '发明',
1426 | '幸运',
1427 | '置信度',
1428 | '市郊',
1429 | '工业化',
1430 | '可怕',
1431 | '情报',
1432 | '童年',
1433 | '粉碎',
1434 | '意向',
1435 | '发现',
1436 | '地铁',
1437 | '磁铁',
1438 | '缺陷',
1439 | '属性',
1440 | '发布',
1441 | '演替',
1442 | '芯片',
1443 | '类似',
1444 | '保持',
1445 | '广告',
1446 | '特权',
1447 | '平淡',
1448 | '惹',
1449 | '功能',
1450 | '替代',
1451 | '极端',
1452 | '轨道',
1453 | '记者',
1454 | '时髦',
1455 | '津贴',
1456 | '零件',
1457 | '打断',
1458 | '连续',
1459 | '外部',
1460 | '不知何故',
1461 | '宣言',
1462 | '分发',
1463 | '专家',
1464 | '旋转',
1465 | '竿',
1466 | '吸',
1467 | '负',
1468 | '遭受',
1469 | '足够',
1470 | '法庭',
1471 | '卷曲',
1472 | '局',
1473 | '湿',
1474 | '相对',
1475 | '建议',
1476 | '不安',
1477 | '交货',
1478 | '要求',
1479 | '自杀',
1480 | '蘸',
1481 | '利润',
1482 | '租',
1483 | '处置',
1484 | '上诉',
1485 | '大车',
1486 | '稳定',
1487 | '已婚',
1488 | '估计',
1489 | '几乎',
1490 | '接待',
1491 | '陪审团',
1492 | '荣耀',
1493 | '薄雾',
1494 | '祝贺',
1495 | '和',
1496 | '执行',
1497 | '文章',
1498 | '路线',
1499 | '值得',
1500 | '本地',
1501 | '妥协',
1502 | '团结',
1503 | '羽毛',
1504 | '表征',
1505 | '爆炸',
1506 | '知道的',
1507 | '粮食',
1508 | '水壶',
1509 | '总结',
1510 | '错误',
1511 | '高度',
1512 | '概要',
1513 | '保护',
1514 | '首脑',
1515 | '奖励',
1516 | '可用',
1517 | '专业',
1518 | '结构体',
1519 | '居民',
1520 | '边界',
1521 | '激进',
1522 | '领导',
1523 | '抹布',
1524 | '规定',
1525 | '演示',
1526 | '方式',
1527 | '日出',
1528 | '构造',
1529 | '铁路',
1530 | '机会',
1531 | '落后',
1532 | '褪色',
1533 | '日落',
1534 | '单数',
1535 | '扫帚',
1536 | '下面',
1537 | '娱乐',
1538 | '游行',
1539 | '滑车',
1540 | '组合',
1541 | '地狱',
1542 | '证明',
1543 | '采取',
1544 | '招',
1545 | '对比',
1546 | '阳光',
1547 | '介绍',
1548 | '祖先',
1549 | '分裂',
1550 | '痛苦',
1551 | '高超',
1552 | '利益',
1553 | '显',
1554 | '毕业',
1555 | '一目了然',
1556 | '血腥',
1557 | '激烈',
1558 | '段',
1559 | '查询',
1560 | '制备',
1561 | '正义',
1562 | '滴',
1563 | '发射',
1564 | '浅',
1565 | '建议',
1566 | '唯一',
1567 | '民间',
1568 | '秩',
1569 | '发动机',
1570 | '飞机场',
1571 | '括',
1572 | '弹跳',
1573 | '场合',
1574 | '确定',
1575 | '建议',
1576 | '允许',
1577 | '声明',
1578 | '奖',
1579 | '胆大',
1580 | '所谓的',
1581 | '优越',
1582 | '阳光',
1583 | '替代',
1584 | '王国',
1585 | '移动',
1586 | '该死的',
1587 | '存储',
1588 | '补充',
1589 | '定位',
1590 | '舱',
1591 | '多数',
1592 | '接收器',
1593 | '支持',
1594 | '圣经',
1595 | '分配',
1596 | '插曲',
1597 | '致命',
1598 | '垫',
1599 | '漂移',
1600 | '愚昧',
1601 | '县',
1602 | '凝结',
1603 | '愈合',
1604 | '资产',
1605 | '涉及',
1606 | '后',
1607 | '空心',
1608 | '宪章',
1609 | '领导',
1610 | '浅',
1611 | '程序',
1612 | '令人印象深刻',
1613 | '争议',
1614 | '曲线',
1615 | '精神',
1616 | '震惊',
1617 | '折',
1618 | '警报',
1619 | '条件',
1620 | '分割',
1621 | '卷心菜',
1622 | '谴责',
1623 | '温和',
1624 | '手术',
1625 | '休闲',
1626 | '完成',
1627 | '插头',
1628 | '介绍',
1629 | '剩余',
1630 | '盒',
1631 | '环绕',
1632 | '私人的',
1633 | '灯泡',
1634 | '含义',
1635 | '每年',
1636 | '扩张',
1637 | '消除',
1638 | '喇叭',
1639 | '责任',
1640 | '坝',
1641 | '挑战',
1642 | '一样',
1643 | '现象',
1644 | '调查',
1645 | '窗帘',
1646 | '家庭',
1647 | '生存',
1648 | '勋章',
1649 | '投资',
1650 | '生存',
1651 | '尴尬',
1652 | '人造',
1653 | '制造',
1654 | '诅咒',
1655 | '疑似',
1656 | '暂停',
1657 | '浪潮',
1658 | '穿越',
1659 | '游览',
1660 | '仅仅',
1661 | '应付',
1662 | '间隙',
1663 | '反对',
1664 | '截止日期',
1665 | '自动',
1666 | '联合',
1667 | '投降',
1668 | '无礼',
1669 | '晕',
1670 | '会议',
1671 | '问题',
1672 | '吞',
1673 | '室内',
1674 | '计算器',
1675 | '分析',
1676 | '冒险',
1677 | '奇迹',
1678 | '摇摆',
1679 | '社论',
1680 | '承认',
1681 | '图书管理员',
1682 | '分析',
1683 | '孩子',
1684 | '伙伴',
1685 | '发誓',
1686 | '中央',
1687 | '整洁',
1688 | '护照',
1689 | '胀',
1690 | '链接',
1691 | '勇敢',
1692 | '迅速',
1693 | '禁止',
1694 | '批准',
1695 | '摇摆',
1696 | '理想',
1697 | '逮捕',
1698 | '景观',
1699 | '代表',
1700 | '听众',
1701 | '开关',
1702 | '剑',
1703 | '点',
1704 | '符号',
1705 | '制裁',
1706 | '桶',
1707 | '诗歌',
1708 | '纤维',
1709 | '养老金',
1710 | '乞丐',
1711 | '插图',
1712 | '容易',
1713 | '束',
1714 | '管理',
1715 | '同情',
1716 | '会话',
1717 | '美味的',
1718 | '微风',
1719 | '模拟',
1720 | '婴儿',
1721 | '同情',
1722 | '优点',
1723 | '大量',
1724 | '骨刺',
1725 | '宗教',
1726 | '旗帜',
1727 | '尼龙',
1728 | '非常',
1729 | '症状',
1730 | '支柱',
1731 | '结果',
1732 | '旅程',
1733 | '前额',
1734 | '良心',
1735 | '精确',
1736 | '电缆',
1737 | '拧',
1738 | '帮派',
1739 | '青睐',
1740 | '构成',
1741 | '挤',
1742 | '系统',
1743 | '文化',
1744 | '导弹',
1745 | '投',
1746 | '马克思主义者',
1747 | '事先',
1748 | '染料',
1749 | '优美',
1750 | '洋葱',
1751 | '密封',
1752 | '圣',
1753 | '犹豫',
1754 | '爬行',
1755 | '有助于',
1756 | '迷人',
1757 | '娱乐',
1758 | '香烟',
1759 | '巨大',
1760 | '外',
1761 | '革命',
1762 | '布',
1763 | '岭',
1764 | '大众',
1765 | '有能力',
1766 | '结论',
1767 | '砰',
1768 | '好奇',
1769 | '脉冲',
1770 | '遭遇',
1771 | '关心',
1772 | '介词',
1773 | '池塘',
1774 | '规定',
1775 | '加强',
1776 | '系统(人)',
1777 | '轨',
1778 | '拍',
1779 | '合理的',
1780 | '逃跑',
1781 | '响应',
1782 | '行政人员',
1783 | '标签',
1784 | '手段',
1785 | '外甥',
1786 | '引动',
1787 | '失败',
1788 | '一致',
1789 | '无处',
1790 | '同情',
1791 | '草图',
1792 | '冷静',
1793 | '驯服',
1794 | '取消',
1795 | '祈祷',
1796 | '目标',
1797 | '骆驼',
1798 | '技术员',
1799 | '设置',
1800 | '技术',
1801 | '税',
1802 | '出现',
1803 | '能',
1804 | '技术',
1805 | '自私',
1806 | '定义',
1807 | '每',
1808 | '参加',
1809 | '乏味',
1810 | '急',
1811 | '饥荒',
1812 | '基本的',
1813 | '复数',
1814 | '预料',
1815 | '青少年',
1816 | '压缩',
1817 | '胡椒',
1818 | '卸货',
1819 | '望远镜',
1820 | '脾气',
1821 | '广泛',
1822 | '逗',
1823 | '当前',
1824 | '面具',
1825 | '音乐家',
1826 | '寺庙',
1827 | '衰变',
1828 | '批评',
1829 | '反馈',
1830 | '按照',
1831 | '感知',
1832 | '几乎没有',
1833 | '粘土',
1834 | '智能',
1835 | '导体',
1836 | '频率',
1837 | '有吸引力',
1838 | '大蒜',
1839 | '临时',
1840 | '认识',
1841 | '难题',
1842 | '电梯',
1843 | '收购',
1844 | '绝对',
1845 | '坦率',
1846 | '臀部',
1847 | '抛光',
1848 | '民主',
1849 | '诱惑',
1850 | '伪装',
1851 | '胶',
1852 | '庄严',
1853 | '趋向',
1854 | '古',
1855 | '有效',
1856 | '渠道',
1857 | '原始',
1858 | '同意',
1859 | '组织',
1860 | '戏剧',
1861 | '惨',
1862 | '毛皮',
1863 | '古董',
1864 | '替代',
1865 | '内',
1866 | '业务员',
1867 | '酒',
1868 | '目前',
1869 | '基因',
1870 | '安全',
1871 | '神经',
1872 | '贪婪',
1873 | '必要',
1874 | '装饰',
1875 | '过量',
1876 | '比较',
1877 | '命令',
1878 | '汽油',
1879 | '塑料',
1880 | '特性',
1881 | '压力',
1882 | '附近',
1883 | '环境',
1884 | '犯罪',
1885 | '鸽子',
1886 | '水泥',
1887 | '华丽的',
1888 | '趋势',
1889 | '调查',
1890 | '无穷',
1891 | '画家',
1892 | '投标',
1893 | '法律',
1894 | '中等',
1895 | '原子',
1896 | '锚',
1897 | '神秘',
1898 | '关联',
1899 | '反应',
1900 | '影响',
1901 | '紧张',
1902 | '面粉',
1903 | '喜剧',
1904 | '直',
1905 | '碰撞',
1906 | '缺席',
1907 | '危急',
1908 | '爪子',
1909 | '船员',
1910 | '恭喜',
1911 | '干扰',
1912 | '肉',
1913 | '无辜',
1914 | '激动',
1915 | '成人',
1916 | '提高',
1917 | '到达',
1918 | '简要',
1919 | '志向',
1920 | '大纲',
1921 | '飞机',
1922 | '肥料',
1923 | '张力',
1924 | '汽油',
1925 | '区分',
1926 | '缺点',
1927 | '提出',
1928 | '前任的',
1929 | '消费',
1930 | '终奌站',
1931 | '休闲',
1932 | '强硬',
1933 | '追求',
1934 | '意外',
1935 | '省长',
1936 | '口服',
1937 | '领土',
1938 | '单纯',
1939 | '毛',
1940 | '音',
1941 | '指示',
1942 | '关于',
1943 | '拥抱',
1944 | '众多',
1945 | '发射',
1946 | '折扣',
1947 | '保养',
1948 | '倾斜',
1949 | '自由主义的',
1950 | '厕',
1951 | '结婚',
1952 | '宪法',
1953 | '容忍',
1954 | '知识分子',
1955 | '业余',
1956 | '蘑菇',
1957 | '毫米',
1958 | '伴侣',
1959 | '弯头',
1960 | '纺织品',
1961 | '帧',
1962 | '混合',
1963 | '误解',
1964 | '搭接',
1965 | '概念',
1966 | '仇恨',
1967 | '滑',
1968 | '耐用',
1969 | '推理',
1970 | '雇员',
1971 | '香肠',
1972 | '主题',
1973 | '同事',
1974 | '戏剧性',
1975 | '忍耐',
1976 | '飞船',
1977 | '保留',
1978 | '进口',
1979 | '破产',
1980 | '动画片',
1981 | '联盟',
1982 | '浪漫',
1983 | '桶',
1984 | '理论',
1985 | '栈',
1986 | '解决',
1987 | '希望',
1988 | '刑事',
1989 | '插',
1990 | '特别',
1991 | '告',
1992 | '揭示',
1993 | '包',
1994 | '有罪',
1995 | '付款',
1996 | '进攻',
1997 | '选',
1998 | '向下',
1999 | '液体',
2000 | '线索',
2001 | '爵士乐',
2002 | '连词',
2003 | '主',
2004 | '治疗',
2005 | '停止',
2006 | '变量',
2007 | '身份',
2008 | '义务',
2009 | '相对论',
2010 | '请教',
2011 | '无论如何',
2012 | '间接',
2013 | '代理人',
2014 | '扫描',
2015 | '柠檬',
2016 | '对手',
2017 | '气候',
2018 | '加成',
2019 | '建筑师',
2020 | '整合',
2021 | '外观',
2022 | '从而',
2023 | '因此',
2024 | '一小撮',
2025 | '忠诚',
2026 | '此外',
2027 | '保险',
2028 | '类别',
2029 | '细化',
2030 | '厚',
2031 | '少数民族',
2032 | '悲哀',
2033 | '思维',
2034 | '测验',
2035 | '飞机',
2036 | '渴',
2037 | '异议',
2038 | '平台',
2039 | '商人',
2040 | '沃',
2041 | '尤其',
2042 | '师',
2043 | '危机',
2044 | '彻底',
2045 | '向前',
2046 | '观察员',
2047 | '撤退',
2048 | '相关',
2049 | '精确',
2050 | '承认',
2051 | '丛林',
2052 | '周到',
2053 | '公寓',
2054 | '之后',
2055 | '整个',
2056 | '碳',
2057 | '室',
2058 | '领域',
2059 | '比',
2060 | '捕获',
2061 | '棒球',
2062 | '无聊',
2063 | '人群',
2064 | '样品',
2065 | '房地产',
2066 | '威胁',
2067 | '可靠',
2068 | '不变',
2069 | '支持',
2070 | '马力',
2071 | '怀疑',
2072 | '展望',
2073 | '进行',
2074 | '草坪',
2075 | '发送',
2076 | '污染',
2077 | '滑',
2078 | '有影响',
2079 | '处理',
2080 | '威胁',
2081 | '飞机',
2082 | '兴旺',
2083 | '危害',
2084 | '类似',
2085 | '突出',
2086 | '信号',
2087 | '鼓励',
2088 | '经济衰退',
2089 | '承诺',
2090 | '监控',
2091 | '火花',
2092 | '杯',
2093 | '缺席',
2094 | '欣赏',
2095 | '豆',
2096 | '弹性',
2097 | '想必',
2098 | '讨价还价',
2099 | '重大',
2100 | '喉',
2101 | '延伸',
2102 | '可比',
2103 | '容器',
2104 | '首席',
2105 | '瞬间',
2106 | '推力',
2107 | '拇指',
2108 | '蜜糖',
2109 | '执行',
2110 | '缓解',
2111 | '雷',
2112 | '客厅',
2113 | '纪念碑',
2114 | '评估',
2115 | '恐慌',
2116 | '毯',
2117 | '漂移',
2118 | '一般',
2119 | '解雇',
2120 | '副',
2121 | '英亩',
2122 | '合同',
2123 | '周年',
2124 | '大陆',
2125 | '暴露',
2126 | '政策',
2127 | '机械',
2128 | '发挥',
2129 | '采集',
2130 | '汽油',
2131 | '处置',
2132 | '引起',
2133 | '愤怒',
2134 | '向内的',
2135 | '系列',
2136 | '烤',
2137 | '木材',
2138 | '不情愿',
2139 | '执照',
2140 | '直立',
2141 | '作者',
2142 | '任务',
2143 | '增长',
2144 | '攻击',
2145 | '装设',
2146 | '假装',
2147 | '集中',
2148 | '机构',
2149 | '平面',
2150 | '组织',
2151 | '精致',
2152 | '上',
2153 | '公克',
2154 | '王冠',
2155 | '标题',
2156 | '传达',
2157 | '安装',
2158 | '敬酒',
2159 | '公差',
2160 | '之间',
2161 | '片',
2162 | '奶牛',
2163 | '顾问',
2164 | '乘',
2165 | '裸',
2166 | '摄氏度',
2167 | '测量',
2168 | '预防',
2169 | '分配',
2170 | '证书',
2171 | ]
2172 |
2173 | export {
2174 | words,
2175 | translations,
2176 | }
2177 |
--------------------------------------------------------------------------------
/src/assets/js/waterMark.js:
--------------------------------------------------------------------------------
1 | const defaultSettings = {
2 | watermark_txt: 'text',
3 | watermark_x: 24, // 水印起始位置x轴坐标
4 | watermark_y: 24, // 水印起始位置Y轴坐标
5 | watermark_rows: 24, // 水印行数
6 | watermark_cols: 24, // 水印列数
7 | watermark_x_space: 200, // 水印x轴间隔
8 | watermark_y_space: 100, // 水印y轴间隔
9 | watermark_color: '#000000', // 水印字体颜色
10 | watermark_alpha: 0.1, // 水印透明度
11 | watermark_fontsize: '1rem', // 水印字体大小
12 | watermark_font: '微软雅黑', // 水印字体
13 | watermark_width: 120, // 水印宽度
14 | watermark_height: 30, // 水印长度
15 | watermark_angle: 15, // 水印倾斜度数
16 | }
17 |
18 | class WaterMark {
19 | constructor(settings) {
20 | this.settings = Object.assign({}, defaultSettings, settings)
21 | }
22 |
23 | init() {
24 | this.destory()
25 | this.addWaterMark()
26 | }
27 |
28 | addWaterMark() {
29 | const oTemp = document.createDocumentFragment()
30 |
31 | // 获取页面最大宽度
32 | const page_width = Math.max(document.body.scrollWidth, document.body.clientWidth)
33 | // 获取页面最大长度
34 | const page_height = Math.max(document.body.scrollHeight, document.body.clientHeight)
35 |
36 | // 如果将水印列数设置为0,或水印列数设置过大,超过页面最大宽度,则重新计算水印列数和水印x轴间隔
37 | if (this.settings.watermark_cols === 0
38 | || (Number.parseInt(this.settings.watermark_x
39 | + this.settings.watermark_width * this.settings.watermark_cols
40 | + this.settings.watermark_x_space * (this.settings.watermark_cols - 1))
41 | > page_width)) {
42 | this.settings.watermark_cols
43 | = Number.parseInt((page_width
44 | - this.settings.watermark_x
45 | + this.settings.watermark_x_space)
46 | / (this.settings.watermark_width
47 | + this.settings.watermark_x_space))
48 | this.settings.watermark_x_space
49 | = Number.parseInt((page_width
50 | - this.settings.watermark_x
51 | - this.settings.watermark_width
52 | * this.settings.watermark_cols)
53 | / (this.settings.watermark_cols - 1))
54 | }
55 |
56 | // 如果将水印行数设置为0,或水印行数设置过大,超过页面最大长度,则重新计算水印行数和水印y轴间隔
57 | if (this.settings.watermark_rows === 0
58 | || (Number.parseInt(this.settings.watermark_y
59 | + this.settings.watermark_height * this.settings.watermark_rows
60 | + this.settings.watermark_y_space * (this.settings.watermark_rows - 1))
61 | > page_height)) {
62 | this.settings.watermark_rows
63 | = Number.parseInt((this.settings.watermark_y_space
64 | + page_height - this.settings.watermark_y)
65 | / (this.settings.watermark_height + this.settings.watermark_y_space))
66 | this.settings.watermark_y_space
67 | = Number.parseInt((page_height
68 | - this.settings.watermark_y
69 | - this.settings.watermark_height
70 | * this.settings.watermark_rows)
71 | / (this.settings.watermark_rows - 1))
72 | }
73 |
74 | const arr = []
75 |
76 | for (let i = 1; i < this.settings.watermark_rows - 1; i++) {
77 | const y = this.settings.watermark_y + (this.settings.watermark_y_space + this.settings.watermark_height) * i
78 | for (let j = 0; j < this.settings.watermark_cols; j++) {
79 | const x = this.settings.watermark_x + (this.settings.watermark_width + this.settings.watermark_x_space) * j
80 |
81 | const mask_div = document.createElement('div')
82 | mask_div.className = 'mask_div'
83 | mask_div.id = `mask_div${i}${j}`
84 | mask_div.appendChild(document.createTextNode(this.settings.watermark_txt))
85 | // 设置水印div倾斜显示
86 | mask_div.style.webkitTransform = `rotate(-${this.settings.watermark_angle}deg)`
87 | mask_div.style.MozTransform = `rotate(-${this.settings.watermark_angle}deg)`
88 | mask_div.style.msTransform = `rotate(-${this.settings.watermark_angle}deg)`
89 | mask_div.style.OTransform = `rotate(-${this.settings.watermark_angle}deg)`
90 | mask_div.style.transform = `rotate(-${this.settings.watermark_angle}deg)`
91 | mask_div.style.visibility = ''
92 | mask_div.style.position = 'absolute'
93 | mask_div.style.left = `${x}px`
94 | mask_div.style.top = `${y}px`
95 | mask_div.style.overflow = 'hidden'
96 | mask_div.style.zIndex = '9999'
97 | // mask_div.style.border="solid #eee 1px";
98 | mask_div.style.opacity = this.settings.watermark_alpha
99 | mask_div.style.fontSize = this.settings.watermark_fontsize
100 | mask_div.style.fontFamily = this.settings.watermark_font
101 | mask_div.style.color = this.settings.watermark_color
102 | mask_div.style.textAlign = 'center'
103 | mask_div.style.width = `${this.settings.watermark_width}px`
104 | mask_div.style.height = `${this.settings.watermark_height}px`
105 | mask_div.style.display = 'block'
106 | mask_div.style.pointerEvents = 'none'
107 | oTemp.appendChild(mask_div)
108 | arr.push(mask_div.id)
109 | }
110 | }
111 | document.body.appendChild(oTemp)
112 | }
113 |
114 | destory() {
115 | // 每次添加水印时,都先清一遍水印,防止水印多次添加
116 | const waterMarkArr = document.querySelectorAll('.mask_div')
117 | waterMarkArr.forEach((item) => {
118 | item.remove()
119 | })
120 | }
121 | }
122 |
123 | export default WaterMark
124 |
--------------------------------------------------------------------------------
/src/components.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | /* prettier-ignore */
3 | // @ts-nocheck
4 | // Generated by unplugin-vue-components
5 | // Read more: https://github.com/vuejs/core/pull/3399
6 | export {}
7 |
8 | declare module 'vue' {
9 | export interface GlobalComponents {
10 | CloseHandler: typeof import('./components/CloseHandler.vue')['default']
11 | CollapseTransition: typeof import('./components/CollapseTransition.vue')['default']
12 | HiddenSourceSvg: typeof import('./components/Svg/HiddenSourceSvg.vue')['default']
13 | Loading: typeof import('./components/Loading.vue')['default']
14 | RouterLink: typeof import('vue-router')['RouterLink']
15 | RouterView: typeof import('vue-router')['RouterView']
16 | Showcase: typeof import('./components/Showcase.vue')['default']
17 | SourceCode: typeof import('./components/SourceCode.vue')['default']
18 | TheFooter: typeof import('./components/TheFooter.vue')['default']
19 | TheSidebar: typeof import('./components/TheSidebar.vue')['default']
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/CloseHandler.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
61 |
--------------------------------------------------------------------------------
/src/components/CollapseTransition.vue:
--------------------------------------------------------------------------------
1 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
86 |
--------------------------------------------------------------------------------
/src/components/Loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
264 |
--------------------------------------------------------------------------------
/src/components/Showcase.cy.ts:
--------------------------------------------------------------------------------
1 | import Showcase from './Showcase.vue'
2 |
3 | describe('', () => {
4 | it('renders', () => {
5 | // see: https://test-utils.vuejs.org/guide/
6 | cy.mount(Showcase)
7 | })
8 | })
9 |
--------------------------------------------------------------------------------
/src/components/Showcase.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 | {{ title }}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
77 |
78 |
79 |
80 | 隐藏源代码
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
100 |
--------------------------------------------------------------------------------
/src/components/SourceCode.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
32 |
33 |
34 |
82 |
--------------------------------------------------------------------------------
/src/components/Svg/HiddenSourceSvg.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/TheFooter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/TheSidebar.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
31 |
32 |
--------------------------------------------------------------------------------
/src/composables/dark.ts:
--------------------------------------------------------------------------------
1 | export const isDark = useDark()
2 | export const preferredDark = usePreferredDark()
3 | const isAppearanceTransition
4 | = typeof document !== 'undefined'
5 | // @ts-expect-error: Transition API
6 | && document.startViewTransition
7 | && !window.matchMedia('(prefers-reduced-motion: reduce)').matches
8 |
9 | /**
10 | * Credit to [@hooray](https://github.com/hooray)
11 | * @see https://github.com/vuejs/vitepress/pull/2347
12 | */
13 | export function toggleDark(event?: MouseEvent) {
14 | if (!isAppearanceTransition || !event) {
15 | isDark.value = !isDark.value
16 | return
17 | }
18 |
19 | const x = event.clientX
20 | const y = event.clientY
21 | const endRadius = Math.hypot(
22 | Math.max(x, innerWidth - x),
23 | Math.max(y, innerHeight - y),
24 | )
25 | // @ts-expect-error: Transition API
26 | const transition = document.startViewTransition(async () => {
27 | isDark.value = !isDark.value
28 | await nextTick()
29 | })
30 |
31 | transition.ready.then(() => {
32 | const clipPath = [
33 | `circle(0px at ${x}px ${y}px)`,
34 | `circle(${endRadius}px at ${x}px ${y}px)`,
35 | ]
36 | document.documentElement.animate(
37 | {
38 | clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
39 | },
40 | {
41 | duration: 400,
42 | easing: 'ease-in',
43 | pseudoElement: isDark.value
44 | ? '::view-transition-old(root)'
45 | : '::view-transition-new(root)',
46 | },
47 | )
48 | })
49 | }
50 |
--------------------------------------------------------------------------------
/src/composables/display.ts:
--------------------------------------------------------------------------------
1 | export const isFullDisplay = ref(false)
2 | export const toggleFullDisplay = useToggle(isFullDisplay)
3 |
4 | useStorage('isFullDisplay', isFullDisplay)
5 |
--------------------------------------------------------------------------------
/src/composables/hiddenSidebar.ts:
--------------------------------------------------------------------------------
1 | export const isHiddenSidebar = ref(false)
2 | export const toggleHiddenSidebar = useToggle(isHiddenSidebar)
3 |
4 | useStorage('isHiddenSidebar', isHiddenSidebar)
5 |
--------------------------------------------------------------------------------
/src/layouts/404.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |

12 |
13 |
14 |
15 |
18 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/layouts/demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/layouts/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { ViteSSG } from 'vite-ssg'
2 | import { setupLayouts } from 'virtual:generated-layouts'
3 |
4 | // import Previewer from 'virtual:vue-component-preview'
5 | import App from './App.vue'
6 | import type { UserModule } from './types'
7 | import generatedRoutes from '~pages'
8 |
9 | import '@unocss/reset/tailwind.css'
10 | import './styles/main.css'
11 | import 'uno.css'
12 |
13 | const routes = setupLayouts(generatedRoutes)
14 |
15 | // https://github.com/antfu/vite-ssg
16 | export const createApp = ViteSSG(
17 | App,
18 | { routes, base: import.meta.env.BASE_URL },
19 | (ctx) => {
20 | // install all modules under `modules/`
21 | Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true }))
22 | .forEach(i => i.install?.(ctx))
23 | // ctx.app.use(Previewer)
24 | },
25 | )
26 |
--------------------------------------------------------------------------------
/src/modules/i18n.ts:
--------------------------------------------------------------------------------
1 | import type { Locale } from 'vue-i18n'
2 | import { createI18n } from 'vue-i18n'
3 | import { type UserModule } from '~/types'
4 |
5 | // Import i18n resources
6 | // https://vitejs.dev/guide/features.html#glob-import
7 | //
8 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
9 | const i18n = createI18n({
10 | legacy: false,
11 | locale: '',
12 | messages: {},
13 | })
14 |
15 | const localesMap = Object.fromEntries(
16 | Object.entries(import.meta.glob('../../locales/*.yml'))
17 | .map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]),
18 | ) as Record Promise<{ default: Record }>>
19 |
20 | export const availableLocales = Object.keys(localesMap)
21 |
22 | const loadedLanguages: string[] = []
23 |
24 | function setI18nLanguage(lang: Locale) {
25 | i18n.global.locale.value = lang as any
26 | if (typeof document !== 'undefined')
27 | document.querySelector('html')?.setAttribute('lang', lang)
28 | return lang
29 | }
30 |
31 | export async function loadLanguageAsync(lang: string): Promise {
32 | // If the same language
33 | if (i18n.global.locale.value === lang)
34 | return setI18nLanguage(lang)
35 |
36 | // If the language was already loaded
37 | if (loadedLanguages.includes(lang))
38 | return setI18nLanguage(lang)
39 |
40 | // If the language hasn't been loaded yet
41 | const messages = await localesMap[lang]()
42 | i18n.global.setLocaleMessage(lang, messages.default)
43 | loadedLanguages.push(lang)
44 | return setI18nLanguage(lang)
45 | }
46 |
47 | export const install: UserModule = ({ app }) => {
48 | app.use(i18n)
49 | loadLanguageAsync('en')
50 | }
51 |
--------------------------------------------------------------------------------
/src/modules/nprogress.ts:
--------------------------------------------------------------------------------
1 | import NProgress from 'nprogress'
2 | import { type UserModule } from '~/types'
3 |
4 | export const install: UserModule = ({ isClient, router }) => {
5 | if (isClient) {
6 | router.beforeEach((to, from) => {
7 | if (to.path !== from.path)
8 | NProgress.start()
9 | })
10 | router.afterEach(() => {
11 | NProgress.done()
12 | })
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/modules/pinia.ts:
--------------------------------------------------------------------------------
1 | import { createPinia } from 'pinia'
2 | import { type UserModule } from '~/types'
3 |
4 | // Setup Pinia
5 | // https://pinia.vuejs.org/
6 | export const install: UserModule = ({ isClient, initialState, app }) => {
7 | const pinia = createPinia()
8 | app.use(pinia)
9 | // Refer to
10 | // https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization
11 | // for other serialization strategies.
12 | if (isClient)
13 | pinia.state.value = (initialState.pinia) || {}
14 |
15 | else
16 | initialState.pinia = pinia.state.value
17 | }
18 |
--------------------------------------------------------------------------------
/src/modules/pwa.ts:
--------------------------------------------------------------------------------
1 | import { type UserModule } from '~/types'
2 |
3 | // https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available
4 | export const install: UserModule = ({ isClient, router }) => {
5 | if (!isClient)
6 | return
7 |
8 | router.isReady()
9 | .then(async () => {
10 | const { registerSW } = await import('virtual:pwa-register')
11 | registerSW({ immediate: true })
12 | })
13 | .catch(() => { })
14 | }
15 |
--------------------------------------------------------------------------------
/src/pages/[...all].vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 未找到页面
4 |
5 |
6 |
7 |
8 | meta:
9 | layout: 404
10 |
11 |
--------------------------------------------------------------------------------
/src/pages/about.md:
--------------------------------------------------------------------------------
1 | ## 前端示例代码库
2 |
3 | 整理前端样式和功能的实现代码,可以用来寻找灵感,或直接使用示例中的代码。
4 |
5 | 当然,你也可以将其当做自己的前端样式展示库。
6 |
7 | 所有演示代码均存放在 [src/pages/example](https://github.com/kuizuo/example/tree/main/src/pages/example) 下,均使用 [vue3 setup](https://cn.vuejs.org/api/sfc-script-setup.html#script-setup) 语法进行编写。
8 |
9 | ### 特点
10 |
11 | - 基于 [vitesse](https://github.com/antfu/vitesse) 模板,使用Vue3 + Vite + UnoCSS
12 |
13 | - 在 [src/pages/example](https://github.com/kuizuo/example/tree/main/src/pages/example) 下的组件通过 [SFC](https://cn.vuejs.org/api/sfc-spec.html#sfc-syntax-specification) 使用 [\ 标签块](https://github.com/hannoeru/vite-plugin-pages#sfc-custom-block-for-route-data) 定义组件信息,无需额外定义数据。
14 |
15 | - 两种演示组件方式,方便预览的同时,还可以查看或复制组件相关代码。
16 |
--------------------------------------------------------------------------------
/src/pages/example/aircraft.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 |
41 | 随便移动一下鼠标,看看效果
42 |
43 |
44 |
45 |
52 |
53 |
54 | name: 指向鼠标的小飞机
55 | meta:
56 | layout: demo
57 |
58 |
--------------------------------------------------------------------------------
/src/pages/example/annular-progress.vue:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
39 |
40 |
41 |
77 |
78 |
79 | name: 环形进度栏
80 | meta:
81 | layout: demo
82 |
83 |
--------------------------------------------------------------------------------
/src/pages/example/bottom-navigation.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 | 1
18 |
19 |
20 |
42 |
43 |
44 |
45 |
95 |
96 |
97 | name: 底部导航条
98 | meta:
99 | layout: demo
100 |
101 |
--------------------------------------------------------------------------------
/src/pages/example/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | name: 按钮效果
9 | meta:
10 | layout: demo
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/example/carousel.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
26 |
32 |
33 | -
34 | {{ i + 1 }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
87 |
88 |
89 | name: 轮播图
90 | meta:
91 | layout: demo
92 |
93 |
--------------------------------------------------------------------------------
/src/pages/example/claymorphism.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
11 |
12 |
26 |
27 |
28 | name: 泥陶态风格
29 | meta:
30 | layout: demo
31 |
32 |
--------------------------------------------------------------------------------
/src/pages/example/click.vue:
--------------------------------------------------------------------------------
1 |
228 |
229 |
230 |
231 | 当前鼠标效果: {{ type }}
232 |
233 |
254 |
255 |
256 |
257 |
258 | name: 鼠标点击特效
259 | meta:
260 | layout: demo
261 |
262 |
--------------------------------------------------------------------------------
/src/pages/example/clip-path.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 | -
10 |
11 |
12 | -
13 |
14 |
15 | -
16 |
17 |
18 | -
19 |
20 |
21 | -
22 |
23 |
24 | -
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
34 |
35 |
36 |
100 |
101 |
102 | name: clip-path 裁剪图形
103 | meta:
104 | layout: demo
105 |
106 |
--------------------------------------------------------------------------------
/src/pages/example/congratulations.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | 🎉 Congratulations!
16 |
17 |
20 |
21 |
22 |
29 |
30 |
31 | name: 五彩纸屑
32 | meta:
33 | layout: demo
34 |
35 |
--------------------------------------------------------------------------------
/src/pages/example/digital-clock.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 | {{ formatted }}
8 |
9 |
10 |
11 |
27 |
28 |
29 | name: 数码时钟
30 | meta:
31 | layout: demo
32 |
33 |
--------------------------------------------------------------------------------
/src/pages/example/glassmorphism.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
32 |
33 |
34 | name: 玻璃态风格
35 | meta:
36 | layout: demo
37 |
38 |
--------------------------------------------------------------------------------
/src/pages/example/gradient-background.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
30 |
31 |
32 | name: 渐变背景
33 | meta:
34 | layout: demo
35 |
36 |
--------------------------------------------------------------------------------
/src/pages/example/gradient-border.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
28 |
29 |
30 | name: 渐变边框
31 | meta:
32 | layout: demo
33 |
34 |
--------------------------------------------------------------------------------
/src/pages/example/gradient-shadow.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
33 |
34 |
35 | name: 渐变阴影
36 | meta:
37 | layout: demo
38 |
39 |
--------------------------------------------------------------------------------
/src/pages/example/loading-pac-man.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
更多 Loading 效果
17 |
18 | SpinKit
19 |
20 |
21 | 前端可视化
22 |
23 |
24 |
25 |
26 |
273 |
274 |
275 | name: 吃豆人加载动画
276 | meta:
277 | layout: demo
278 |
279 |
--------------------------------------------------------------------------------
/src/pages/example/mac-terminal.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 | {{ language }}
23 |
24 |
25 |
26 |
27 | $
28 | {{ c }}
29 |
30 |
31 |
32 |
33 |
34 | {{ copied ? 'Copied!' : 'Click to copy' }}
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 | name: 仿Mac终端
45 | meta:
46 | layout: demo
47 |
48 |
--------------------------------------------------------------------------------
/src/pages/example/multilayer-border.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
16 |
17 |
18 | name: 多重边框
19 | meta:
20 | layout: demo
21 |
22 |
--------------------------------------------------------------------------------
/src/pages/example/neumorphism.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
86 |
87 |
88 | name: 新拟态风格
89 | meta:
90 | layout: demo
91 |
92 |
--------------------------------------------------------------------------------
/src/pages/example/profile.vue:
--------------------------------------------------------------------------------
1 |
55 |
56 |
57 |
58 |
59 |
60 | 👋{{ t('profile.hi') }}{{ t('profile.kuizuo') }},
61 |
62 | {{ text }}
63 |
64 |
65 |
72 | Let’s Look It
73 |
74 |
75 |
76 |
77 |
78 |
79 | name: 个人主页简介
80 | meta:
81 | layout: demo
82 |
83 |
--------------------------------------------------------------------------------
/src/pages/example/siderbar-navigation.vue:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 侧边栏导航
35 |
36 |
47 |
48 |
49 |
50 |
51 |

52 |
愧怍
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | test
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
226 |
227 |
228 | name: 侧边导航栏
229 | meta:
230 | layout: demo
231 |
232 |
--------------------------------------------------------------------------------
/src/pages/example/srcoll.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
1
5 |
1
6 |
1
7 |
1
8 |
1
9 |
1
10 |
1
11 |
1
12 |
1
13 |
1
14 |
1
15 |
1
16 |
1
17 |
1
18 |
1
19 |
1
20 |
1
21 |
1
22 |
1
23 |
1
24 |
1
25 |
1
26 |
27 |
28 |
29 |
30 |
62 |
63 |
64 | name: 滚动条
65 | meta:
66 | layout: demo
67 |
68 |
--------------------------------------------------------------------------------
/src/pages/example/tabs.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
37 | -
38 | {{ item.title }}
39 |
40 |
41 |
42 |
43 | {{ item.content }}
44 |
45 |
46 |
47 |
48 |
49 |
107 |
108 |
109 | name: tabs栏
110 | meta:
111 | layout: demo
112 |
113 |
--------------------------------------------------------------------------------
/src/pages/example/tag-surround.vue:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
29 |
37 |
38 | {{ item }}
39 |
40 |
41 |
42 |
45 |
46 |
47 |
92 |
93 |
94 | name: 标签3D环绕
95 | meta:
96 | layout: demo
97 |
98 |
--------------------------------------------------------------------------------
/src/pages/example/text-overflow.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 | {{ data }}
14 |
15 |
16 |
17 |
18 |
28 |
29 |
30 | name: 文本省略
31 | meta:
32 | layout: demo
33 |
34 |
--------------------------------------------------------------------------------
/src/pages/example/text.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 | {{ data }}
15 |
16 |
17 |
18 |
19 | {{ data }}
20 |
21 |
22 |
23 |
24 | {{ data }}
25 |
26 |
27 |
28 |
29 | {{ data }}
30 |
31 |
32 |
33 |
34 |
35 |
80 |
81 |
82 | name: 文本特效
83 | meta:
84 | layout: demo
85 |
86 |
--------------------------------------------------------------------------------
/src/pages/example/typewriter.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 | {{ data }}
14 |
15 |
16 |
17 |
18 |
47 |
48 |
49 | name: 打字机效果
50 | meta:
51 | layout: demo
52 |
53 |
--------------------------------------------------------------------------------
/src/pages/example/watermark.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 |
22 | name: 水印
23 | meta:
24 | layout: demo
25 |
26 |
--------------------------------------------------------------------------------
/src/pages/example/weather.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
15 |
21 |
27 |
35 |
36 |
37 |
44 |
45 |
46 |
424 |
425 |
426 | name: 动态天气效果
427 | meta:
428 | layout: demo
429 |
430 |
--------------------------------------------------------------------------------
/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | 前端示例代码库
11 |
12 |
13 | -
14 |
15 | {{ item.name }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
63 |
64 |
65 | meta:
66 | layout: home
67 |
68 |
--------------------------------------------------------------------------------
/src/shims.d.ts:
--------------------------------------------------------------------------------
1 | declare interface Window {
2 | // extend the window
3 | }
4 |
5 | // with vite-plugin-vue-markdown, markdown files can be treated as Vue components
6 | declare module '*.md' {
7 | import { type DefineComponent } from 'vue'
8 | const component: DefineComponent<{}, {}, any>
9 | export default component
10 | }
11 |
12 | declare module '*.vue' {
13 | import { type DefineComponent } from 'vue'
14 | const component: DefineComponent<{}, {}, any>
15 | export default component
16 | }
17 |
--------------------------------------------------------------------------------
/src/styles/main.css:
--------------------------------------------------------------------------------
1 | @import './markdown.css';
2 |
3 | html,
4 | body,
5 | #app {
6 | height: 100%;
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 | html.dark {
12 | background: #121212;
13 | }
14 |
15 | #nprogress {
16 | pointer-events: none;
17 | }
18 |
19 | #nprogress .bar {
20 | background: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
21 | opacity: 0.75;
22 | position: fixed;
23 | z-index: 1031;
24 | top: 0;
25 | left: 0;
26 | width: 100%;
27 | height: 2px;
28 | }
29 |
30 | .page-fade-enter-active,
31 | .page-fade-leave-active {
32 | transition: opacity 0.3s ease;
33 | }
34 |
35 | .page-fade-enter-from,
36 | .page-fade-leave-to {
37 | opacity: 0;
38 | }
39 |
40 |
41 | /* Color Mode transition */
42 | ::view-transition-old(root),
43 | ::view-transition-new(root) {
44 | animation: none;
45 | mix-blend-mode: normal;
46 | }
47 | ::view-transition-old(root) {
48 | z-index: 1;
49 | }
50 | ::view-transition-new(root) {
51 | z-index: 2147483646;
52 | }
53 | .dark::view-transition-old(root) {
54 | z-index: 2147483646;
55 | }
56 | .dark::view-transition-new(root) {
57 | z-index: 1;
58 | }
59 |
--------------------------------------------------------------------------------
/src/styles/markdown.css:
--------------------------------------------------------------------------------
1 | .prose pre:not(.shiki) {
2 | padding: 0;
3 | }
4 |
5 | .prose .shiki {
6 | font-family: 'DM Mono', monospace;
7 | font-size: 1.2em;
8 | line-height: 1.4;
9 | }
10 |
11 | .prose img {
12 | width: 100%;
13 | }
14 |
15 | .shiki-light {
16 | background: #f8f8f8 !important;
17 | }
18 | .shiki-dark {
19 | background: #0e0e0e !important;
20 | }
21 |
22 | html.dark .shiki-light {
23 | display: none;
24 | }
25 |
26 | html:not(.dark) .shiki-dark {
27 | display: none;
28 | }
29 |
--------------------------------------------------------------------------------
/src/styles/prism.css:
--------------------------------------------------------------------------------
1 |
2 | :root {
3 | --prism-marker-opacity: .6;
4 | --prism-marker-color: var(--code-text-color);
5 | --prism-line-height: var(--code-line-height)
6 | }
7 |
8 | html:not(.dark) {
9 | --prism-builtin: #3182bd;
10 | --prism-comment: #848486;
11 | --prism-deleted: #3182bd;
12 | --prism-function: #6196cc;
13 | --prism-boolean: #c25205;
14 | --prism-number: #c25205;
15 | --prism-property: #717c11;
16 | --prism-punctuation: #a8a9cc;
17 | --prism-keyword: #c792ea;
18 | --prism-variable: #0b8235;
19 | --prism-url-decoration: #67cdcc;
20 | --prism-symbol: green;
21 | --prism-selector: #0b8235
22 | }
23 |
24 | html.dark {
25 | --prism-scheme: dark;
26 | --prism-foreground: #a6accd;
27 | --prism-background: #181818;
28 | --prism-comment: #758575;
29 | --prism-string: #c3e88d;
30 | --prism-literal: #429988;
31 | --prism-keyword: #89ddff;
32 | --prism-boolean: #6394bf;
33 | --prism-number: #6394bf;
34 | --prism-variable: #c2b36e;
35 | --prism-function: #82aaff;
36 | --prism-deleted: #bc6066;
37 | --prism-class: #54b1bf;
38 | --prism-builtin: #3375b9;
39 | --prism-property: #c792ea;
40 | --prism-namespace: #db889a;
41 | --prism-punctuation: #89ddff;
42 | --prism-decorator: #bd8f8f;
43 | --prism-regex: #ab5e3f;
44 | --prism-json-property: #6b8b9e;
45 | --prism-line-number: #888888;
46 | --prism-line-number-gutter: #eeeeee;
47 | --prism-line-highlight-background: #444444;
48 | --prism-selection-background: #444444;
49 | --prism-inline-background: #2d2d2d
50 | }
51 |
52 | code {
53 | margin: 0;
54 | border-radius: 4px;
55 | padding: .15rem .5rem;
56 | font-family: var(--code-font-family);
57 | font-size: var(--code-font-size);
58 | color: var(--code-text-color);
59 | line-height: var(--code-line-height);
60 | background-color: var(--code-bg-color)
61 | }
62 |
63 | pre code {
64 | background-color: transparent
65 | }
66 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { type ViteSSGContext } from 'vite-ssg'
2 |
3 | export type UserModule = (ctx: ViteSSGContext) => void
4 |
--------------------------------------------------------------------------------
/src/utils/highlight.ts:
--------------------------------------------------------------------------------
1 | import * as shiki from 'shiki'
2 | import { isDark } from '~/composables/dark'
3 |
4 | shiki.setCDN('/node_modules/shiki/languages/vue.tmLanguage.json')
5 |
6 | const highlighter = await shiki
7 | .getHighlighter({
8 |
9 | })
10 |
11 | export function highlight(str: string, lang: string) {
12 | const code = highlighter.codeToHtml(str, { lang }, (isDark.value ? 'vitesse-light' : 'vitesse-dark'))
13 | return code
14 | }
15 |
--------------------------------------------------------------------------------
/test/__snapshots__/component.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1
2 |
3 | exports[`Counter.vue > should render 1`] = `"10
"`;
4 |
--------------------------------------------------------------------------------
/test/basic.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | describe('tests', () => {
4 | it('should works', () => {
5 | expect(1 + 1).toEqual(2)
6 | })
7 | })
8 |
--------------------------------------------------------------------------------
/test/component.test.ts:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import { describe, expect, it } from 'vitest'
3 | import Counter from '../src/components/Counter.vue'
4 |
5 | describe('Counter.vue', () => {
6 | it('should render', () => {
7 | const wrapper = mount(Counter, { props: { initial: 10 } })
8 | expect(wrapper.text()).toContain('10')
9 | expect(wrapper.html()).toMatchSnapshot()
10 | })
11 |
12 | it('should be interactive', async () => {
13 | const wrapper = mount(Counter, { props: { initial: 0 } })
14 | expect(wrapper.text()).toContain('0')
15 |
16 | expect(wrapper.find('.inc').exists()).toBe(true)
17 |
18 | expect(wrapper.find('.dec').exists()).toBe(true)
19 |
20 | await wrapper.get('.inc').trigger('click')
21 |
22 | expect(wrapper.text()).toContain('1')
23 |
24 | await wrapper.get('.dec').trigger('click')
25 |
26 | expect(wrapper.text()).toContain('0')
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "module": "ESNext",
5 | "target": "ESNext",
6 | "lib": ["DOM", "ESNext"],
7 | "strict": true,
8 | "esModuleInterop": true,
9 | "jsx": "preserve",
10 | "skipLibCheck": true,
11 | "moduleResolution": "node",
12 | "resolveJsonModule": true,
13 | "noUnusedLocals": true,
14 | "strictNullChecks": true,
15 | "allowJs": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "types": [
18 | "vitest",
19 | "vite/client",
20 | "vue/ref-macros",
21 | "vite-plugin-pages/client",
22 | "vite-plugin-vue-layouts/client"
23 | ],
24 | "paths": {
25 | "~/*": ["src/*"]
26 | }
27 | },
28 | "exclude": ["dist", "node_modules", "cypress"]
29 | }
30 |
--------------------------------------------------------------------------------
/unocss.config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | defineConfig,
3 | presetAttributify,
4 | presetIcons,
5 | presetTypography,
6 | presetUno,
7 | presetWebFonts,
8 | transformerDirectives,
9 | transformerVariantGroup,
10 | } from 'unocss'
11 |
12 | export default defineConfig({
13 | shortcuts: [
14 | ['btn', 'px-4 py-1 rounded inline-block bg-cyan-700 text-white cursor-pointer hover:bg-cyan-600 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
15 | ['icon-btn', 'inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-cyan-600 dark:hover:text-cyan-900'],
16 | ['card', 'border border-gray-5/50 shadow p-6 rounded'],
17 | ],
18 | presets: [
19 | presetUno(),
20 | presetAttributify(),
21 | presetIcons({
22 | scale: 1.2,
23 | warn: true,
24 | }),
25 | presetTypography(),
26 | presetWebFonts({
27 | fonts: {
28 | sans: 'DM Sans',
29 | serif: 'DM Serif Display',
30 | mono: 'DM Mono',
31 | },
32 | }),
33 | ],
34 | transformers: [
35 | transformerDirectives(),
36 | transformerVariantGroup(),
37 | ],
38 | safelist: 'prose prose-sm m-auto text-left'.split(' '),
39 | })
40 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import { defineConfig } from 'vite'
3 | import Vue from '@vitejs/plugin-vue'
4 | import Pages from 'vite-plugin-pages'
5 | import generateSitemap from 'vite-ssg-sitemap'
6 | import Layouts from 'vite-plugin-vue-layouts'
7 | import Components from 'unplugin-vue-components/vite'
8 | import AutoImport from 'unplugin-auto-import/vite'
9 | import VueMacros from 'unplugin-vue-macros/vite'
10 | import Markdown from 'vite-plugin-vue-markdown'
11 | import { VitePWA } from 'vite-plugin-pwa'
12 | import VueI18n from '@intlify/unplugin-vue-i18n/vite'
13 | import VueDevTools from 'vite-plugin-vue-devtools'
14 | import LinkAttributes from 'markdown-it-link-attributes'
15 | import Unocss from 'unocss/vite'
16 | import Shiki from 'markdown-it-shiki'
17 |
18 | export default defineConfig({
19 | resolve: {
20 | alias: {
21 | '~/': `${path.resolve(__dirname, 'src')}/`,
22 | },
23 | },
24 |
25 | plugins: [
26 | VueMacros({
27 | plugins: {
28 | vue: Vue({
29 | include: [/\.vue$/, /\.md$/],
30 | }),
31 | },
32 | }),
33 |
34 | // https://github.com/hannoeru/vite-plugin-pages
35 | Pages({
36 | extensions: ['vue', 'md'],
37 | }),
38 |
39 | // https://github.com/JohnCampionJr/vite-plugin-vue-layouts
40 | Layouts(),
41 |
42 | // https://github.com/antfu/unplugin-auto-import
43 | AutoImport({
44 | imports: [
45 | 'vue',
46 | 'vue-router',
47 | 'vue-i18n',
48 | '@vueuse/head',
49 | '@vueuse/core',
50 | ],
51 | dts: 'src/auto-imports.d.ts',
52 | dirs: [
53 | 'src/composables',
54 | ],
55 | vueTemplate: true,
56 | }),
57 |
58 | // https://github.com/antfu/unplugin-vue-components
59 | Components({
60 | // allow auto load markdown components under `./src/components/`
61 | extensions: ['vue', 'md'],
62 | // allow auto import and register components used in markdown
63 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
64 | dts: 'src/components.d.ts',
65 | }),
66 |
67 | // https://github.com/antfu/unocss
68 | // see unocss.config.ts for config
69 | Unocss(),
70 |
71 | // https://github.com/antfu/vite-plugin-vue-markdown
72 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
73 | Markdown({
74 | wrapperClasses: 'prose prose-sm m-auto text-left',
75 | headEnabled: true,
76 | markdownItSetup(md) {
77 | // https://prismjs.com/
78 | md.use(Shiki, {
79 | theme: {
80 | light: 'vitesse-light',
81 | dark: 'vitesse-dark',
82 | },
83 | })
84 | md.use(LinkAttributes, {
85 | matcher: (link: string) => /^https?:\/\//.test(link),
86 | attrs: {
87 | target: '_blank',
88 | rel: 'noopener',
89 | },
90 | })
91 | },
92 | }),
93 |
94 | // https://github.com/antfu/vite-plugin-pwa
95 | VitePWA({
96 | registerType: 'autoUpdate',
97 | includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'],
98 | manifest: {
99 | name: 'Example',
100 | short_name: 'Example',
101 | theme_color: '#ffffff',
102 | icons: [
103 | {
104 | src: '/pwa-192x192.png',
105 | sizes: '192x192',
106 | type: 'image/png',
107 | },
108 | {
109 | src: '/pwa-512x512.png',
110 | sizes: '512x512',
111 | type: 'image/png',
112 | },
113 | {
114 | src: '/pwa-512x512.png',
115 | sizes: '512x512',
116 | type: 'image/png',
117 | purpose: 'any maskable',
118 | },
119 | ],
120 | },
121 | }),
122 |
123 | // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
124 | VueI18n({
125 | runtimeOnly: true,
126 | compositionOnly: true,
127 | fullInstall: true,
128 | include: [path.resolve(__dirname, 'locales/**')],
129 | }),
130 |
131 | // https://github.com/webfansplz/vite-plugin-vue-devtools
132 | VueDevTools(),
133 | ],
134 |
135 | // https://github.com/vitest-dev/vitest
136 | test: {
137 | include: ['test/**/*.test.ts'],
138 | environment: 'jsdom',
139 | deps: {
140 | inline: ['@vue', '@vueuse', 'vue-demi'],
141 | },
142 | },
143 |
144 | // https://github.com/antfu/vite-ssg
145 | ssgOptions: {
146 | script: 'async',
147 | formatting: 'minify',
148 | crittersOptions: {
149 | reduceInlineStyles: false,
150 | },
151 | onFinished() {
152 | generateSitemap()
153 | },
154 | },
155 | ssr: {
156 | // TODO: workaround until they support native ESM
157 | noExternal: ['workbox-window', /vue-i18n/],
158 | },
159 | })
160 |
--------------------------------------------------------------------------------