feat: first commit

This commit is contained in:
Mrxtyyp 2024-04-28 15:30:35 +08:00
parent b4c128a9ef
commit 5468b1186d
969 changed files with 116813 additions and 1 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
node_modules/
dist/
.vscode/

5
.env Normal file
View File

@ -0,0 +1,5 @@
# Configure the name of the global project
VITE_GLOB_APP_TITLE = EAIRP
# Need to underline here
VITE_GLOB_APP_SHORT_NAME=WanSen_ERP

23
.env.analyze Normal file
View File

@ -0,0 +1,23 @@
# Whether to open mock
VITE_USE_MOCK = false
# public path
VITE_PUBLIC_PATH = /
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
# Basic interface address SPA
VITE_GLOB_API_URL=/erp-api
# File upload address optional
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=/upload
# Interface prefix
VITE_GLOB_API_URL_PREFIX=
VITE_ENABLE_ANALYZE = true

16
.env.development Normal file
View File

@ -0,0 +1,16 @@
# Whether to open mock
VITE_USE_MOCK = false
# public path
VITE_PUBLIC_PATH = /
VITE_BUILD_COMPRESS = 'none'
# Delete console
VITE_DROP_CONSOLE = false
# Basic interface address SPA
VITE_GLOB_API_URL=/erp-api
# Interface prefix
VITE_GLOB_API_URL_PREFIX=

22
.env.docker Normal file
View File

@ -0,0 +1,22 @@
# Whether to open mock
VITE_USE_MOCK = false
# public path
VITE_PUBLIC_PATH = /
# timeout(seconds)
VITE_TIMEOUT = 15
# Delete console
VITE_DROP_CONSOLE = true
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
VITE_GLOB_API_URL='api_base_url'
# File upload address optional
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=/files/upload
# Interface prefix
VITE_GLOB_API_URL_PREFIX=

25
.env.production Normal file
View File

@ -0,0 +1,25 @@
# Whether to open mock
VITE_USE_MOCK = false
# public path
VITE_PUBLIC_PATH = /
VITE_BUILD_COMPRESS = 'none'
# Delete console
VITE_DROP_CONSOLE = false
# Basic interface address SPA
VITE_GLOB_API_URL=/erp-api
# Interface prefix
VITE_GLOB_API_URL_PREFIX=
# Whether to enable image compression
VITE_USE_IMAGEMIN= false
# use pwa
VITE_USE_PWA = false
# Is it compatible with older browsers
VITE_LEGACY = false

15
.eslintignore Normal file
View File

@ -0,0 +1,15 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.local
/bin
/docker
/internal/**/dist

15
.eslintrc.js Normal file
View File

@ -0,0 +1,15 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

110
.gitignore vendored Normal file
View File

@ -0,0 +1,110 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# vscode private configuration file
.vscode/redis.json
.idea
.vscode

7
.npmrc Normal file
View File

@ -0,0 +1,7 @@
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=lint-staged
public-hoist-pattern[]=*stylelint*
public-hoist-pattern[]=@commitlint/cli
registry=https://registry.npmmirror.com

17
.prettierignore Normal file
View File

@ -0,0 +1,17 @@
dist
.local
.output.js
node_modules
**/*.svg
**/*.sh
public
.npmrc
internal/**/dist
deploy
docs
docker
mock

20
.prettierrc.js Normal file
View File

@ -0,0 +1,20 @@
module.exports = {
printWidth: 100,
semi: true,
vueIndentScriptAndStyle: true,
singleQuote: true,
trailingComma: 'all',
proseWrap: 'never',
// Ignore space sensitivity in HTML tags
htmlWhitespaceSensitivity: 'ignore',
endOfLine: 'auto',
plugins: ['prettier-plugin-packagejson'],
overrides: [
{
files: '.*rc',
options: {
parser: 'json',
},
},
],
};

4
.stylelintrc.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ['@vben/stylelint-config'],
};

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM node:18.18.0 as build-stage
MAINTAINER WanSen AI<team@wansenai.com>
WORKDIR app
COPY . ./
ENV NODE_OPTIONS --max-old-space-size=16384
RUN npm install pnpm -g
RUN pnpm install --frozen-lockfile
RUN pnpm build:docker
RUN echo "Build Success"
FROM nginx:1.23.4 as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html/dist
COPY --from=build-stage /app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD sed -i "s|api_base_url|$API_BASE_URL|g" /usr/share/nginx/html/dist/assets/index.js && \
sed -i "s|api_base_url|$API_BASE_URL|g" /usr/share/nginx/html/dist/_app.config.js && \
nginx -g 'daemon off;'
RUN echo "Run Success"

113
README.md Normal file
View File

@ -0,0 +1,113 @@
<p align="center">
<!-- <a href="https://www.antdv.com/">
<img width="350" src="/images/wansenai-logo.png">
</a> -->
</p>
<h1 align="center">
<a href="#" target="_blank">Enterprise AI Resource Planning Web</a>
</h1>
<div align="center">
<!-- nodejs build status-->
<a href="https://github.com/wansenai/wansen-erp/blob/master/.github/workflows/node.js.yml">
<img src="https://img.shields.io/github/actions/workflow/status/wansenai/wansen-erp/node.js.yml"
alt="Crates.io version" />
</a>
<a href="">
<img src="https://img.shields.io/github/repo-size/wansenai/wansen-erp"/>
</a>
<a href="">
<img src="https://img.shields.io/github/last-commit/wansenai/wansen-erp"/>
</a>
</div>
<div align="center">
<strong>Next generation artificial intelligent ERP system.</strong>
</div>
<br />
## Project
[English](README.md) | [简体中文](./README-zh_CN.md)
### Quick Start
You can directly use the Docker pull image for quick startup. Here are the commands to pull the front-end image
### Pull images
```shell
docker pull wansenai/eairp-web:2.0.3
```
### Run Server
Please note the `API_BASE_URL` parameter, this is the address mapped by the back-end interface.
If you are deploying on your server, modify the localhost address here to your server IP.
```shell
docker run --name eairp-web -d -p 3000:80 -e API_BASE_URL=http://localhost:8080/erp-api wansenai/eairp-web:2.0.3
```
If you want to deploy the API using Docker, you can also pull the API image
```shell
docker pull wansenai/eairp:2.0.3
```
And run API services
```shell
docker run --name eairp -d -p 9998:8088 wansenai/eairp:2.0.3
```
### Online preview
- [eairp preview / 在线预览](https://erp.wansen.cloud/)
- test account (测试账号): wansen
- test password (测试密码): 123456
- Some functional modules are being developed and improved, please refer to our [to-do list](https://github.com/wansenai/eairp-web/issues/41). It's not easy to generate electricity with love.
- If this project is helpful to you, please click on Star. Thank you.
一些功能模块正在开发和改进中, 请参阅我们的[开发计划](https://github.com/wansenai/eairp-web/issues/42), 用爱发电很不容易, 如果这个项目对你有帮助, 请点击Star非常感谢.
### Repository code
- [wansen-erp](https://github.com/wansenai/wansen-erp) - **Current version**
- [wansen-erp-core](https://github.com/wansenai/wansen-erp-core) - **Current API version**
## Browser support
The `Chrome 80+` browser is recommended for local development
Support modern browsers, not IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## System screenshot (only part)
![](images/login-page-en.png)
![](images/home-page-zh.png)
![](images/user-manage-zh.png)
![](images/add-menu-zh.png)
![](images/role-permission-zh.png)
## Install and use
- Get the project code
```bash
git clone https://github.com/wansenai/wansen-erp.git
```
- Installation dependencies
```bash
cd wansen-erp
pnpm install
```
- run
```bash
pnpm serve
```
- build
```bash
pnpm build
```

18
deploy/default.conf Normal file
View File

@ -0,0 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /erp-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

8
docker/Dockerfile Normal file
View File

@ -0,0 +1,8 @@
FROM nginx:1.23.4-alpine
COPY dist/ /usr/share/nginx/html/
COPY ../deploy/default.conf /etc/nginx/conf.d/
LABEL MAINTAINER="team@wansenai.com"
EXPOSE 80

25
docker/Makefile Normal file
View File

@ -0,0 +1,25 @@
VERSION=$(shell git describe --tags --always)
.PHONY: docker
docker: # Compile and build the docker | 编译并构建 docker 镜像
pnpm install
pnpm build
docker build -f Dockerfile -t ${DOCKER_USERNAME}/backend-ui:${VERSION} .
.PHONY: docker-not-build
docker-not-build: # Build the docker without compiling | 不编译直接构建镜像
docker build -f Dockerfile -t ${DOCKER_USERNAME}/backend-ui:${VERSION} .
.PHONY: publish-docker
publish-docker: # Publish the docker | 发布镜像
echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin https://${REPO}
docker push ${DOCKER_USERNAME}/backend-ui:${VERSION}
.PHONY: run-docker
run-docker: # Run the docker image | 运行 docker 镜像
docker volume create backendui
docker run -d --name ${DOCKER_USERNAME}/backend-ui:${VERSION} -p 80:80 -v backendui:/etc/nginx --network docker-compose_simple-admin ${DOCKER_USERNAME}/backendui:${VERSION}
.PHONY: help
help: # Show help | 显示帮助
@grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done

24
docs/README_ZH.md Normal file
View File

@ -0,0 +1,24 @@
# WanSen ERP UI
## 项目设置
```
npm install -g pnpm
pnpm install
```
### 用于打包生产环境的编译程序
```
pnpm build
pnpm preview
```
### 查看打包后的程序
```
pnpm preview:dist
```
### Vue-Cli 自定义配置
See [Configuration Reference](https://cli.vuejs.org/config/).

BIN
docs/template/会员信息模板.xlsx vendored Normal file

Binary file not shown.

BIN
docs/template/供应商模板.xlsx vendored Normal file

Binary file not shown.

BIN
docs/template/客户信息模板.xlsx vendored Normal file

Binary file not shown.

BIN
images/add-menu-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
images/home-page-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
images/login-page-en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

BIN
images/register-page-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
images/user-manage-zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
images/user-mgt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

BIN
images/wansenai-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

153
index.html Normal file
View File

@ -0,0 +1,153 @@
<!DOCTYPE html>
<html lang="en" id="htmlRoot">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<title><%= VITE_GLOB_APP_TITLE %></title>
<link rel="icon" href="/favicon.ico" />
</head>
<body>
<div id="app">
<style>
html[data-theme='dark'] .app-loading {
background-color: #2c344a;
}
html[data-theme='dark'] .app-loading .app-loading-title {
color: rgb(255 255 255 / 85%);
}
.app-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #f4f7f9;
}
.app-loading .app-loading-wrap {
display: flex;
position: absolute;
top: 50%;
left: 50%;
flex-direction: column;
align-items: center;
justify-content: center;
transform: translate3d(-50%, -50%, 0);
}
.app-loading .dots {
display: flex;
align-items: center;
justify-content: center;
padding: 98px;
}
.app-loading .app-loading-title {
display: flex;
align-items: center;
justify-content: center;
margin-top: 30px;
color: rgb(0 0 0 / 85%);
font-size: 30px;
}
.app-loading .app-loading-logo {
display: block;
width: 90px;
margin: 0 auto;
margin-bottom: 20px;
}
.dot {
display: inline-block;
position: relative;
box-sizing: border-box;
width: 48px;
height: 48px;
margin-top: 30px;
transform: rotate(45deg);
animation: ant-rotate 1.2s infinite linear;
font-size: 32px;
}
.dot i {
display: block;
position: absolute;
width: 20px;
height: 20px;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: ant-spin-move 1s infinite linear alternate;
border-radius: 100%;
opacity: 0.3;
background-color: #0065cc;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
animation-delay: 1.2s;
}
@keyframes ant-rotate {
to {
transform: rotate(405deg);
}
}
@keyframes ant-rotate {
to {
transform: rotate(405deg);
}
}
@keyframes ant-spin-move {
to {
opacity: 1;
}
}
@keyframes ant-spin-move {
to {
opacity: 1;
}
}
</style>
<div class="app-loading">
<div class="app-loading-wrap">
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
<div class="app-loading-dots">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
<div class="app-loading-title"><%= VITE_GLOB_APP_TITLE %></div>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

BIN
internal/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
*.sh
node_modules
dist

View File

@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
entries: ['src/index'],
declaration: true,
rollup: {
emitCJS: true,
},
});

View File

@ -0,0 +1,39 @@
{
"name": "@vben/stylelint-config",
"version": "1.0.0",
"private": true,
"license": "MIT",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"clean": "pnpm rimraf node_modules dist",
"stub": "pnpm unbuild --stub"
},
"devDependencies": {
"postcss": "^8.4.29",
"postcss-html": "^1.5.0",
"postcss-less": "^6.0.0",
"postcss-scss": "^4.0.7",
"prettier": "^2.8.8",
"stylelint": "^15.10.3",
"stylelint-config-property-sort-order-smacss": "^9.1.0",
"stylelint-config-recommended": "^12.0.0",
"stylelint-config-recommended-scss": "^11.0.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^33.0.0",
"stylelint-config-standard-scss": "^9.0.0",
"stylelint-order": "^6.0.3",
"stylelint-prettier": "^3.0.0"
}
}

View File

@ -0,0 +1,91 @@
export default {
extends: ['stylelint-config-standard', 'stylelint-config-property-sort-order-smacss'],
plugins: ['stylelint-order', 'stylelint-prettier'],
// customSyntax: 'postcss-html',
overrides: [
{
files: ['**/*.(css|html|vue)'],
customSyntax: 'postcss-html',
},
{
files: ['*.less', '**/*.less'],
customSyntax: 'postcss-less',
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
},
{
files: ['*.scss', '**/*.scss'],
customSyntax: 'postcss-scss',
extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
rule: {
'scss/percent-placeholder-pattern': null,
},
},
],
rules: {
'selector-not-notation': null,
'import-notation': null,
'function-no-unknown': null,
'selector-class-pattern': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'deep'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'if',
'each',
'include',
'mixin',
'extend',
],
},
],
'no-empty-source': null,
'string-quotes': null,
'named-grid-areas-no-invalid': null,
'no-descending-specificity': null,
'font-family-no-missing-generic-family-keyword': null,
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested'],
},
],
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
'order/order': [
[
'dollar-variables',
'custom-properties',
'at-rules',
'declarations',
{
type: 'at-rule',
name: 'supports',
},
{
type: 'at-rule',
name: 'media',
},
'rules',
],
{ severity: 'error' },
],
},
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
};

View File

@ -0,0 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/node.json",
"include": ["src"]
}

View File

@ -0,0 +1,4 @@
*.sh
node_modules
dist

View File

@ -0,0 +1,27 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Base",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"declaration": true,
"noImplicitOverride": true,
"noUnusedLocals": true,
"esModuleInterop": true,
"useUnknownInCatchVariables": false,
"composite": false,
"declarationMap": false,
"forceConsistentCasingInFileNames": true,
"inlineSources": false,
"isolatedModules": true,
"skipLibCheck": true,
"noUnusedParameters": false,
"preserveWatchOutput": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"removeComments": true
},
"exclude": ["**/node_modules/**", "**/dist/**"]
}

View File

@ -0,0 +1,18 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node Server Config",
"extends": "./base.json",
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": false,
"esModuleInterop": true,
"outDir": "./dist",
"baseUrl": "./"
},
"exclude": ["node_modules"]
}

View File

@ -0,0 +1,12 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node Config",
"extends": "./base.json",
"compilerOptions": {
"lib": ["ESNext"],
"noImplicitAny": true,
"sourceMap": true,
"noEmit": true,
"baseUrl": "./"
}
}

View File

@ -0,0 +1,17 @@
{
"name": "@vben/ts-config",
"version": "1.0.0",
"private": true,
"license": "MIT",
"files": [
"base.json",
"node.json",
"vue-app.json",
"node-server.json"
],
"dependencies": {
"@types/node": "^18.17.12",
"unplugin-vue-define-options": "^1.3.17",
"vite": "^4.4.9"
}
}

View File

@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Vue Application",
"extends": "./base.json",
"compilerOptions": {
"jsx": "preserve",
"lib": ["ESNext", "DOM"],
"noImplicitAny": false
}
}

View File

@ -0,0 +1,4 @@
*.sh
node_modules
dist

View File

@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
entries: ['src/index'],
declaration: true,
rollup: {
emitCJS: true,
},
});

View File

@ -0,0 +1,50 @@
{
"name": "@vben/vite-config",
"version": "1.0.0",
"private": true,
"license": "MIT",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"clean": "pnpm rimraf .turbo node_modules dist",
"lint": "pnpm eslint .",
"stub": "pnpm unbuild --stub"
},
"dependencies": {
"@ant-design/colors": "^7.0.0",
"vite": "^4.4.9"
},
"devDependencies": {
"@types/fs-extra": "^11.0.1",
"@vitejs/plugin-vue": "^4.3.4",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"ant-design-vue": "^4.0.6",
"dayjs": "^1.11.9",
"dotenv": "^16.3.1",
"fs-extra": "^11.1.1",
"less": "^4.2.0",
"picocolors": "^1.0.0",
"pkg-types": "^1.0.3",
"rollup-plugin-visualizer": "^5.9.2",
"sass": "^1.66.1",
"unocss": "^0.55.3",
"unplugin-vue-define-options": "^1.3.17",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-dts": "^2.3.0",
"vite-plugin-html": "^3.2.0",
"vite-plugin-mock": "^3.0.0",
"vite-plugin-purge-icons": "^0.9.2",
"vite-plugin-svg-icons": "^2.0.1"
}
}

View File

@ -0,0 +1,115 @@
import { resolve } from 'node:path';
import dayjs from 'dayjs';
import { readPackageJSON } from 'pkg-types';
import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite';
import { createPlugins } from '../plugins';
import { generateModifyVars } from '../utils/modifyVars';
import { commonConfig } from './common';
interface DefineOptions {
overrides?: UserConfig;
options?: {
//
};
}
function defineApplicationConfig(defineOptions: DefineOptions = {}) {
const { overrides = {} } = defineOptions;
return defineConfig(async ({ command, mode }) => {
const root = process.cwd();
const isBuild = command === 'build';
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(mode, root);
const defineData = await createDefineData(root);
const plugins = await createPlugins({
isBuild,
root,
enableAnalyze: VITE_ENABLE_ANALYZE === 'true',
enableMock: VITE_USE_MOCK === 'true',
compress: VITE_BUILD_COMPRESS,
});
const pathResolve = (pathname: string) => resolve(root, '.', pathname);
const applicationConfig: UserConfig = {
resolve: {
alias: [
{
find: 'vue-i18n',
replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
},
// /@/xxxx => src/xxxx
{
find: /\/@\//,
replacement: pathResolve('src') + '/',
},
// /#/xxxx => types/xxxx
{
find: /\/#\//,
replacement: pathResolve('types') + '/',
},
// @/xxxx => src/xxxx
{
find: /@\//,
replacement: pathResolve('src') + '/',
},
// #/xxxx => types/xxxx
{
find: /#\//,
replacement: pathResolve('types') + '/',
},
],
},
define: defineData,
build: {
target: 'es2015',
cssTarget: 'chrome80',
rollupOptions: {
output: {
// 入口文件名
entryFileNames: 'assets/[name].js',
manualChunks: {
vue: ['vue', 'pinia', 'vue-router'],
antd: ['ant-design-vue', '@ant-design/icons-vue'],
},
},
},
},
css: {
preprocessorOptions: {
less: {
modifyVars: generateModifyVars(),
javascriptEnabled: true,
},
},
},
plugins,
};
const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig);
return mergeConfig(mergedConfig, overrides);
});
}
async function createDefineData(root: string) {
try {
const pkgJson = await readPackageJSON(root);
const { dependencies, devDependencies, name, version } = pkgJson;
const __APP_INFO__ = {
pkg: { dependencies, devDependencies, name, version },
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
};
return {
__APP_INFO__: JSON.stringify(__APP_INFO__),
};
} catch (error) {
return {};
}
}
export { defineApplicationConfig };

View File

@ -0,0 +1,46 @@
import {
presetAttributify,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives,
transformerVariantGroup,
} from 'unocss';
import UnoCSS from 'unocss/vite';
import { type UserConfig } from 'vite';
const commonConfig: (mode: string) => UserConfig = (mode) => ({
server: {
host: true,
},
esbuild: {
drop: mode === 'production' ? ['console', 'debugger'] : [],
},
build: {
reportCompressedSize: false,
chunkSizeWarningLimit: 1500,
rollupOptions: {
// TODO: Prevent memory overflow
maxParallelFileOps: 3,
},
},
plugins: [
UnoCSS({
presets: [
presetUno(),
presetAttributify(),
presetIcons(),
presetTypography(),
presetWebFonts({
fonts: {
// ...
},
}),
],
transformers: [transformerDirectives(), transformerVariantGroup()],
}),
],
});
export { commonConfig };

View File

@ -0,0 +1,42 @@
import { readPackageJSON } from 'pkg-types';
import { defineConfig, mergeConfig, type UserConfig } from 'vite';
import dts from 'vite-plugin-dts';
import { commonConfig } from './common';
interface DefineOptions {
overrides?: UserConfig;
options?: {
//
};
}
function definePackageConfig(defineOptions: DefineOptions = {}) {
const { overrides = {} } = defineOptions;
const root = process.cwd();
return defineConfig(async ({ mode }) => {
const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root);
const packageConfig: UserConfig = {
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.mjs',
},
rollupOptions: {
external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)],
},
},
plugins: [
dts({
logLevel: 'error',
}),
],
};
const mergedConfig = mergeConfig(commonConfig(mode), packageConfig);
return mergeConfig(mergedConfig, overrides);
});
}
export { definePackageConfig };

View File

@ -0,0 +1,2 @@
export * from './config/application';
export * from './config/package';

View File

@ -0,0 +1,96 @@
import colors from 'picocolors';
import { readPackageJSON } from 'pkg-types';
import { type PluginOption } from 'vite';
import { getEnvConfig } from '../utils/env';
import { createContentHash } from '../utils/hash';
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
const PLUGIN_NAME = 'app-config';
async function createAppConfigPlugin({
root,
isBuild,
}: {
root: string;
isBuild: boolean;
}): Promise<PluginOption> {
let publicPath: string;
let source: string;
if (!isBuild) {
return {
name: PLUGIN_NAME,
};
}
const { version = '' } = await readPackageJSON(root);
return {
name: PLUGIN_NAME,
async configResolved(_config) {
let appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '';
appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_');
publicPath = _config.base;
source = await getConfigSource(appTitle);
},
async transformIndexHtml(html) {
publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
const appConfigSrc = `${
publicPath || '/'
}${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}}`;
return {
html,
tags: [
{
tag: 'script',
attrs: {
src: appConfigSrc,
},
},
],
};
},
async generateBundle() {
try {
this.emitFile({
type: 'asset',
fileName: GLOBAL_CONFIG_FILE_NAME,
source,
});
console.log(colors.cyan(`✨configuration file is build successfully!`));
} catch (error) {
console.log(
colors.red('configuration file configuration file failed to package:\n' + error),
);
}
},
};
}
/**
* Get the configuration file variable name
* @param env
*/
const getVariableName = (title: string) => {
return `__PRODUCTION__${title || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
};
async function getConfigSource(appTitle: string) {
const config = await getEnvConfig();
const variableName = getVariableName(appTitle);
const windowVariable = `window.${variableName}`;
// Ensure that the variable will not be modified
let source = `${windowVariable}=${JSON.stringify(config)};`;
source += `
Object.freeze(${windowVariable});
Object.defineProperty(window, "${variableName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g, '');
return source;
}
export { createAppConfigPlugin };

View File

@ -0,0 +1,38 @@
/**
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
* https://github.com/anncwb/vite-plugin-compression
*/
import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin({
compress,
deleteOriginFile = false,
}: {
compress: string;
deleteOriginFile?: boolean;
}): PluginOption[] {
const compressList = compress.split(',');
const plugins: PluginOption[] = [];
if (compressList.includes('gzip')) {
plugins.push(
compressPlugin({
ext: '.gz',
deleteOriginFile,
}),
);
}
if (compressList.includes('brotli')) {
plugins.push(
compressPlugin({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile,
}),
);
}
return plugins;
}

View File

@ -0,0 +1,13 @@
/**
* Plugin to minimize and use ejs template syntax in index.html.
* https://github.com/anncwb/vite-plugin-html
*/
import type { PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) {
const htmlPlugin: PluginOption[] = createHtmlPlugin({
minify: isBuild,
});
return htmlPlugin;
}

View File

@ -0,0 +1,61 @@
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
// @ts-ignore: type unless
import DefineOptions from 'unplugin-vue-define-options/vite';
import { type PluginOption } from 'vite';
import purgeIcons from 'vite-plugin-purge-icons';
import { createAppConfigPlugin } from './appConfig';
import { configCompressPlugin } from './compress';
import { configHtmlPlugin } from './html';
import { configMockPlugin } from './mock';
import { configSvgIconsPlugin } from './svgSprite';
import { configVisualizerConfig } from './visualizer';
interface Options {
isBuild: boolean;
root: string;
compress: string;
enableMock?: boolean;
enableAnalyze?: boolean;
}
async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) {
const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx(), DefineOptions()];
const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
vitePlugins.push(appConfigPlugin);
// vite-plugin-html
vitePlugins.push(configHtmlPlugin({ isBuild }));
// vite-plugin-svg-icons
vitePlugins.push(configSvgIconsPlugin({ isBuild }));
// vite-plugin-purge-icons
vitePlugins.push(purgeIcons());
// The following plugins only work in the production environment
if (isBuild) {
// rollup-plugin-gzip
vitePlugins.push(
configCompressPlugin({
compress,
}),
);
}
// rollup-plugin-visualizer
if (enableAnalyze) {
vitePlugins.push(configVisualizerConfig());
}
// vite-plugin-mock
if (enableMock) {
vitePlugins.push(configMockPlugin({ isBuild }));
}
return vitePlugins;
}
export { createPlugins };

View File

@ -0,0 +1,19 @@
/**
* Mock plugin for development and production.
* https://github.com/anncwb/vite-plugin-mock
*/
import { viteMockServe } from 'vite-plugin-mock';
export function configMockPlugin({ isBuild }: { isBuild: boolean }) {
return viteMockServe({
ignore: /^_/,
mockPath: 'mock',
localEnabled: !isBuild,
prodEnabled: isBuild,
injectCode: `
import { setupProdMockServer } from '../mock/_createProductionServer';
setupProdMockServer();
`,
});
}

View File

@ -0,0 +1,17 @@
/**
* Vite Plugin for fast creating SVG sprites.
* https://github.com/anncwb/vite-plugin-svg-icons
*/
import { resolve } from 'node:path';
import type { PluginOption } from 'vite';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) {
const svgIconsPlugin = createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
svgoOptions: isBuild,
});
return svgIconsPlugin as PluginOption;
}

View File

@ -0,0 +1,14 @@
/**
* Package file volume analysis
*/
import visualizer from 'rollup-plugin-visualizer';
import { type PluginOption } from 'vite';
export function configVisualizerConfig() {
return visualizer({
filename: './node_modules/.cache/visualizer/stats.html',
open: true,
gzipSize: true,
brotliSize: true,
}) as PluginOption;
}

View File

@ -0,0 +1,44 @@
import { join } from 'node:path';
import dotenv from 'dotenv';
import { readFile } from 'fs-extra';
/**
*
*/
function getConfFiles() {
const script = process.env.npm_lifecycle_script as string;
const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script);
if (result) {
const mode = result[1];
return ['.env', `.env.${mode}`];
}
return ['.env', '.env.production'];
}
/**
* Get the environment variables starting with the specified prefix
* @param match prefix
* @param confFiles ext
*/
export async function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
let envConfig = {};
for (const confFile of confFiles) {
try {
const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' });
const env = dotenv.parse(envPath);
envConfig = { ...envConfig, ...env };
} catch (e) {
console.error(`Error in parsing ${confFile}`, e);
}
}
const reg = new RegExp(`^(${match})`);
Object.keys(envConfig).forEach((key) => {
if (!reg.test(key)) {
Reflect.deleteProperty(envConfig, key);
}
});
return envConfig;
}

View File

@ -0,0 +1,8 @@
import { createHash } from 'node:crypto';
function createContentHash(content: string, hashLSize = 12) {
const hash = createHash('sha256').update(content);
return hash.digest('hex').slice(0, hashLSize);
}
export { createContentHash };

View File

@ -0,0 +1,47 @@
import { resolve } from 'node:path';
import { generate } from '@ant-design/colors';
// @ts-ignore: typo
/* import { getThemeVariables } from 'ant-design-vue/dist/theme'; */
import { theme } from 'ant-design-vue/lib';
import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken';
const { defaultAlgorithm, defaultSeed } = theme;
const primaryColor = '#0960bd';
function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') {
return generate(color, {
theme,
});
}
/**
* less global variable
*/
export function generateModifyVars() {
const palettes = generateAntColors(primaryColor);
const primary = palettes[5];
const primaryColorObj: Record<string, string> = {};
for (let index = 0; index < 10; index++) {
primaryColorObj[`primary-${index + 1}`] = palettes[index];
}
// const modifyVars = getThemeVariables();
const mapToken = defaultAlgorithm(defaultSeed);
const v3Token = convertLegacyToken(mapToken);
return {
...v3Token,
// reference: Avoid repeated references
hack: `true; @import (reference) "${resolve('src/design/config.less')}";`,
'primary-color': primary,
...primaryColorObj,
'info-color': primary,
'processing-color': primary,
'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color
'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color
};
}

View File

@ -0,0 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/node.json",
"include": ["src"]
}

33
nginx.conf Normal file
View File

@ -0,0 +1,33 @@
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 80;
location / {
root /usr/share/nginx/html/dist;
try_files $uri $uri/ /index.html;
index index.html;
# Enable CORS
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
}
}

152
package.json Normal file
View File

@ -0,0 +1,152 @@
{
"name": "eairp-web",
"version": "1.0.1",
"homepage": "https://github.com/wansenai/wansen-erp-ui",
"bugs": {
"url": "https://github.com/wansenai/wansen-erp-ui/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/wansenai/wansen-erp-ui.git"
},
"scripts": {
"bootstrap": "pnpm install",
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build",
"build:analyze": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode analyze",
"build:no-cache": "pnpm store prune && npm run build",
"build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build --mode test",
"build:docker": "vite build --mode docker",
"commit": "czg",
"dev": "pnpm vite",
"preinstall": "npx only-allow pnpm",
"postinstall": "turbo run stub",
"lint": "turbo run lint",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write .",
"lint:stylelint": "stylelint \"**/*.{vue,css,less.scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/",
"preview": "npm run build && vite preview",
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"serve": "npm run dev",
"test:gzip": "npx http-server dist --cors --gzip -c-1",
"type:check": "vue-tsc --noEmit --skipLibCheck"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
"prettier --write--parser json"
],
"package.json": [
"prettier --write"
],
"*.vue": [
"eslint --fix",
"prettier --write",
"stylelint --fix"
],
"*.{scss,less,styl,html}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"prettier --write"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
},
"dependencies": {
"@ant-design/icons-vue": "^6.1.0",
"@axolo/tree-array": "^0.1.0",
"@iconify/iconify": "^3.1.1",
"@logicflow/core": "^1.2.9",
"@logicflow/extension": "^1.2.9",
"@vben/hooks": "workspace:*",
"@vue/shared": "^3.3.4",
"@vueuse/core": "^10.2.1",
"@vueuse/shared": "^10.2.1",
"@zxcvbn-ts/core": "^3.0.2",
"ant-design-vue": "^4.0.6",
"axios": "^1.4.0",
"codemirror": "^5.65.12",
"cropperjs": "^1.5.13",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.9",
"echarts": "^5.4.2",
"exceljs": "^4.3.0",
"intro.js": "^7.0.1",
"lodash-es": "^4.17.21",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.1",
"pinia": "2.1.4",
"print-js": "^1.6.0",
"qrcode": "^1.5.3",
"qs": "^6.11.2",
"resize-observer-polyfill": "^1.5.1",
"showdown": "^2.1.0",
"sortablejs": "^1.15.0",
"tinymce": "^5.10.7",
"vditor": "^3.9.4",
"vue": "^3.3.4",
"vue-i18n": "^9.2.2",
"vue-json-pretty": "^2.2.4",
"vue-router": "^4.2.3",
"vue-types": "^5.1.0",
"vuedraggable": "^4.1.0",
"vxe-table": "^4.5.14",
"vxe-table-plugin-export-xlsx": "3.1.0",
"xe-utils": "^3.5.11",
"xlsx": "^0.18.5",
"bpmn-js": "^16.1.0",
"@bpmn-io/properties-panel": "^3.13.0",
"bpmn-js-properties-panel": "^5.6.1",
"camunda-bpmn-moddle": "^7.0.1",
"diagram-js-grid-bg": "^1.0.3",
"diagram-js-minimap": "4.1.0"
},
"devDependencies": {
"@commitlint/cli": "^17.6.6",
"@commitlint/config-conventional": "^17.6.6",
"@iconify/json": "^2.2.87",
"@purge-icons/generated": "^0.9.0",
"@types/codemirror": "^5.60.8",
"@types/crypto-js": "^4.1.1",
"@types/intro.js": "^5.1.1",
"@types/lodash-es": "^4.17.7",
"@types/mockjs": "^1.0.7",
"@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.5.1",
"@types/qs": "^6.9.7",
"@types/showdown": "^2.0.1",
"@types/sortablejs": "^1.15.1",
"@vben/stylelint-config": "workspace:*",
"@vben/ts-config": "workspace:*",
"@vben/types": "workspace:*",
"@vben/vite-config": "workspace:*",
"@vue/compiler-sfc": "^3.3.4",
"@vue/test-utils": "^2.4.0",
"cross-env": "^7.0.3",
"cz-git": "^1.6.1",
"czg": "^1.6.1",
"lint-staged": "13.2.3",
"prettier": "^2.8.8",
"prettier-plugin-packagejson": "^2.4.4",
"rimraf": "^5.0.1",
"turbo": "^1.10.7",
"typescript": "^5.1.6",
"unbuild": "^1.2.1",
"vite": "^4.4.0",
"vite-plugin-mock": "^2.9.6",
"vue-tsc": "^1.8.4"
},
"packageManager": "pnpm@8.1.0",
"engines": {
"node": ">=16.15.1",
"pnpm": ">=8.1.0"
}
}

BIN
packages/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ['@vben/eslint-config/strict'],
};

View File

@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
entries: ['src/index'],
declaration: true,
rollup: {
emitCJS: true,
},
});

View File

@ -0,0 +1,29 @@
{
"name": "@vben/hooks",
"version": "1.0.0",
"license": "MIT",
"sideEffects": false,
"exports": {
".": {
"default": "./src/index.ts"
}
},
"main": "./src/index.ts",
"module": "./src/index.ts",
"files": [
"dist"
],
"scripts": {
"//build": "pnpm unbuild",
"//stub": "pnpm unbuild --stub",
"clean": "pnpm rimraf node_modules dist",
"lint": "pnpm eslint ."
},
"dependencies": {
"@vueuse/core": "^9.13.0",
"vue": "^3.2.47"
},
"devDependencies": {
"@vben/types": "workspace:*"
}
}

View File

@ -0,0 +1,6 @@
export * from './onMountedOrActivated';
export * from './useAttrs';
export * from './useRefs';
export * from './useScrollTo';
export * from './useWindowSizeFn';
export { useTimeoutFn } from '@vueuse/core';

View File

@ -0,0 +1,25 @@
import { type AnyFunction } from '@vben/types';
import { nextTick, onActivated, onMounted } from 'vue';
/**
* OnMounted OnActivated
* @param hook
*/
function onMountedOrActivated(hook: AnyFunction) {
let mounted: boolean;
onMounted(() => {
hook();
nextTick(() => {
mounted = true;
});
});
onActivated(() => {
if (mounted) {
hook();
}
});
}
export { onMountedOrActivated };

View File

@ -0,0 +1,43 @@
import { type Recordable } from '@vben/types';
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
interface UseAttrsOptions {
excludeListeners?: boolean;
excludeKeys?: string[];
excludeDefaultKeys?: boolean;
}
const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
const LISTENER_PREFIX = /^on[A-Z]/;
function entries<T>(obj: Recordable<T>): [string, T][] {
return Object.keys(obj).map((key: string) => [key, obj[key]]);
}
function useAttrs(options: UseAttrsOptions = {}): Recordable<any> {
const instance = getCurrentInstance();
if (!instance) return {};
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
const attrs = shallowRef({});
const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
// Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
instance.attrs = reactive(instance.attrs);
watchEffect(() => {
const res = entries(instance.attrs).reduce((acm, [key, val]) => {
if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) {
acm[key] = val;
}
return acm;
}, {} as Recordable<any>);
attrs.value = res;
});
return attrs;
}
export { useAttrs, type UseAttrsOptions };

View File

@ -0,0 +1,24 @@
import type { Ref } from 'vue';
import { onBeforeUpdate, shallowRef } from 'vue';
function useRefs(): {
refs: Ref<HTMLElement[]>;
setRefs: (index: number) => (el: HTMLElement) => void;
} {
const refs = shallowRef([]) as Ref<HTMLElement[]>;
onBeforeUpdate(() => {
refs.value = [];
});
const setRefs = (index: number) => (el: HTMLElement) => {
refs.value[index] = el;
};
return {
refs,
setRefs,
};
}
export { useRefs };

View File

@ -0,0 +1,60 @@
import { shallowRef, unref } from 'vue';
interface UseScrollToOptions {
el: any;
to: number;
duration?: number;
callback?: () => any;
}
function easeInOutQuad(t: number, b: number, c: number, d: number) {
t /= d / 2;
if (t < 1) {
return (c / 2) * t * t + b;
}
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
}
function move(el: HTMLElement, amount: number) {
el.scrollTop = amount;
}
const position = (el: HTMLElement) => {
return el.scrollTop;
};
function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) {
const isActiveRef = shallowRef(false);
const start = position(el);
const change = to - start;
const increment = 20;
let currentTime = 0;
const animateScroll = function () {
if (!unref(isActiveRef)) {
return;
}
currentTime += increment;
const val = easeInOutQuad(currentTime, start, change, duration);
move(el, val);
if (currentTime < duration && unref(isActiveRef)) {
requestAnimationFrame(animateScroll);
} else {
if (callback && typeof callback === 'function') {
callback();
}
}
};
const run = () => {
isActiveRef.value = true;
animateScroll();
};
const stop = () => {
isActiveRef.value = false;
};
return { start: run, stop };
}
export { useScrollTo, type UseScrollToOptions };

View File

@ -0,0 +1,40 @@
import { type AnyFunction } from '@vben/types';
import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
interface UseWindowSizeOptions {
wait?: number;
once?: boolean;
immediate?: boolean;
listenerOptions?: AddEventListenerOptions | boolean;
}
function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
const { wait = 150, immediate } = options;
let handler = () => {
fn();
};
const handleSize = useDebounceFn(handler, wait);
handler = handleSize;
const start = () => {
if (immediate) {
handler();
}
window.addEventListener('resize', handler);
};
const stop = () => {
window.removeEventListener('resize', handler);
};
tryOnMounted(() => {
start();
});
tryOnUnmounted(() => {
stop();
});
return { start, stop };
}
export { useWindowSizeFn, type UseWindowSizeOptions };

View File

@ -0,0 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/vue-app.json",
"include": ["src"]
}

View File

@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ['@vben/eslint-config/strict'],
};

View File

@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
entries: ['src/index'],
declaration: true,
rollup: {
emitCJS: true,
},
});

View File

@ -0,0 +1,22 @@
{
"name": "@vben/types",
"version": "1.0.0",
"license": "MIT",
"sideEffects": false,
"exports": {
".": {
"default": "./src/index.ts"
}
},
"main": "./src/index.ts",
"module": "./src/index.ts",
"files": [
"dist"
],
"scripts": {
"//build": "pnpm unbuild",
"//stub": "pnpm unbuild --stub",
"clean": "pnpm rimraf node_modules dist",
"lint": "pnpm eslint ."
}
}

View File

@ -0,0 +1 @@
export * from './utils';

View File

@ -0,0 +1,58 @@
/**
*
*/
type AnyPromiseFunction = (...arg: any[]) => PromiseLike<any>;
/**
*
*/
type AnyNormalFunction = (...arg: any[]) => any;
/**
*
*/
type AnyFunction = AnyNormalFunction | AnyPromiseFunction;
/**
* T | null
*/
type Nullable<T> = T | null;
/**
* T | Not null
*/
type NonNullable<T> = T extends null | undefined ? never : T;
/**
*
*/
type Recordable<T> = Record<string, T>;
/**
*
*/
interface ReadonlyRecordable<T = any> {
readonly [key: string]: T;
}
/**
* setTimeout
*/
type TimeoutHandle = ReturnType<typeof setTimeout>;
/**
* setInterval
*/
type IntervalHandle = ReturnType<typeof setInterval>;
export {
type AnyFunction,
type AnyNormalFunction,
type AnyPromiseFunction,
type IntervalHandle,
type NonNullable,
type Nullable,
type ReadonlyRecordable,
type Recordable,
type TimeoutHandle,
};

View File

@ -0,0 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/vue-app.json",
"include": ["src"]
}

15390
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

4
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,4 @@
packages:
- 'internal/*'
- 'packages/*'
- 'apps/test-server'

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/resource/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
This is where language files should be placed.
Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/

View File

@ -0,0 +1,419 @@
tinymce.addI18n('es', {
Redo: 'Rehacer',
Undo: 'Deshacer',
Cut: 'Cortar',
Copy: 'Copiar',
Paste: 'Pegar',
'Select all': 'Seleccionar todo',
'New document': 'Nuevo documento',
Ok: 'Ok',
Cancel: 'Cancelar',
'Visual aids': 'Ayudas visuales',
Bold: 'Negrita',
Italic: 'Cursiva',
Underline: 'Subrayado',
Strikethrough: 'Tachado',
Superscript: 'Super\u00edndice',
Subscript: 'Sub\u00edndice',
'Clear formatting': 'Limpiar formato',
'Align left': 'Alinear a la izquierda',
'Align center': 'Alinear al centro',
'Align right': 'Alinear a la derecha',
Justify: 'Justificar',
'Bullet list': 'Lista de vi\u00f1etas',
'Numbered list': 'Lista numerada',
'Decrease indent': 'Disminuir sangr\u00eda',
'Increase indent': 'Incrementar sangr\u00eda',
Close: 'Cerrar',
Formats: 'Formatos',
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": 'Su navegador no es compatible con el acceso directo al portapapeles. Use las teclas Crtl+X\/C\/V de su teclado.',
Headers: 'Encabezados',
'Header 1': 'Encabezado 1',
'Header 2': 'Encabezado 2',
'Header 3': 'Encabezado 3',
'Header 4': 'Encabezado 4',
'Header 5': 'Encabezado 5',
'Header 6': 'Encabezado 6',
Headings: 'Encabezados',
'Heading 1': 'Encabezado 1',
'Heading 2': 'Encabezado 2',
'Heading 3': 'Encabezado 3',
'Heading 4': 'Encabezado 4',
'Heading 5': 'Encabezado 5',
'Heading 6': 'Encabezado 6',
Preformatted: 'Con formato previo',
Div: 'Div',
Pre: 'Pre',
Code: 'C\u00f3digo',
Paragraph: 'P\u00e1rrafo',
Blockquote: 'Blockquote',
Inline: 'Alineado',
Blocks: 'Bloques',
'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.': 'Pegar est\u00e1 ahora en modo de texto plano. El contenido se pegar\u00e1 como texto plano hasta que desactive esta opci\u00f3n.',
Fonts: 'Fuentes',
'Font Sizes': 'Tama\u00f1os de fuente',
Class: 'Clase',
'Browse for an image': 'Buscar una imagen',
OR: 'OR',
'Drop an image here': 'Arrastre una imagen aqu\u00ed',
Upload: 'Cargar',
Block: 'Bloque',
Align: 'Alinear',
Default: 'Por defecto',
Circle: 'C\u00edrculo',
Disc: 'Disco',
Square: 'Cuadrado',
'Lower Alpha': 'Inferior Alfa',
'Lower Greek': 'Inferior Griega',
'Lower Roman': 'Inferior Romana',
'Upper Alpha': 'Superior Alfa',
'Upper Roman': 'Superior Romana',
'Anchor...': 'Anclaje...',
Name: 'Nombre',
Id: 'Id',
'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.': 'Deber\u00eda comenzar por una letra, seguida solo de letras, n\u00fameros, guiones, puntos, dos puntos o guiones bajos.',
'You have unsaved changes are you sure you want to navigate away?': 'Tiene cambios sin guardar. \u00bfEst\u00e1 seguro de que quiere salir?',
'Restore last draft': 'Restaurar el \u00faltimo borrador',
'Special character...': 'Car\u00e1cter especial...',
'Source code': 'C\u00f3digo fuente',
'Insert\/Edit code sample': 'Insertar\/editar c\u00f3digo de prueba',
Language: 'Idioma',
'Code sample...': 'Ejemplo de c\u00f3digo...',
'Color Picker': 'Selector de colores',
R: 'R',
G: 'V',
B: 'A',
'Left to right': 'De izquierda a derecha',
'Right to left': 'De derecha a izquierda',
'Emoticons...': 'Emoticones...',
'Metadata and Document Properties': 'Metadatos y propiedades del documento',
Title: 'T\u00edtulo',
Keywords: 'Palabras clave',
Description: 'Descripci\u00f3n',
Robots: 'Robots',
Author: 'Autor',
Encoding: 'Codificaci\u00f3n',
Fullscreen: 'Pantalla completa',
Action: 'Acci\u00f3n',
Shortcut: 'Atajo',
Help: 'Ayuda',
Address: 'Direcci\u00f3n',
'Focus to menubar': 'Enfocar la barra del men\u00fa',
'Focus to toolbar': 'Enfocar la barra de herramientas',
'Focus to element path': 'Enfocar la ruta del elemento',
'Focus to contextual toolbar': 'Enfocar la barra de herramientas contextual',
'Insert link (if link plugin activated)': 'Insertar enlace (si el complemento de enlace est\u00e1 activado)',
'Save (if save plugin activated)': 'Guardar (si el componente de salvar est\u00e1 activado)',
'Find (if searchreplace plugin activated)': 'Buscar (si el complemento buscar-remplazar est\u00e1 activado)',
'Plugins installed ({0}):': 'Plugins instalados ({0}):',
'Premium plugins:': 'Complementos premium:',
'Learn more...': 'Aprende m\u00e1s...',
'You are using {0}': 'Estas usando {0}',
Plugins: 'Complementos',
'Handy Shortcuts': 'Accesos directos',
'Horizontal line': 'L\u00ednea horizontal',
'Insert\/edit image': 'Insertar\/editar imagen',
'Image description': 'Descripci\u00f3n de la imagen',
Source: 'Enlace',
Dimensions: 'Dimensiones',
'Constrain proportions': 'Restringir proporciones',
General: 'General',
Advanced: 'Avanzado',
Style: 'Estilo',
'Vertical space': 'Espacio vertical',
'Horizontal space': 'Espacio horizontal',
Border: 'Borde',
'Insert image': 'Insertar imagen',
'Image...': 'Imagen...',
'Image list': 'Lista de im\u00e1genes',
'Rotate counterclockwise': 'Girar a la izquierda',
'Rotate clockwise': 'Girar a la derecha',
'Flip vertically': 'Invertir verticalmente',
'Flip horizontally': 'Invertir horizontalmente',
'Edit image': 'Editar imagen',
'Image options': 'Opciones de imagen',
'Zoom in': 'Acercar',
'Zoom out': 'Alejar',
Crop: 'Recortar',
Resize: 'Redimensionar',
Orientation: 'Orientaci\u00f3n',
Brightness: 'Brillo',
Sharpen: 'Forma',
Contrast: 'Contraste',
'Color levels': 'Niveles de color',
Gamma: 'Gamma',
Invert: 'Invertir',
Apply: 'Aplicar',
Back: 'Atr\u00e1s',
'Insert date\/time': 'Insertar fecha\/hora',
'Date\/time': 'Fecha\/hora',
'Insert\/Edit Link': 'Insertar\/editar enlace',
'Insert\/edit link': 'Insertar\/editar enlace',
'Text to display': 'Texto para mostrar',
Url: 'URL',
'Open link in...': 'Abrir enlace en...',
'Current window': 'Ventana actual',
None: 'Ninguno',
'New window': 'Nueva ventana',
'Remove link': 'Quitar enlace',
Anchors: 'Anclas',
'Link...': 'Enlace...',
'Paste or type a link': 'Pega o introduce un enlace',
'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?': 'El enlace que has introducido no parece ser una direcci\u00f3n de correo electr\u00f3nico. Quieres a\u00f1adir el prefijo necesario mailto: ?',
'The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?': 'El enlace que has introducido no parece ser una enlace externo. Quieres a\u00f1adir el prefijo necesario http:\/\/ ?',
'Link list': 'Lista de enlaces',
'Insert video': 'Insertar video',
'Insert\/edit video': 'Insertar\/editar video',
'Insert\/edit media': 'Insertar\/editar medio',
'Alternative source': 'Enlace alternativo',
'Alternative source URL': 'Origen de URL alternativo',
'Media poster (Image URL)': 'P\u00f3ster de medio (URL de imagen)',
'Paste your embed code below:': 'Pega tu c\u00f3digo embebido debajo',
Embed: 'Incrustado',
'Media...': 'Medios...',
'Nonbreaking space': 'Espacio fijo',
'Page break': 'Salto de p\u00e1gina',
'Paste as text': 'Pegar como texto',
Preview: 'Previsualizar',
'Print...': 'Imprimir...',
Save: 'Guardar',
Find: 'Buscar',
'Replace with': 'Reemplazar con',
Replace: 'Reemplazar',
'Replace all': 'Reemplazar todo',
Previous: 'Anterior',
Next: 'Siguiente',
'Find and replace...': 'Buscar y reemplazar...',
'Could not find the specified string.': 'No se encuentra la cadena de texto especificada',
'Match case': 'Coincidencia exacta',
'Find whole words only': 'Solo palabras completas',
'Spell check': 'Revisar ortograf\u00eda',
Ignore: 'Ignorar',
'Ignore all': 'Ignorar todos',
Finish: 'Finalizar',
'Add to Dictionary': 'A\u00f1adir al Diccionario',
'Insert table': 'Insertar tabla',
'Table properties': 'Propiedades de la tabla',
'Delete table': 'Eliminar tabla',
Cell: 'Celda',
Row: 'Fila',
Column: 'Columna',
'Cell properties': 'Propiedades de la celda',
'Merge cells': 'Combinar celdas',
'Split cell': 'Dividir celdas',
'Insert row before': 'Insertar fila antes',
'Insert row after': 'Insertar fila despu\u00e9s ',
'Delete row': 'Eliminar fila',
'Row properties': 'Propiedades de la fila',
'Cut row': 'Cortar fila',
'Copy row': 'Copiar fila',
'Paste row before': 'Pegar la fila antes',
'Paste row after': 'Pegar la fila despu\u00e9s',
'Insert column before': 'Insertar columna antes',
'Insert column after': 'Insertar columna despu\u00e9s',
'Delete column': 'Eliminar columna',
Cols: 'Columnas',
Rows: 'Filas',
Width: 'Ancho',
Height: 'Alto',
'Cell spacing': 'Espacio entre celdas',
'Cell padding': 'Relleno de celda',
'Show caption': 'Mostrar t\u00edtulo',
Left: 'Izquierda',
Center: 'Centrado',
Right: 'Derecha',
'Cell type': 'Tipo de celda',
Scope: '\u00c1mbito',
Alignment: 'Alineaci\u00f3n',
'H Align': 'Alineamiento Horizontal',
'V Align': 'Alineamiento Vertical',
Top: 'Arriba',
Middle: 'Centro',
Bottom: 'Abajo',
'Header cell': 'Celda de la cebecera',
'Row group': 'Grupo de filas',
'Column group': 'Grupo de columnas',
'Row type': 'Tipo de fila',
Header: 'Cabecera',
Body: 'Cuerpo',
Footer: 'Pie de p\u00e1gina',
'Border color': 'Color del borde',
'Insert template...': 'Insertar plantilla...',
Templates: 'Plantillas',
Template: 'Plantilla',
'Text color': 'Color del texto',
'Background color': 'Color de fondo',
'Custom...': 'Personalizar...',
'Custom color': 'Color personalizado',
'No color': 'Sin color',
'Remove color': 'Quitar color',
'Table of Contents': 'Tabla de contenidos',
'Show blocks': 'Mostrar bloques',
'Show invisible characters': 'Mostrar caracteres invisibles',
'Word count': 'Contar palabras',
Count: 'Recuento',
Document: 'Documento',
Selection: 'Selecci\u00f3n',
Words: 'Palabras',
'Words: {0}': 'Palabras: {0}',
'{0} words': '{0} palabras',
File: 'Archivo',
Edit: 'Editar',
Insert: 'Insertar',
View: 'Ver',
Format: 'Formato',
Table: 'Tabla',
Tools: 'Herramientas',
'Powered by {0}': 'Desarrollado por {0}',
'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help': '\u00c1rea de texto enriquecido. Pulse ALT-F9 para el menu. Pulse ALT-F10 para la barra de herramientas. Pulse ALT-0 para ayuda',
'Image title': 'Titulo de imagen',
'Border width': 'Ancho de borde',
'Border style': 'Estilo de borde',
Error: 'Error',
Warn: 'Advertencia',
Valid: 'V\u00e1lido',
'To open the popup, press Shift+Enter': 'Para abrir el elemento emergente, pulse May\u00fas+Intro',
'Rich Text Area. Press ALT-0 for help.': '\u00c1rea de texto enriquecido. Pulse ALT-0 para abrir la ayuda.',
'System Font': 'Fuente de sistema',
'Failed to upload image: {0}': 'Fallo al cargar imagen: {0}',
'Failed to load plugin: {0} from url {1}': 'Fallo al cargar complemento: {0} desde URL {1}',
'Failed to load plugin url: {0}': 'Fallo al cargar URL del complemento: {0}',
'Failed to initialize plugin: {0}': 'Fallo al iniciar el complemento: {0}',
example: 'ejemplo',
Search: 'Buscar',
All: 'Todo',
Currency: 'Divisa',
Text: 'Texto',
Quotations: 'Comillas',
Mathematical: 'S\u00edmbolo matem\u00e1tico',
'Extended Latin': 'Latino extendido A',
Symbols: 'S\u00edmbolos',
Arrows: 'Flechas',
'User Defined': 'Definido por el usuario',
'dollar sign': 'signo de d\u00f3lar',
'currency sign': 'signo de divisa',
'euro-currency sign': 'signo de euro',
'colon sign': 'signo de dos puntos',
'cruzeiro sign': 'signo de cruceiro',
'french franc sign': 'signo de franco franc\u00e9s',
'lira sign': 'signo de lira',
'mill sign': 'signo de mill',
'naira sign': 'signo de naira',
'peseta sign': 'signo de peseta',
'rupee sign': 'signo de rupia',
'won sign': 'signo de won',
'new sheqel sign': 'signo de nuevo s\u00e9quel',
'dong sign': 'signo de dong',
'kip sign': 'signo de kip',
'tugrik sign': 'signo de tugrik',
'drachma sign': 'signo de dracma',
'german penny symbol': 'signo de penique alem\u00e1n',
'peso sign': 'signo de peso',
'guarani sign': 'signo de guaran\u00ed',
'austral sign': 'signo de austral',
'hryvnia sign': 'signo de grivna',
'cedi sign': 'signo de cedi',
'livre tournois sign': 'signo de libra tornesa',
'spesmilo sign': 'signo de spesmilo',
'tenge sign': 'signo de tenge',
'indian rupee sign': 'signo de rupia india',
'turkish lira sign': 'signo de lira turca',
'nordic mark sign': 'signo de marco n\u00f3rdico',
'manat sign': 'signo de manat',
'ruble sign': 'signo de rublo',
'yen character': 'car\u00e1cter de yen',
'yuan character': 'car\u00e1cter de yuan',
'yuan character, in hong kong and taiwan': 'car\u00e1cter de yuan en Hong Kong y Taiw\u00e1n',
'yen\/yuan character variant one': 'Variante uno de car\u00e1cter de yen\/yuan',
'Loading emoticons...': 'Cargando emoticonos...',
'Could not load emoticons': 'No se han podido cargar los emoticonos',
People: 'Personas',
'Animals and Nature': 'Animales y naturaleza',
'Food and Drink': 'Comida y bebida',
Activity: 'Actividad',
'Travel and Places': 'Viajes y lugares',
Objects: 'Objetos',
Flags: 'Banderas',
Characters: 'Caracteres',
'Characters (no spaces)': 'Caracteres (sin espacios)',
'{0} characters': '{0} caracteres',
'Error: Form submit field collision.': 'Error: Colisi\u00f3n de campo al enviar formulario.',
'Error: No form element found.': 'Error: No se encuentra ning\u00fan elemento de formulario.',
Update: 'Actualizar',
'Color swatch': 'Muestrario de colores',
Turquoise: 'Turquesa',
Green: 'Verde',
Blue: 'Azul',
Purple: 'P\u00farpura',
'Navy Blue': 'Azul marino',
'Dark Turquoise': 'Turquesa oscuro',
'Dark Green': 'Verde oscuro',
'Medium Blue': 'Azul medio',
'Medium Purple': 'P\u00farpura medio',
'Midnight Blue': 'Azul medio',
Yellow: 'Amarillo',
Orange: 'Naranja',
Red: 'Rojo',
'Light Gray': 'Gris claro',
Gray: 'Gris',
'Dark Yellow': 'Amarillo oscuro',
'Dark Orange': 'Naranja oscuro',
'Dark Red': 'Rojo oscuro',
'Medium Gray': 'Gris medio',
'Dark Gray': 'Gris oscuro',
'Light Green': 'Verde claro',
'Light Yellow': 'Amarillo claro',
'Light Red': 'Rojo claro',
'Light Purple': 'Morado claro',
'Light Blue': 'Azul claro',
'Dark Purple': 'Morado oscuro',
'Dark Blue': 'Azul oscuro',
Black: 'Negro',
White: 'Blanco',
'Switch to or from fullscreen mode': 'Activar o desactivar modo pantalla completa',
'Open help dialog': 'Abrir di\u00e1logo de ayuda',
history: 'historial',
styles: 'estilos',
formatting: 'formato',
alignment: 'alineaci\u00f3n',
indentation: 'sangr\u00eda',
'permanent pen': 'bol\u00edgrafo permanente',
comments: 'comentarios',
'Format Painter': 'Copiar formato',
'Insert\/edit iframe': 'Insertar\/editar iframe',
Capitalization: 'Uso de may\u00fasculas',
lowercase: 'min\u00fasculas',
UPPERCASE: 'MAY\u00daSCULAS',
'Title Case': 'Tipo T\u00edtulo',
'Permanent Pen Properties': 'Propiedades del bol\u00edgrafo permanente',
'Permanent pen properties...': 'Propiedades del bol\u00edgrafo permanente...',
Font: 'Fuente',
Size: 'Tama\u00f1o',
'More...': 'M\u00e1s...',
'Spellcheck Language': 'Corrector',
'Select...': 'Seleccionar...',
Preferences: 'Preferencias',
Yes: 'S\u00ed',
No: 'No',
'Keyboard Navigation': 'Navegaci\u00f3n con el teclado',
Version: 'Versi\u00f3n',
Anchor: 'Ancla',
'Special character': 'Car\u00e1cter especial',
'Code sample': 'Ejemplo de c\u00f3digo',
Color: 'Color',
Emoticons: 'Emoticonos',
'Document properties': 'Propiedades del documento',
Image: 'Imagen',
'Insert link': 'Insertar enlace',
Target: 'Destino',
Link: 'Enlace',
Poster: 'Miniatura',
Media: 'Media',
Print: 'Imprimir',
Prev: 'Anterior',
'Find and replace': 'Buscar y reemplazar',
'Whole words': 'Palabras completas',
Spellcheck: 'Corrector ortogr\u00e1fico',
Caption: 'Subt\u00edtulo',
'Insert template': 'Insertar plantilla'
})

View File

@ -0,0 +1,389 @@
tinymce.addI18n('zh_CN',{
"Redo": "\u91cd\u505a",
"Undo": "\u64a4\u9500",
"Cut": "\u526a\u5207",
"Copy": "\u590d\u5236",
"Paste": "\u7c98\u8d34",
"Select all": "\u5168\u9009",
"New document": "\u65b0\u6587\u4ef6",
"Ok": "\u786e\u5b9a",
"Cancel": "\u53d6\u6d88",
"Visual aids": "\u7f51\u683c\u7ebf",
"Bold": "\u7c97\u4f53",
"Italic": "\u659c\u4f53",
"Underline": "\u4e0b\u5212\u7ebf",
"Strikethrough": "\u5220\u9664\u7ebf",
"Superscript": "\u4e0a\u6807",
"Subscript": "\u4e0b\u6807",
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
"Numbered list": "\u7f16\u53f7\u5217\u8868",
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
"Close": "\u5173\u95ed",
"Formats": "\u683c\u5f0f",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
"Headers": "\u6807\u9898",
"Header 1": "\u6807\u98981",
"Header 2": "\u6807\u98982",
"Header 3": "\u6807\u98983",
"Header 4": "\u6807\u98984",
"Header 5": "\u6807\u98985",
"Header 6": "\u6807\u98986",
"Headings": "\u6807\u9898",
"Heading 1": "\u6807\u98981",
"Heading 2": "\u6807\u98982",
"Heading 3": "\u6807\u98983",
"Heading 4": "\u6807\u98984",
"Heading 5": "\u6807\u98985",
"Heading 6": "\u6807\u98986",
"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
"Div": "Div",
"Pre": "Pre",
"Code": "\u4ee3\u7801",
"Paragraph": "\u6bb5\u843d",
"Blockquote": "\u5f15\u6587\u533a\u5757",
"Inline": "\u6587\u672c",
"Blocks": "\u57fa\u5757",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
"Fonts": "\u5b57\u4f53",
"Font Sizes": "\u5b57\u53f7",
"Class": "\u7c7b\u578b",
"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
"OR": "\u6216",
"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
"Upload": "\u4e0a\u4f20",
"Block": "\u5757",
"Align": "\u5bf9\u9f50",
"Default": "\u9ed8\u8ba4",
"Circle": "\u7a7a\u5fc3\u5706",
"Disc": "\u5b9e\u5fc3\u5706",
"Square": "\u65b9\u5757",
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Anchor...": "\u951a\u70b9...",
"Name": "\u540d\u79f0",
"Id": "\u6807\u8bc6\u7b26",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
"Special characters...": "\u7279\u6b8a\u5b57\u7b26...",
"Source code": "\u6e90\u4ee3\u7801",
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
"Language": "\u8bed\u8a00",
"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
"Color Picker": "\u9009\u8272\u5668",
"R": "R",
"G": "G",
"B": "B",
"Left to right": "\u4ece\u5de6\u5230\u53f3",
"Right to left": "\u4ece\u53f3\u5230\u5de6",
"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
"Title": "\u6807\u9898",
"Keywords": "\u5173\u952e\u8bcd",
"Description": "\u63cf\u8ff0",
"Robots": "\u673a\u5668\u4eba",
"Author": "\u4f5c\u8005",
"Encoding": "\u7f16\u7801",
"Fullscreen": "\u5168\u5c4f",
"Action": "\u64cd\u4f5c",
"Shortcut": "\u5feb\u6377\u952e",
"Help": "\u5e2e\u52a9",
"Address": "\u5730\u5740",
"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
"Plugins": "\u63d2\u4ef6",
"Handy Shortcuts": "\u5feb\u6377\u952e",
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
"Image description": "\u56fe\u7247\u63cf\u8ff0",
"Source": "\u5730\u5740",
"Dimensions": "\u5927\u5c0f",
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
"General": "\u666e\u901a",
"Advanced": "\u9ad8\u7ea7",
"Style": "\u6837\u5f0f",
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
"Border": "\u8fb9\u6846",
"Insert image": "\u63d2\u5165\u56fe\u7247",
"Image...": "\u56fe\u7247...",
"Image list": "\u56fe\u7247\u5217\u8868",
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
"Edit image": "\u7f16\u8f91\u56fe\u7247",
"Image options": "\u56fe\u7247\u9009\u9879",
"Zoom in": "\u653e\u5927",
"Zoom out": "\u7f29\u5c0f",
"Crop": "\u88c1\u526a",
"Resize": "\u8c03\u6574\u5927\u5c0f",
"Orientation": "\u65b9\u5411",
"Brightness": "\u4eae\u5ea6",
"Sharpen": "\u9510\u5316",
"Contrast": "\u5bf9\u6bd4\u5ea6",
"Color levels": "\u989c\u8272\u5c42\u6b21",
"Gamma": "\u4f3d\u9a6c\u503c",
"Invert": "\u53cd\u8f6c",
"Apply": "\u5e94\u7528",
"Back": "\u540e\u9000",
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
"Text to display": "\u663e\u793a\u6587\u5b57",
"Url": "\u5730\u5740",
"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
"Current window": "\u5f53\u524d\u7a97\u53e3",
"None": "\u65e0",
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
"Remove link": "\u5220\u9664\u94fe\u63a5",
"Anchors": "\u951a\u70b9",
"Link...": "\u94fe\u63a5...",
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
"Link list": "\u94fe\u63a5\u5217\u8868",
"Insert video": "\u63d2\u5165\u89c6\u9891",
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
"Alternative source": "\u955c\u50cf",
"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
"Embed": "\u5185\u5d4c",
"Media...": "\u591a\u5a92\u4f53...",
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
"Page break": "\u5206\u9875\u7b26",
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
"Preview": "\u9884\u89c8",
"Print...": "\u6253\u5370...",
"Save": "\u4fdd\u5b58",
"Find": "\u67e5\u627e",
"Replace with": "\u66ff\u6362\u4e3a",
"Replace": "\u66ff\u6362",
"Replace all": "\u5168\u90e8\u66ff\u6362",
"Previous": "\u4e0a\u4e00\u4e2a",
"Next": "\u4e0b\u4e00\u4e2a",
"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
"Find whole words only": "\u5168\u5b57\u5339\u914d",
"Spell check": "\u62fc\u5199\u68c0\u67e5",
"Ignore": "\u5ffd\u7565",
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
"Finish": "\u5b8c\u6210",
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
"Insert table": "\u63d2\u5165\u8868\u683c",
"Table properties": "\u8868\u683c\u5c5e\u6027",
"Delete table": "\u5220\u9664\u8868\u683c",
"Cell": "\u5355\u5143\u683c",
"Row": "\u884c",
"Column": "\u5217",
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
"Delete row": "\u5220\u9664\u884c",
"Row properties": "\u884c\u5c5e\u6027",
"Cut row": "\u526a\u5207\u884c",
"Copy row": "\u590d\u5236\u884c",
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
"Delete column": "\u5220\u9664\u5217",
"Cols": "\u5217",
"Rows": "\u884c",
"Width": "\u5bbd",
"Height": "\u9ad8",
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
"Show caption": "\u663e\u793a\u6807\u9898",
"Left": "\u5de6\u5bf9\u9f50",
"Center": "\u5c45\u4e2d",
"Right": "\u53f3\u5bf9\u9f50",
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
"Scope": "\u8303\u56f4",
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
"V Align": "\u5782\u76f4\u5bf9\u9f50",
"Top": "\u9876\u90e8\u5bf9\u9f50",
"Middle": "\u5782\u76f4\u5c45\u4e2d",
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
"Row group": "\u884c\u7ec4",
"Column group": "\u5217\u7ec4",
"Row type": "\u884c\u7c7b\u578b",
"Header": "\u8868\u5934",
"Body": "\u8868\u4f53",
"Footer": "\u8868\u5c3e",
"Border color": "\u8fb9\u6846\u989c\u8272",
"Insert template...": "\u63d2\u5165\u6a21\u677f...",
"Templates": "\u6a21\u677f",
"Template": "\u6a21\u677f",
"Text color": "\u6587\u5b57\u989c\u8272",
"Background color": "\u80cc\u666f\u8272",
"Custom...": "\u81ea\u5b9a\u4e49...",
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
"No color": "\u65e0",
"Remove color": "\u79fb\u9664\u989c\u8272",
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
"Word count": "\u5b57\u6570",
"Words: {0}": "\u5b57\u6570\uff1a{0}",
"{0} words": "{0} \u5b57",
"File": "\u6587\u4ef6",
"Edit": "\u7f16\u8f91",
"Insert": "\u63d2\u5165",
"View": "\u89c6\u56fe",
"Format": "\u683c\u5f0f",
"Table": "\u8868\u683c",
"Tools": "\u5de5\u5177",
"Powered by {0}": "\u7531{0}\u9a71\u52a8",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
"Image title": "\u56fe\u7247\u6807\u9898",
"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
"Border style": "\u8fb9\u6846\u6837\u5f0f",
"Error": "\u9519\u8bef",
"Warn": "\u8b66\u544a",
"Valid": "\u6709\u6548",
"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
"System Font": "\u7cfb\u7edf\u5b57\u4f53",
"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
"example": "\u793a\u4f8b",
"Search": "\u641c\u7d22",
"All": "\u5168\u90e8",
"Currency": "\u8d27\u5e01",
"Text": "\u6587\u5b57",
"Quotations": "\u5f15\u7528",
"Mathematical": "\u6570\u5b66",
"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
"Symbols": "\u7b26\u53f7",
"Arrows": "\u7bad\u5934",
"User Defined": "\u81ea\u5b9a\u4e49",
"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
"currency sign": "\u8d27\u5e01\u7b26\u53f7",
"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
"colon sign": "\u5192\u53f7",
"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
"lira sign": "\u91cc\u62c9\u7b26\u53f7",
"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
"naira sign": "\u5948\u62c9\u7b26\u53f7",
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
"won sign": "\u97e9\u5143\u7b26\u53f7",
"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
"austral sign": "\u6fb3\u5143\u7b26\u53f7",
"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
"cedi sign": "\u585e\u5730\u7b26\u53f7",
"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
"spesmilo sign": "spesmilo\u7b26\u53f7",
"tenge sign": "\u575a\u6208\u7b26\u53f7",
"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
"ruble sign": "\u5362\u5e03\u7b26\u53f7",
"yen character": "\u65e5\u5143\u5b57\u6837",
"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
"People": "\u4eba\u7c7b",
"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
"Activity": "\u6d3b\u52a8",
"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
"Objects": "\u7269\u4ef6",
"Flags": "\u65d7\u5e1c",
"Characters": "\u5b57\u7b26",
"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
"Update": "\u66f4\u65b0",
"Color swatch": "\u989c\u8272\u6837\u672c",
"Turquoise": "\u9752\u7eff\u8272",
"Green": "\u7eff\u8272",
"Blue": "\u84dd\u8272",
"Purple": "\u7d2b\u8272",
"Navy Blue": "\u6d77\u519b\u84dd",
"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
"Dark Green": "\u6df1\u7eff\u8272",
"Medium Blue": "\u4e2d\u84dd\u8272",
"Medium Purple": "\u4e2d\u7d2b\u8272",
"Midnight Blue": "\u6df1\u84dd\u8272",
"Yellow": "\u9ec4\u8272",
"Orange": "\u6a59\u8272",
"Red": "\u7ea2\u8272",
"Light Gray": "\u6d45\u7070\u8272",
"Gray": "\u7070\u8272",
"Dark Yellow": "\u6697\u9ec4\u8272",
"Dark Orange": "\u6df1\u6a59\u8272",
"Dark Red": "\u6df1\u7ea2\u8272",
"Medium Gray": "\u4e2d\u7070\u8272",
"Dark Gray": "\u6df1\u7070\u8272",
"Black": "\u9ed1\u8272",
"White": "\u767d\u8272",
"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
"history": "\u5386\u53f2",
"styles": "\u6837\u5f0f",
"formatting": "\u683c\u5f0f\u5316",
"alignment": "\u5bf9\u9f50",
"indentation": "\u7f29\u8fdb",
"permanent pen": "\u8bb0\u53f7\u7b14",
"comments": "\u5907\u6ce8",
"Anchor": "\u951a\u70b9",
"Special character": "\u7279\u6b8a\u7b26\u53f7",
"Code sample": "\u4ee3\u7801\u793a\u4f8b",
"Color": "\u989c\u8272",
"Emoticons": "\u8868\u60c5",
"Document properties": "\u6587\u6863\u5c5e\u6027",
"Image": "\u56fe\u7247",
"Insert link": "\u63d2\u5165\u94fe\u63a5",
"Target": "\u6253\u5f00\u65b9\u5f0f",
"Link": "\u94fe\u63a5",
"Poster": "\u5c01\u9762",
"Media": "\u5a92\u4f53",
"Print": "\u6253\u5370",
"Prev": "\u4e0a\u4e00\u4e2a",
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
"Whole words": "\u5168\u5b57\u5339\u914d",
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
"Caption": "\u6807\u9898",
"Insert template": "\u63d2\u5165\u6a21\u677f"
});

View File

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

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),l=t=>null==t,i=t=>!l(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return i(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>e=>i(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>l(t)||"default"===t?"":t,h=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;e<n;e++){const n=t[e];if(d(r=n)&&!/\btox\-/.test(r.className))return a.some(n);if(s(n,e))break}var r;return a.none()})(e,0,g).exists((e=>e.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)})(t,n))})(t,r.parents))),m=(t,s,r,n,l,i)=>{i.length>1?((t,s,r,n,l,i)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(i,(t=>{const e="OL"===l?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,l,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,l)})})(t,s,r,n,l,i):((t,s,r,n,l,i)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",onSetup:h(t,l),onAction:()=>t.queryCommandState(n)||""===i?t.execCommand(n):e(t,l,i)})})(t,s,r,n,l,c(i[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;o<t.length;o++){const n=t[o];c(n)&&n.attr("contenteditable",e)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),h=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),w=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),h);if(!w)return null;let v=w.container;const _=k.backwards(w.container,w.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),h),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(w.container,w.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=$.length&&b.substr(0,0+$.length)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&s<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i<e.getContainer().offsetHeight;if(t){const t=e.dom,o=e.getDoc();t.setStyles(o.documentElement,{"min-height":0}),t.setStyles(e.getBody(),{"min-height":"inherit"})}l=t?(0,()=>0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t));const r=(void 0,t=>undefined===t);var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},y=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.4.2 (2023-04-26)
*/
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}();

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More