Compare commits
No commits in common. "factory" and "master" have entirely different histories.
28
.babelrc
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
// 移除 "es2015" 预设,因为它已经被 "env" 预设覆盖
|
||||
["@babel/preset-env" ],
|
||||
"@babel/preset-react" // 使用新的插件命名
|
||||
],
|
||||
"plugins": [
|
||||
["import", { "libraryName": "antd", "libraryDirectory": "lib"}],
|
||||
// 使用新的插件命名
|
||||
["@babel/plugin-transform-runtime", {
|
||||
"corejs": 3,
|
||||
"helpers": true,
|
||||
"regenerator": true,
|
||||
"useESModules": false
|
||||
}],
|
||||
["@babel/plugin-proposal-decorators", {
|
||||
"legacy": true
|
||||
}],
|
||||
["@babel/plugin-syntax-dynamic-import"],
|
||||
["@babel/plugin-transform-class-properties"], // 使用新的插件命名
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
name: Deploy API
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
env:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: https://gitlink.org.cn/actions/checkout@v4
|
||||
- name: Deploy API
|
||||
run: |
|
||||
echo "Deploying API to ${{ inputs.env }}"
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
name: Deploy Web
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
env:
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: https://gitlink.org.cn/actions/checkout@v4
|
||||
- name: Deploy Web
|
||||
run: |
|
||||
echo "Deploying Web to ${{ inputs.env }}"
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
name: Context testing
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
dump_contexts_to_log:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "SELECTED_COLOR=green" >> "$GITHUB_ENV"
|
||||
- run: echo "The selected color is ${{env.SELECTED_COLOR}}"
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Dump job context
|
||||
env:
|
||||
JOB_CONTEXT: ${{ toJson(job) }}
|
||||
run: |
|
||||
echo "$JOB_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
- name: env
|
||||
run: env
|
||||
- name: Dump steps context
|
||||
id: steps_context
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: |
|
||||
echo "$STEPS_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
echo "ACTIONS_RUNTIME_TOKEN====================${{ACTIONS_RUNTIME_TOKEN}}"
|
||||
- name: Dump runner context
|
||||
env:
|
||||
RUNNER_CONTEXT: ${{ toJson(runner) }}
|
||||
run: echo "$RUNNER_CONTEXT"
|
||||
- name: Dump needs context
|
||||
env:
|
||||
NEEDS_CONTEXT: ${{ toJson(needs) }}
|
||||
run: echo "$NEEDS_CONTEXT"
|
||||
- name: Dump strategy context
|
||||
env:
|
||||
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
|
||||
run: echo "$STRATEGY_CONTEXT"
|
||||
- name: Dump matrix context
|
||||
env:
|
||||
MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
||||
run: echo "$MATRIX_CONTEXT"
|
||||
- name: Dump steps context2
|
||||
id: steps_context2
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: |
|
||||
echo "$STEPS_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
echo "ACTIONS_RUNTIME_TOKEN====================${{ACTIONS_RUNTIME_TOKEN}}"
|
||||
- name: Dump GitHub context2
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: sleep 33 && echo "$GITHUB_CONTEXT"
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
name: Context testing
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
run-01:
|
||||
uses: ./.gitea/workflows/上下文信息.yml
|
||||
run-02:
|
||||
uses: ./.gitea/workflows/声明流水线.yml
|
||||
run-03:
|
||||
uses: ./.gitea/workflows/deploy-api.yml
|
||||
run-04:
|
||||
uses: ./.gitea/workflows/deploy-web.yml
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
name: Context testing
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
dump_contexts_to_log:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "SELECTED_COLOR=green" >> "$GITHUB_ENV"
|
||||
- run: echo "The selected color is ${{env.SELECTED_COLOR}}"
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Dump job context
|
||||
env:
|
||||
JOB_CONTEXT: ${{ toJson(job) }}
|
||||
run: |
|
||||
echo "$JOB_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
- name: env
|
||||
run: env
|
||||
- name: Dump steps context
|
||||
id: steps_context
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: |
|
||||
echo "$STEPS_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
echo "ACTIONS_RUNTIME_TOKEN====================${{ACTIONS_RUNTIME_TOKEN}}"
|
||||
- name: Dump runner context
|
||||
env:
|
||||
RUNNER_CONTEXT: ${{ toJson(runner) }}
|
||||
run: echo "$RUNNER_CONTEXT"
|
||||
- name: Dump needs context
|
||||
env:
|
||||
NEEDS_CONTEXT: ${{ toJson(needs) }}
|
||||
run: echo "$NEEDS_CONTEXT"
|
||||
- name: Dump strategy context
|
||||
env:
|
||||
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
|
||||
run: echo "$STRATEGY_CONTEXT"
|
||||
- name: Dump matrix context
|
||||
env:
|
||||
MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
||||
run: echo "$MATRIX_CONTEXT"
|
||||
- name: Dump steps context2
|
||||
id: steps_context2
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: |
|
||||
echo "$STEPS_CONTEXT"
|
||||
echo "adsfsf=========${{ github.action }}"
|
||||
echo "ACTIONS_RUNTIME_TOKEN====================${{ACTIONS_RUNTIME_TOKEN}}"
|
||||
- name: Dump GitHub context2
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Ignore master key for decrypting credentials and more.
|
||||
/config/master.key
|
||||
/config/database.yml
|
||||
/.idea/*
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# 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/
|
||||
buildserver/
|
||||
src/.umi/
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
#DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
.DS_Store
|
||||
.idea/*
|
||||
|
||||
1179
.idea/workspace.xml
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
{
|
||||
}
|
||||
124
LICENSE
|
|
@ -1,124 +0,0 @@
|
|||
木兰宽松许可证, 第2版
|
||||
|
||||
2020年1月 http://license.coscl.org.cn/MulanPSL2
|
||||
|
||||
您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
|
||||
|
||||
0. 定义
|
||||
|
||||
“软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
|
||||
|
||||
“贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
|
||||
|
||||
“贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
|
||||
|
||||
“法人实体” 是指提交贡献的机构及其“关联实体”。
|
||||
|
||||
“关联实体” 是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
|
||||
|
||||
1. 授予版权许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
|
||||
|
||||
2. 授予专利许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
|
||||
|
||||
3. 无商标许可
|
||||
|
||||
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
|
||||
|
||||
4. 分发限制
|
||||
|
||||
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
|
||||
|
||||
5. 免责声明与责任限制
|
||||
|
||||
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
|
||||
|
||||
6. 语言
|
||||
|
||||
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
|
||||
|
||||
条款结束
|
||||
|
||||
如何将木兰宽松许可证,第2版,应用到您的软件
|
||||
|
||||
如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
|
||||
|
||||
1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
|
||||
|
||||
2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
|
||||
|
||||
3, 请将如下声明文本放入每个源文件的头部注释中。
|
||||
|
||||
Copyright (c) [Year] [name of copyright holder]
|
||||
[Software Name] is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
Mulan Permissive Software License,Version 2
|
||||
Mulan Permissive Software License,Version 2 (Mulan PSL v2)
|
||||
|
||||
January 2020 http://license.coscl.org.cn/MulanPSL2
|
||||
|
||||
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
|
||||
|
||||
0. Definition
|
||||
|
||||
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
|
||||
|
||||
Contribution means the copyrightable work licensed by a particular Contributor under this License.
|
||||
|
||||
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
|
||||
|
||||
Legal Entity means the entity making a Contribution and all its Affiliates.
|
||||
|
||||
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
|
||||
|
||||
1. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
|
||||
|
||||
2. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
|
||||
|
||||
3. No Trademark License
|
||||
|
||||
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4.
|
||||
|
||||
4. Distribution Restriction
|
||||
|
||||
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
|
||||
|
||||
5. Disclaimer of Warranty and Limitation of Liability
|
||||
|
||||
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
6. Language
|
||||
|
||||
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
|
||||
|
||||
END OF THE TERMS AND CONDITIONS
|
||||
|
||||
How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
|
||||
|
||||
To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
|
||||
|
||||
Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
|
||||
Create a file named "LICENSE" which contains the whole context of this License in the first directory of your software package;
|
||||
Attach the statement to the appropriate annotated syntax at the beginning of each source file.
|
||||
Copyright (c) [Year] [name of copyright holder]
|
||||
[Software Name] is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
102
README.md
|
|
@ -1,102 +1,2 @@
|
|||
####版本:2024-6-20 更新版本,包含开通工作台、代码库、issue、等模块的版本更新,基本与forge一直,属于内网版本,邮件、协议签订等均已隐藏。
|
||||
#### node版本
|
||||
12.x/14.x
|
||||
#### ng配置
|
||||
后端服务另分配一个端口,不再映射域名
|
||||
改为前端服务映射域名,并转发到3000
|
||||
# forgeplus-react-v2
|
||||
|
||||
```
|
||||
server {
|
||||
listen 8080;
|
||||
server_name testforgeplus.trustie.net;
|
||||
|
||||
location / {
|
||||
root /home/pdl/forgeplus/public/;
|
||||
autoindex off;
|
||||
try_files $uri @backend;
|
||||
}
|
||||
location @backend {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8081;
|
||||
# server_name testforgeplus.trustie.net;
|
||||
# return http://$server_name$request_uri;
|
||||
# rewrite ^(.*)$ https://$host$1 permanent;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### 部署脚本
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
# Avoid root execution
|
||||
if [ `id|sed -e s/uid=//g -e s/\(.*//g` -eq 0 ]; then
|
||||
echo "Execution by root not allowed"
|
||||
exit 1
|
||||
fi
|
||||
cd
|
||||
|
||||
#上线分支
|
||||
Branch=pre_gitlink_ssr
|
||||
#代码路径
|
||||
Code_Path=/home/pdl/forgeplus/public/react/forgeplus-react
|
||||
#Build代码路径
|
||||
Build_Path=/home/pdl/forgeplus/public/react
|
||||
|
||||
cd $Code_Path
|
||||
pwd
|
||||
git checkout $Branch
|
||||
git pull
|
||||
|
||||
# 分别打静态包与node服务包
|
||||
npm install
|
||||
npm run build
|
||||
npm run build:server
|
||||
|
||||
# 复制一份到原来build路径
|
||||
#cd $Build_Path
|
||||
#rm -rf build.bak
|
||||
#mv build build.bak
|
||||
#scp -r $Code_Path/build ./
|
||||
|
||||
pm2 restart pm2.json
|
||||
|
||||
# 重新加载 Nginx 配置
|
||||
/home/pdl/nginx/sbin/nginx -s reload
|
||||
|
||||
# 检查 Nginx 是否重启成功
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo -e "\e[1;42m restart nginx OK! \e[0m"
|
||||
else
|
||||
echo -e "\e[1;31m restart nginx FAILED! \e[0m"
|
||||
fi
|
||||
```
|
||||
|
||||
pm2.json配置
|
||||
```json
|
||||
{
|
||||
"apps": [{
|
||||
"name": "gitlink-ssr",
|
||||
"script": "buildserver/bundle.js",
|
||||
"watch": false,
|
||||
"log_date_format": "YYYY-MM-DD HH:mm Z",
|
||||
"exec_mode": "cluster",
|
||||
"max_memory_restart": "300M", // 内存超过300m重启
|
||||
"env": {
|
||||
"NODE_ENV": "production",
|
||||
"PORT": "8081" // 修改为ng给后端服务另配的端口
|
||||
},
|
||||
"instances": 4 // 实例数
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
|
|
|||
59
Routes.js
|
|
@ -1,59 +0,0 @@
|
|||
import app from './src/App'
|
||||
// import users from './src/forge/users/Index';
|
||||
import Detail from "./src/forge/Main/Detail";
|
||||
// import Information from "./src/forge/Information/index"
|
||||
// import NewsDetail from './src/forge/Information/Pages/newsDetail';
|
||||
|
||||
export default [
|
||||
{
|
||||
key:"zone",
|
||||
path: "/zone/:deptId",
|
||||
// component: app,
|
||||
},
|
||||
{
|
||||
key: "zoneNews",
|
||||
path: "/zone/:deptId/newdetail/:id",
|
||||
// component: app
|
||||
},
|
||||
{
|
||||
key:"detail",
|
||||
path: "/:owner/:projectsId",
|
||||
component: app,
|
||||
}
|
||||
];
|
||||
|
||||
export const deepRoutes = [
|
||||
{
|
||||
key: "zoneNews",
|
||||
path: "/zone/:deptId/newdetail/:id",
|
||||
onlyHead: true,
|
||||
// component: NewsDetail
|
||||
},
|
||||
{
|
||||
key: "zone",
|
||||
path: "/zone/:deptId",
|
||||
onlyHead: true,
|
||||
// component: Information
|
||||
},
|
||||
{
|
||||
key: "detailBranch",
|
||||
path: "/:owner/:projectsId/tree/:branchName",
|
||||
onlyHead: false,
|
||||
component: Detail,
|
||||
},
|
||||
{
|
||||
key: "detail",
|
||||
path: "/:owner/:projectsId",
|
||||
onlyHead: false,
|
||||
component: Detail,
|
||||
},
|
||||
{
|
||||
key: "owner",
|
||||
path: "/:owner",
|
||||
onlyHead: true,
|
||||
// component: Detail,
|
||||
}
|
||||
]
|
||||
|
||||
// 不进行组织或个人判断
|
||||
export const specialRoute = ["ossRepo", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "undefined", "admins", "oauth", "competitions", "hiagent","sf", "development", "governance","explore"]
|
||||
34
add.txt
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
新版tpi改动的文件:
|
||||
Index.js
|
||||
contex/TPIContextProvider.js
|
||||
page/main/LeftViewContainer.js
|
||||
taskList/TaskList.js
|
||||
TPMIndexHOC.js
|
||||
App.js
|
||||
CodeRepositoryViewContainer.js
|
||||
|
||||
Index.js
|
||||
choose={context.chooses}
|
||||
|
||||
|
||||
TPIContextProvider.js
|
||||
|
||||
LeftViewContainer.js
|
||||
|
||||
TaskList.js
|
||||
|
||||
TPMIndexHOC.js
|
||||
|
||||
MainContentContainer
|
||||
新:rep_content返回值多了一层 {content: '...'}
|
||||
|
||||
|
||||
|
||||
|
||||
TODO
|
||||
待同步
|
||||
1、timer图标样式更换
|
||||
index.html
|
||||
WebSSHTimer.css
|
||||
WebSSHTimer.js
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const paths = require('./paths');
|
||||
|
||||
// Make sure that including paths.js after env.js will read .env variables.
|
||||
delete require.cache[require.resolve('./paths')];
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
if (!NODE_ENV) {
|
||||
throw new Error(
|
||||
'The NODE_ENV environment variable is required but was not specified.'
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
|
||||
var dotenvFiles = [
|
||||
`${paths.dotenv}.${NODE_ENV}.local`,
|
||||
`${paths.dotenv}.${NODE_ENV}`,
|
||||
// Don't include `.env.local` for `test` environment
|
||||
// since normally you expect tests to produce the same
|
||||
// results for everyone
|
||||
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
|
||||
paths.dotenv,
|
||||
].filter(Boolean);
|
||||
|
||||
// Load environment variables from .env* files. Suppress warnings using silent
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set. Variable expansion is supported in .env files.
|
||||
// https://github.com/motdotla/dotenv
|
||||
// https://github.com/motdotla/dotenv-expand
|
||||
dotenvFiles.forEach(dotenvFile => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
require('dotenv-expand')(
|
||||
require('dotenv').config({
|
||||
path: dotenvFile,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// We support resolving modules according to `NODE_PATH`.
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253.
|
||||
// It works similar to `NODE_PATH` in Node itself:
|
||||
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
|
||||
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
|
||||
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
|
||||
// We also resolve them to make sure all tools using them work consistently.
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||
.split(path.delimiter)
|
||||
.filter(folder => folder && !path.isAbsolute(folder))
|
||||
.map(folder => path.resolve(appDirectory, folder))
|
||||
.join(path.delimiter);
|
||||
|
||||
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
|
||||
// injected into the application via DefinePlugin in Webpack configuration.
|
||||
const REACT_APP = /^REACT_APP_/i;
|
||||
|
||||
function getClientEnvironment(publicUrl,reactUrl) {
|
||||
const raw = Object.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce(
|
||||
(env, key) => {
|
||||
env[key] = process.env[key];
|
||||
return env;
|
||||
},
|
||||
{
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
PUBLIC_URL: publicUrl,
|
||||
REACT_URL: reactUrl,
|
||||
}
|
||||
);
|
||||
// Stringify all values so we can feed into Webpack DefinePlugin
|
||||
const stringified = {
|
||||
'process.env': Object.keys(raw).reduce((env, key) => {
|
||||
env[key] = JSON.stringify(raw[key]);
|
||||
return env;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
return { raw, stringified };
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
// This is a custom Jest transformer turning style imports into empty objects.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process() {
|
||||
return 'module.exports = {};';
|
||||
},
|
||||
getCacheKey() {
|
||||
// The output is always the same.
|
||||
return 'cssTransform';
|
||||
},
|
||||
};
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// This is a custom Jest transformer turning file imports into filenames.
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process(src, filename) {
|
||||
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
|
||||
},
|
||||
};
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const url = require('url');
|
||||
|
||||
// Make sure any symlinks in the project folder are resolved:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/637
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
||||
|
||||
const envPublicUrl = process.env.PUBLIC_URL;
|
||||
|
||||
function ensureSlash(path, needsSlash) {
|
||||
const hasSlash = path.endsWith('/');
|
||||
if (hasSlash && !needsSlash) {
|
||||
return path.substr(path, path.length - 1);
|
||||
} else if (!hasSlash && needsSlash) {
|
||||
return `${path}/`;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
const getPublicUrl = appPackageJson =>
|
||||
envPublicUrl || require(appPackageJson).homepage;
|
||||
|
||||
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
|
||||
// "public path" at which the app is served.
|
||||
// Webpack needs to know it to put the right <script> hrefs into HTML even in
|
||||
// single-page apps that may serve index.html for nested URLs like /todos/42.
|
||||
// We can't use a relative path in HTML because we don't want to load something
|
||||
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
|
||||
function getServedPath(appPackageJson) {
|
||||
const publicUrl = getPublicUrl(appPackageJson);
|
||||
const servedUrl =
|
||||
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
|
||||
return ensureSlash(servedUrl, true);
|
||||
}
|
||||
|
||||
// config after eject: we're in ./config/
|
||||
module.exports = {
|
||||
dotenv: resolveApp('.env'),
|
||||
appBuild: resolveApp('build'),
|
||||
appPublic: resolveApp('public'),
|
||||
appHtml: resolveApp('public/index.html'),
|
||||
appIndexJs: resolveApp('src/index.js'),
|
||||
appPackageJson: resolveApp('package.json'),
|
||||
appSrc: resolveApp('src'),
|
||||
serverSrc: resolveApp('server'),
|
||||
yarnLockFile: resolveApp('yarn.lock'),
|
||||
testsSetup: resolveApp('src/setupTests.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
publicUrl: getPublicUrl(resolveApp('package.json')),
|
||||
servedPath: getServedPath(resolveApp('package.json')),
|
||||
};
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
if (typeof Promise === 'undefined') {
|
||||
// Rejection tracking prevents a common issue where React gets into an
|
||||
// inconsistent state due to an error, but it gets swallowed by a Promise,
|
||||
// and the user has no idea what causes React's erratic future behavior.
|
||||
require('promise/lib/rejection-tracking').enable();
|
||||
window.Promise = require('promise/lib/es6-extensions.js');
|
||||
}
|
||||
|
||||
// fetch() polyfill for making API calls.
|
||||
require('whatwg-fetch');
|
||||
|
||||
// Object.assign() is commonly used with React.
|
||||
// It will use the native implementation if it's present and isn't buggy.
|
||||
Object.assign = require('object-assign');
|
||||
|
||||
// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
|
||||
// We don't polyfill it in the browser--this is user's responsibility.
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
require('raf').polyfill(global);
|
||||
}
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
const autoprefixer = require("autoprefixer");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin");
|
||||
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
|
||||
const WatchMissingNodeModulesPlugin = require("react-dev-utils/WatchMissingNodeModulesPlugin");
|
||||
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
||||
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
|
||||
|
||||
const getClientEnvironment = require("./env");
|
||||
|
||||
const paths = require("./paths");
|
||||
|
||||
const publicPath = "/";
|
||||
const env = getClientEnvironment("/","development");
|
||||
|
||||
const process = require('process');
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
// 开发时,websocket proxy 会因服务重新部署而报错中断本地 server,这里拦截一下
|
||||
console.log('拦截未处理异常:', err);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: "async",
|
||||
// 大于30KB才单独分离成chunk
|
||||
minSize: 30000,
|
||||
maxAsyncRequests: 5,
|
||||
maxInitialRequests: 3,
|
||||
name: true,
|
||||
cacheGroups: {
|
||||
default: {
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
vendors: {
|
||||
name: "vendors",
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: -10,
|
||||
chunks: "all",
|
||||
},
|
||||
},
|
||||
},
|
||||
runtimeChunk: true,
|
||||
},
|
||||
mode: "development",
|
||||
// 开启调试
|
||||
devtool: "source-map", // 开启调试
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
|
||||
entry: [
|
||||
// We ship a few polyfills by default:
|
||||
require.resolve("./polyfills"),
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
// Finally, this is your app's code:
|
||||
paths.appIndexJs,
|
||||
// We include the app code last so that if there is a runtime error during
|
||||
// initialization, it doesn't blow up the WebpackDevServer client, and
|
||||
// changing JS code would still trigger a refresh.
|
||||
],
|
||||
output: {
|
||||
// Add /* filename */ comments to generated require()s in the output.
|
||||
pathinfo: true,
|
||||
globalObject: "this",
|
||||
// This does not produce a real file. It's just the virtual path that is
|
||||
// served by WebpackDevServer in development. This is the JS bundle
|
||||
// containing code from all our entry points, and the Webpack runtime.
|
||||
filename: "static/js/bundle.js",
|
||||
// There are also additional JS chunk files if you use code splitting.
|
||||
chunkFilename: "static/js/[name].chunk.js",
|
||||
// This is the URL that app is served from. We use "/" in development.
|
||||
publicPath,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: (info) =>
|
||||
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/"),
|
||||
},
|
||||
externals: {
|
||||
"react": "React",
|
||||
"react-dom": "ReactDOM",
|
||||
"alex": "Alex",
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ["node_modules", paths.appNodeModules].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||
alias: {
|
||||
educoder: __dirname + "/../src/common/educoder.js",
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
},
|
||||
plugins: [
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
// match the requirements. When no loader matches it will fall
|
||||
// back to the "file" loader at the end of the loader list.
|
||||
oneOf: [
|
||||
// "url" loader works like "file" loader except that it embeds assets
|
||||
// smaller than specified limit in bytes as data URLs to avoid requests.
|
||||
// A missing `test` is equivalent to a match.
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: require.resolve("url-loader"),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
// Process JS with Babel.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
include: paths.appSrc,
|
||||
exclude: /node_modules/,
|
||||
loader: require.resolve("babel-loader"),
|
||||
options: {
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in ./node_modules/.cache/babel-loader/
|
||||
// directory for faster rebuilds.
|
||||
cacheDirectory: true,
|
||||
plugins: [
|
||||
[
|
||||
"import",
|
||||
{
|
||||
libraryName: "antd",
|
||||
libraryDirectory: "es",
|
||||
style: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
// In production, we use a plugin to extract that CSS to a file, but
|
||||
// in development "style" loader enables hot editing of CSS.
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
require.resolve("style-loader"),
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2677
|
||||
ident: "postcss",
|
||||
plugins: () => [
|
||||
require("postcss-flexbugs-fixes"),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
">1%",
|
||||
"last 4 versions",
|
||||
"Firefox ESR",
|
||||
"not ie < 9", // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: "no-2009",
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
require.resolve("style-loader"),
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("sass-loader"),
|
||||
},
|
||||
{
|
||||
loader: 'sass-resources-loader',
|
||||
options: {
|
||||
resources: ['src/global.scss']
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
}, {
|
||||
loader: 'css-loader', // translates CSS into CommonJS
|
||||
}, {
|
||||
loader: 'less-loader', // compiles Less to CSS
|
||||
options: {
|
||||
modifyVars: {
|
||||
'primary-color': '#2149d4',
|
||||
'primary-color-hover': '#6684FE',
|
||||
'primary-color-active': '#1A47FF',
|
||||
'link-color': '#2149d4',
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
}]
|
||||
},
|
||||
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
// In production, they would get copied to the `build` folder.
|
||||
// This loader doesn't use a "test" so it will catch all modules
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// its runtime that would otherwise processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
|
||||
loader: require.resolve("file-loader"),
|
||||
options: {
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: paths.appHtml,
|
||||
reactPath:'react.production.min.js',
|
||||
}),
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// Add module names to factory functions so they appear in browser profiler.
|
||||
new webpack.NamedModulesPlugin(),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
|
||||
new webpack.DefinePlugin({ ...env.stringified, __SERVER__: 'false',__CLIENT__: 'true' }),
|
||||
// This is necessary to emit hot updates (currently CSS only):
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// Watcher doesn't work well if you mistype casing in a path so we use
|
||||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/240
|
||||
new CaseSensitivePathsPlugin(),
|
||||
// If you require a missing module and then `npm install` it, you still have
|
||||
// to restart the development server for Webpack to discover it. This plugin
|
||||
// makes the discovery automatic so you don't have to restart.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/186
|
||||
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
new MonacoWebpackPlugin({
|
||||
features: ["coreCommands", "find"],
|
||||
languages: ['plaintext', 'apex', 'azcli', 'bat', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'fsharp', 'go', 'handlebars', 'html', 'ini', 'java', 'javascript', 'json', 'less', 'lua', 'markdown', 'msdax', 'mysql', 'objective', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'ruby', 'rust', 'sb', 'scheme', 'scss', 'shell', 'solidity', 'sql', 'st', 'swift', 'typescript', 'vb', 'xml', 'yaml']
|
||||
}),
|
||||
],
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
dgram: "empty",
|
||||
fs: "empty",
|
||||
net: "empty",
|
||||
tls: "empty",
|
||||
child_process: "empty",
|
||||
},
|
||||
// Turn off performance hints during development because we don't do any
|
||||
// splitting or minification in interest of speed. These warnings become
|
||||
// cumbersome.
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
};
|
||||
|
|
@ -1,371 +0,0 @@
|
|||
"use strict";
|
||||
const autoprefixer = require("autoprefixer");
|
||||
const path = require("path");
|
||||
import { ReactLoadablePlugin } from 'react-loadable/webpack';
|
||||
const webpack = require("webpack");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
|
||||
const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
|
||||
const eslintFormatter = require("react-dev-utils/eslintFormatter");
|
||||
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
||||
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
|
||||
const TerserJSPlugin = require("terser-webpack-plugin");
|
||||
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||
const TerserWebpackPlugin = require('terser-webpack-plugin');
|
||||
const paths = require("./paths");
|
||||
const getClientEnvironment = require("./env");
|
||||
|
||||
let publicPath = "/react/build/";
|
||||
const publicUrl = publicPath.slice(0, -1);
|
||||
|
||||
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
const shouldUseSourceMap = process.env.NODE_ENV !== "production";
|
||||
const env = getClientEnvironment(publicPath,'production.min');
|
||||
|
||||
const terserPlugin = new TerserWebpackPlugin({
|
||||
parallel: 4,
|
||||
extractComments: true,
|
||||
terserOptions: {
|
||||
compress: {
|
||||
warnings: false,
|
||||
drop_console: true,
|
||||
drop_debugger: true,
|
||||
pure_funcs: ['console.log'] //移除console
|
||||
}
|
||||
}
|
||||
});
|
||||
// This is the production configuration.
|
||||
// It compiles slowly and is focused on producing a fast and minimal bundle.
|
||||
// The development configuration is different and lives in a separate file.
|
||||
// 上线用的
|
||||
module.exports = {
|
||||
optimization: {
|
||||
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({}),terserPlugin],
|
||||
splitChunks: {
|
||||
chunks: "async",
|
||||
// 大于30KB才单独分离成chunk
|
||||
minSize: 30000,
|
||||
maxAsyncRequests: 5,
|
||||
maxInitialRequests: 3,
|
||||
name: true,
|
||||
cacheGroups: {
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
// vendors: {
|
||||
// name: 'vendors',
|
||||
// test: /[\\/]node_modules[\\/]/,
|
||||
// priority: -10,
|
||||
// chunks: "all"
|
||||
// }
|
||||
},
|
||||
},
|
||||
runtimeChunk: true,
|
||||
},
|
||||
bail: true,
|
||||
mode: "production",
|
||||
// devtool: false, //测试版
|
||||
devtool: shouldUseSourceMap?'source-map':false,
|
||||
entry: [require.resolve("./polyfills"), paths.appIndexJs],
|
||||
output: {
|
||||
path: paths.appBuild,
|
||||
globalObject: "this",
|
||||
filename: "./static/js/[name].[contenthash:8].js",
|
||||
chunkFilename: "./static/js/[name].[contenthash:8].chunk.js",
|
||||
publicPath,
|
||||
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: (info) =>
|
||||
path
|
||||
.relative(paths.appSrc, info.absoluteResourcePath)
|
||||
.replace(/\\/g, "/"),
|
||||
},
|
||||
externals: {
|
||||
'alex': 'Alex',
|
||||
"react": "React",
|
||||
"react-dom": "ReactDOM",
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ["node_modules", paths.appNodeModules].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||
alias: {
|
||||
educoder: __dirname + "/../src/common/educoder.js",
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
},
|
||||
plugins: [
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
new ReactLoadablePlugin({
|
||||
filename: './react-loadable.json',
|
||||
}),
|
||||
// ["transform-remove-console"]
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
enforce: "pre",
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: eslintFormatter,
|
||||
eslintPath: require.resolve("eslint"),
|
||||
},
|
||||
loader: require.resolve("eslint-loader"),
|
||||
},
|
||||
],
|
||||
include: paths.appSrc,
|
||||
},
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
// match the requirements. When no loader matches it will fall
|
||||
// back to the "file" loader at the end of the loader list.
|
||||
oneOf: [
|
||||
// "url" loader works just like "file" loader but it also embeds
|
||||
// assets smaller than specified size as data URLs to avoid requests.
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: require.resolve("url-loader"),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
include: paths.appSrc,
|
||||
exclude: /node_modules/,
|
||||
loader: require.resolve("babel-loader"),
|
||||
options: {
|
||||
compact: true,
|
||||
plugins: [
|
||||
[
|
||||
"import",
|
||||
{
|
||||
libraryName: "antd",
|
||||
libraryDirectory: "es",
|
||||
style: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
ident: "postcss",
|
||||
plugins: () => [
|
||||
require("postcss-flexbugs-fixes"),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
">1%",
|
||||
"last 4 versions",
|
||||
"Firefox ESR",
|
||||
"not ie < 9", // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: "no-2009",
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("sass-loader"),
|
||||
},
|
||||
{
|
||||
loader: 'sass-resources-loader',
|
||||
options: {
|
||||
resources: ['src/global.scss']
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
}, {
|
||||
loader: 'css-loader', // translates CSS into CommonJS
|
||||
}, {
|
||||
loader: 'less-loader', // compiles Less to CSS
|
||||
options: {
|
||||
modifyVars: {
|
||||
'primary-color': '#2149d4',
|
||||
'link-color': '#2149d4',
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
}]
|
||||
},
|
||||
// "file" loader makes sure assets end up in the `build` folder.
|
||||
// When you `import` an asset, you get its filename.
|
||||
// This loader doesn't use a "test" so it will catch all modules
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
loader: require.resolve("file-loader"),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// it's runtime that would otherwise processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: "static/media/[name].[contenthash:8].[ext]",
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: paths.appHtml,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}),
|
||||
new webpack.DefinePlugin({ ...env.stringified, __SERVER__: 'false',__CLIENT__: 'true' }),
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||
// It is absolutely essential that NODE_ENV was set to production here.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "static/css/[name].[contenthash:8].css",
|
||||
chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
|
||||
}),
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
new ManifestPlugin({
|
||||
fileName: "asset-manifest.json",
|
||||
}),
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the Webpack build.
|
||||
new SWPrecacheWebpackPlugin({
|
||||
// By default, a cache-busting query parameter is appended to requests
|
||||
// used to populate the caches, to ensure the responses are fresh.
|
||||
// If a URL is already hashed by Webpack, then there is no concern
|
||||
// about it being stale, and the cache-busting can be skipped.
|
||||
dontCacheBustUrlsMatching: /\.\w{8}\./,
|
||||
filename: "service-worker.js",
|
||||
logger(message) {
|
||||
if (message.indexOf("Total precache size is") === 0) {
|
||||
// This message occurs for every build and is a bit too noisy.
|
||||
return;
|
||||
}
|
||||
if (message.indexOf("Skipping static resource") === 0) {
|
||||
// This message obscures real errors so we ignore it.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2612
|
||||
return;
|
||||
}
|
||||
// console.log(message);
|
||||
},
|
||||
minify: true,
|
||||
// For unknown URLs, fallback to the index page
|
||||
navigateFallback: publicUrl + "/index.html",
|
||||
// Ignores URLs starting from /__ (useful for Firebase):
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
|
||||
navigateFallbackWhitelist: [/^(?!\/__).*/],
|
||||
// Don't precache sourcemaps (they're large) and build asset manifest:f
|
||||
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
|
||||
}),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
new MonacoWebpackPlugin({
|
||||
features: ["coreCommands", "find"],
|
||||
languages: ['plaintext','apex', 'azcli', 'bat', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'fsharp', 'go', 'handlebars', 'html', 'ini', 'java', 'javascript', 'json', 'less', 'lua', 'markdown', 'msdax', 'mysql', 'objective', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'ruby', 'rust', 'sb', 'scheme', 'scss', 'shell', 'solidity', 'sql', 'st', 'swift', 'typescript', 'vb', 'xml', 'yaml']
|
||||
}),
|
||||
new webpack.NamedChunksPlugin(),
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
],
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
dgram: "empty",
|
||||
fs: "empty",
|
||||
net: "empty",
|
||||
tls: "empty",
|
||||
child_process: "empty",
|
||||
},
|
||||
};
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
const autoprefixer = require("autoprefixer");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
|
||||
const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
|
||||
const eslintFormatter = require("react-dev-utils/eslintFormatter");
|
||||
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
|
||||
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
|
||||
const TerserJSPlugin = require("terser-webpack-plugin");
|
||||
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||
const TerserWebpackPlugin = require('terser-webpack-plugin');
|
||||
const paths = require("./paths");
|
||||
const getClientEnvironment = require("./env");
|
||||
|
||||
let publicPath = "/react/buildserver/";
|
||||
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
const shouldUseSourceMap = true;
|
||||
const env = getClientEnvironment(publicPath,'development');
|
||||
const nodeExternals = require("webpack-node-externals");
|
||||
|
||||
const serverConfig = {
|
||||
target:"node", //由于输出代码的运行环境是node,源码中依赖的node原生模块没必要打包进去;为了不把nodejs内置模块打包进输出文件中,例如: fs net模块等;
|
||||
mode: "development",
|
||||
entry: path.resolve(__dirname,"../server/index.js"),
|
||||
output:{
|
||||
filename:"bundle.js",
|
||||
path: path.resolve(__dirname,"../buildserver")
|
||||
},
|
||||
externals: [
|
||||
nodeExternals(), // 忽略 Node.js 核心模块
|
||||
// 自定义的外部模块
|
||||
{ "react": "React", "react-dom": "ReactDOM" ,"alex": "Alex"}
|
||||
],
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ["node_modules", paths.appNodeModules].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||
alias: {
|
||||
educoder: __dirname + "/../src/common/educoder.js",
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
},
|
||||
plugins: [
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
// ["transform-remove-console"]
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
enforce: "pre",
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: eslintFormatter,
|
||||
eslintPath: require.resolve("eslint"),
|
||||
},
|
||||
loader: require.resolve("eslint-loader"),
|
||||
},
|
||||
],
|
||||
include: [paths.appSrc, paths.serverSrc],
|
||||
},
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
// match the requirements. When no loader matches it will fall
|
||||
// back to the "file" loader at the end of the loader list.
|
||||
oneOf: [
|
||||
// "url" loader works just like "file" loader but it also embeds
|
||||
// assets smaller than specified size as data URLs to avoid requests.
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: require.resolve("url-loader"),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: "static/media/[name].[hash:8].[ext]",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
include: [paths.appSrc, paths.serverSrc],
|
||||
// exclude: /node_modules/,
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
presets: [
|
||||
require.resolve('@babel/preset-env'),
|
||||
require.resolve('@babel/preset-react'),
|
||||
],
|
||||
plugins: [
|
||||
require.resolve('@babel/plugin-transform-async-to-generator'),
|
||||
require.resolve('@babel/plugin-syntax-dynamic-import'),
|
||||
require.resolve('@babel/plugin-proposal-class-properties'),
|
||||
require.resolve('@babel/plugin-proposal-export-default-from'),
|
||||
require.resolve('@babel/plugin-transform-runtime'),
|
||||
require.resolve('@babel/plugin-transform-modules-commonjs'),
|
||||
require.resolve('babel-plugin-dynamic-import-webpack'),
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
ident: "postcss",
|
||||
plugins: () => [
|
||||
require("postcss-flexbugs-fixes"),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
">1%",
|
||||
"last 4 versions",
|
||||
"Firefox ESR",
|
||||
"not ie < 9", // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: "no-2009",
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
'isomorphic-style-loader',
|
||||
// {
|
||||
// loader: MiniCssExtractPlugin.loader,
|
||||
// options: {
|
||||
// publicPath,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("sass-loader"),
|
||||
},
|
||||
{
|
||||
loader: 'sass-resources-loader',
|
||||
options: {
|
||||
resources: ['src/global.scss']
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [{
|
||||
loader: 'isomorphic-style-loader',
|
||||
}, {
|
||||
loader: 'css-loader', // translates CSS into CommonJS
|
||||
}, {
|
||||
loader: 'less-loader', // compiles Less to CSS
|
||||
options: {
|
||||
modifyVars: {
|
||||
'primary-color': '#2149d4',
|
||||
'link-color': '#2149d4',
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
}]
|
||||
},
|
||||
// "file" loader makes sure assets end up in the `build` folder.
|
||||
// When you `import` an asset, you get its filename.
|
||||
// This loader doesn't use a "test" so it will catch all modules
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
loader: require.resolve("file-loader"),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// it's runtime that would otherwise processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: "static/media/[name].[contenthash:8].[ext]",
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({ ...env.stringified, __SERVER__: 'true',__CLIENT__: 'false' }),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "static/css/[name].[contenthash:8].css",
|
||||
chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
|
||||
}),
|
||||
new ManifestPlugin({
|
||||
fileName: "asset-manifest.json",
|
||||
}),
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
new MonacoWebpackPlugin({
|
||||
features: ["coreCommands", "find"],
|
||||
languages: ['plaintext','apex', 'azcli', 'bat', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'fsharp', 'go', 'handlebars', 'html', 'ini', 'java', 'javascript', 'json', 'less', 'lua', 'markdown', 'msdax', 'mysql', 'objective', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'ruby', 'rust', 'sb', 'scheme', 'scss', 'shell', 'solidity', 'sql', 'st', 'swift', 'typescript', 'vb', 'xml', 'yaml']
|
||||
}),
|
||||
new webpack.NamedChunksPlugin(),
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = serverConfig;
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
|
||||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
|
||||
const ignoredFiles = require('react-dev-utils/ignoredFiles');
|
||||
const config = require('./webpack.config.dev');
|
||||
const paths = require('./paths');
|
||||
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
|
||||
module.exports = function(proxy, allowedHost) {
|
||||
return {
|
||||
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
|
||||
// websites from potentially accessing local content through DNS rebinding:
|
||||
// https://github.com/webpack/webpack-dev-server/issues/887
|
||||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
||||
// However, it made several existing use cases such as development in cloud
|
||||
// environment or subdomains in development significantly more complicated:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2271
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2233
|
||||
// While we're investigating better solutions, for now we will take a
|
||||
// compromise. Since our WDS configuration only serves files in the `public`
|
||||
// folder we won't consider accessing them a vulnerability. However, if you
|
||||
// use the `proxy` feature, it gets more dangerous because it can expose
|
||||
// remote code execution vulnerabilities in backends like Django and Rails.
|
||||
// So we will disable the host check normally, but enable it if you have
|
||||
// specified the `proxy` setting. Finally, we let you override it if you
|
||||
// really know what you're doing with a special environment variable.
|
||||
disableHostCheck:
|
||||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
|
||||
// Enable gzip compression of generated files.
|
||||
compress: true,
|
||||
// Silence WebpackDevServer's own logs since they're generally not useful.
|
||||
// It will still show compile warnings and errors with this setting.
|
||||
clientLogLevel: 'none',
|
||||
// By default WebpackDevServer serves physical files from current directory
|
||||
// in addition to all the virtual build products that it serves from memory.
|
||||
// This is confusing because those files won’t automatically be available in
|
||||
// production build folder unless we copy them. However, copying the whole
|
||||
// project directory is dangerous because we may expose sensitive files.
|
||||
// Instead, we establish a convention that only files in `public` directory
|
||||
// get served. Our build script will copy `public` into the `build` folder.
|
||||
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
|
||||
// Note that we only recommend to use `public` folder as an escape hatch
|
||||
// for files like `favicon.ico`, `manifest.json`, and libraries that are
|
||||
// for some reason broken when imported through Webpack. If you just want to
|
||||
// use an image, put it in `src` and `import` it from JavaScript instead.
|
||||
contentBase: paths.appPublic,
|
||||
// By default files from `contentBase` will not trigger a page reload.
|
||||
watchContentBase: true,
|
||||
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
|
||||
// for the WebpackDevServer client so it can learn when the files were
|
||||
// updated. The WebpackDevServer client is included as an entry point
|
||||
// in the Webpack development configuration. Note that only changes
|
||||
// to CSS are currently hot reloaded. JS changes will refresh the browser.
|
||||
hot: true,
|
||||
// It is important to tell WebpackDevServer to use the same "root" path
|
||||
// as we specified in the config. In development, we always serve from /.
|
||||
publicPath: config.output.publicPath,
|
||||
// WebpackDevServer is noisy by default so we emit custom message instead
|
||||
// by listening to the compiler events with `compiler.plugin` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/293
|
||||
// src/node_modules is not ignored to support absolute imports
|
||||
// https://github.com/facebookincubator/create-react-app/issues/1065
|
||||
watchOptions: {
|
||||
ignored: ignoredFiles(paths.appSrc),
|
||||
},
|
||||
// Enable HTTPS if the HTTPS environment variable is set to 'true'
|
||||
https: protocol === 'https',
|
||||
host: host,
|
||||
overlay: false,
|
||||
historyApiFallback: {
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
},
|
||||
public: allowedHost,
|
||||
proxy,
|
||||
before(app) {
|
||||
// This lets us open files from the runtime error overlay.
|
||||
app.use(errorOverlayMiddleware());
|
||||
// This service worker file is effectively a 'no-op' that will reset any
|
||||
// previous service worker registered for the same host:port combination.
|
||||
// We do this in development to avoid hitting the production cache if
|
||||
// it used the same host and port.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
|
||||
app.use(noopServiceWorkerMiddleware());
|
||||
},
|
||||
};
|
||||
};
|
||||
262
package.json
|
|
@ -1,262 +0,0 @@
|
|||
{
|
||||
"name": "forge",
|
||||
"version": "3.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.0.0",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.23.3",
|
||||
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
|
||||
"@babel/plugin-proposal-function-sent": "^7.0.0",
|
||||
"@babel/plugin-proposal-json-strings": "^7.0.0",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
|
||||
"@babel/plugin-syntax-import-meta": "^7.0.0",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.0.0",
|
||||
"@babel/plugin-transform-runtime": "^7.23.6",
|
||||
"@babel/preset-env": "^7.23.6",
|
||||
"@babel/preset-react": "^7.23.3",
|
||||
"@babel/preset-stage-2": "^7.8.3",
|
||||
"@babel/runtime-corejs3": "^7.23.6",
|
||||
"@monaco-editor/react": "^2.3.0",
|
||||
"@novnc/novnc": "^1.1.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-react": "^1.0.6",
|
||||
"actioncable": "^5.2.4-3",
|
||||
"ahooks": "^2.10.14",
|
||||
"antd": "^3.26.15",
|
||||
"array-flatten": "^2.1.2",
|
||||
"autoprefixer": "7.1.6",
|
||||
"axios": "^0.24.0",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-jest": "^23.4.2",
|
||||
"babel-plugin-antd": "^0.5.1",
|
||||
"babel-plugin-dynamic-import-webpack": "^1.1.0",
|
||||
"bizcharts": "^3.5.8",
|
||||
"bundle-loader": "^0.5.6",
|
||||
"chalk": "1.1.3",
|
||||
"classnames": "^2.2.5",
|
||||
"clipboard": "^2.0.8",
|
||||
"code-prettify": "^0.1.0",
|
||||
"codemirror": "^5.64.0",
|
||||
"connect-timeout": "^1.9.0",
|
||||
"connected-react-router": "4.4.1",
|
||||
"core-js": "^3.34.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dompurify": "^2.3.3",
|
||||
"dotenv": "4.0.0",
|
||||
"dotenv-expand": "4.2.0",
|
||||
"echarts": "^4.9.0",
|
||||
"echarts-gl": "^1.1.2",
|
||||
"echarts-wordcloud": "^2.0.0",
|
||||
"editor.md": "^1.5.0",
|
||||
"express": "^4.18.2",
|
||||
"flv.js": "^1.5.0",
|
||||
"fs-extra": "3.0.1",
|
||||
"gsap": "^3.14.2",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"i18next": "^23.4.5",
|
||||
"immutability-helper": "^2.6.6",
|
||||
"install": "^0.12.2",
|
||||
"intersection-observer": "^0.12.2",
|
||||
"isomorphic-style-loader": "^5.3.2",
|
||||
"jest": "20.0.4",
|
||||
"jquery": "^3.7.1",
|
||||
"js-base64": "^2.5.2",
|
||||
"js2wordcloud": "^1.1.12",
|
||||
"jsdom": "^15.2.1",
|
||||
"katex": "^0.11.1",
|
||||
"less": "^3.13.1",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.6.8",
|
||||
"marked": "^2.1.0",
|
||||
"material-ui": "^1.0.0-beta.40",
|
||||
"md5": "^2.2.1",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"moment": "^2.23.0",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"monaco-editor-webpack-plugin": "^1.9.0",
|
||||
"nodemon": "^3.0.3",
|
||||
"numeral": "^2.0.6",
|
||||
"nvm": "0.0.4",
|
||||
"object-assign": "4.1.1",
|
||||
"p-queue": "^9.2.0",
|
||||
"papaparse": "^5.3.2",
|
||||
"pinyin": "^4.0.0-alpha.0",
|
||||
"postcss-flexbugs-fixes": "3.2.0",
|
||||
"promise": "8.0.1",
|
||||
"prop-types": "^15.6.1",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"qs": "^6.9.3",
|
||||
"quill": "^1.3.7",
|
||||
"quill-delta-to-html": "^0.11.0",
|
||||
"raf": "3.4.0",
|
||||
"rc-form": "^2.4.11",
|
||||
"rc-pagination": "^1.21.0",
|
||||
"rc-rate": "^2.6.0",
|
||||
"rc-select": "^8.0.12",
|
||||
"rc-tree": "^1.15.3",
|
||||
"rc-upload": "^2.9.4",
|
||||
"react": "^16.13.1",
|
||||
"react-beautiful-dnd": "^10.0.4",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-codemirror2": "^6.0.1",
|
||||
"react-color": "^2.18.0",
|
||||
"react-content-loader": "^3.1.1",
|
||||
"react-cookies": "^0.1.1",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-countup": "^6.1.0",
|
||||
"react-cropper": "^2.1.8",
|
||||
"react-datepicker": "^2.14.1",
|
||||
"react-dev-utils": "^9.2.0-next.80",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-hot-loader": "^4.12.20",
|
||||
"react-i18next": "^13.2.0",
|
||||
"react-infinite-scroller": "^1.2.4",
|
||||
"react-loadable": "^5.3.1",
|
||||
"react-monaco-editor": "0.37",
|
||||
"react-player": "^1.15.3",
|
||||
"react-redux": "5.0.7",
|
||||
"react-resizable": "^1.10.1",
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-config": "^5.1.1",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-slick": "^0.28.1",
|
||||
"react-split-pane": "^0.1.91",
|
||||
"react-svg": "^16.3.0",
|
||||
"react-url-query": "^1.5.0",
|
||||
"react-zmage": "^0.8.5-beta.31",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "2.3.0",
|
||||
"rsuite": "^4.3.4",
|
||||
"sass": "^1.70.0",
|
||||
"scroll-into-view": "^1.14.2",
|
||||
"scrollama": "^3.2.0",
|
||||
"sha1": "^1.1.1",
|
||||
"showdown": "^1.9.1",
|
||||
"showdown-katex": "^0.8.0",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"spark-md5": "^3.0.2",
|
||||
"store": "^2.0.12",
|
||||
"styled-components": "^4.4.1",
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"weixin-js-sdk": "^1.6.0",
|
||||
"whatwg-fetch": "2.0.3",
|
||||
"winston": "^3.11.0",
|
||||
"winston-daily-rotate-file": "^4.7.1",
|
||||
"wrap-md-editor": "^0.2.20",
|
||||
"xss": "^1.0.14",
|
||||
"xterm": "4.8.1",
|
||||
"xterm-addon-fit": "0.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node scripts/start.js",
|
||||
"build": "cross-env NODE_ENV=production babel-node --max_old_space_size=15360 scripts/build.js",
|
||||
"build:server": "cross-env NODE_ENV=production webpack --config config/webpack.server.js",
|
||||
"build:dll": "webpack --config=./config/webpack.dll.config.js",
|
||||
"test-build": "cross-env NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
|
||||
"pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js",
|
||||
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
|
||||
"ana": "webpack-bundle-analyzer ./stats.json",
|
||||
"analyze": "npm run build -- --stats && webpack-bundle-analyzer build/bundle-stats.json",
|
||||
"analyz": "NODE_ENV=production npm_config_report=true npm run build",
|
||||
"dev": "npm-run-all --parallel dev:**",
|
||||
"dev:server": "cross-env NODE_ENV=dev nodemon --exec babel-node \"./buildserver/bundle.js\" --watch config --watch server",
|
||||
"test:build:server": "cross-env NODE_ENV=localtest webpack --config config/webpack.server.js",
|
||||
"dev:build:server": "cross-env NODE_ENV=dev webpack --config config/webpack.server.js",
|
||||
"pm2": "pm2 start pm2.json"
|
||||
},
|
||||
"jest": {
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.{js,jsx,mjs}"
|
||||
],
|
||||
"setupFiles": [
|
||||
"<rootDir>/config/polyfills.js"
|
||||
],
|
||||
"testMatch": [
|
||||
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
|
||||
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
|
||||
],
|
||||
"testEnvironment": "node",
|
||||
"testURL": "http://172.20.32.203:4000",
|
||||
"transform": {
|
||||
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
|
||||
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
|
||||
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^react-native$": "react-native-web"
|
||||
},
|
||||
"moduleFileExtensions": [
|
||||
"web.js",
|
||||
"mjs",
|
||||
"js",
|
||||
"json",
|
||||
"web.jsx",
|
||||
"jsx",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"proxy": "http://172.20.32.203:4000/",
|
||||
"port": "3007",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.6",
|
||||
"@babel/node": "^7.0.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.0.0",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/runtime": "^7.0.0-beta.46",
|
||||
"babel-loader": "^8.3.0",
|
||||
"babel-plugin-import": "^1.13.0",
|
||||
"babel-preset-react-app": "^3.1.1",
|
||||
"babel-upgrade": "^1.0.1",
|
||||
"case-sensitive-paths-webpack-plugin": "2.1.1",
|
||||
"compression-webpack-plugin": "^1.1.12",
|
||||
"concat": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^3.5.2",
|
||||
"eslint": "4.10.0",
|
||||
"eslint-config-react-app": "^2.1.0",
|
||||
"eslint-loader": "^4.0.0",
|
||||
"eslint-plugin-flowtype": "2.39.1",
|
||||
"eslint-plugin-import": "2.8.0",
|
||||
"eslint-plugin-jsx-a11y": "5.1.1",
|
||||
"eslint-plugin-react": "7.4.0",
|
||||
"file-loader": "^6.0.0",
|
||||
"happypack": "^5.0.1",
|
||||
"html-webpack-plugin": "^4.0.4",
|
||||
"less-loader": "^4.1.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"postcss-loader": "2.0.8",
|
||||
"purgecss": "^2.1.2",
|
||||
"react-json-view": "^1.21.3",
|
||||
"reqwest": "^2.0.5",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"sass-loader": "7.3.1",
|
||||
"sass-resources-loader": "^2.2.5",
|
||||
"style-loader": "0.19.0",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"terser-webpack-plugin": "^2.3.8",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"url-loader": "0.6.2",
|
||||
"webpack": "^4.42.1",
|
||||
"webpack-bundle-analyzer": "^3.7.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.2.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "8.12.0"
|
||||
}
|
||||
}
|
||||
15
pm2.json
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"apps": [{
|
||||
"name": "gitlink-ssr",
|
||||
"script": "buildserver/bundle.js",
|
||||
"watch": false,
|
||||
"log_date_format": "YYYY-MM-DD HH:mm Z",
|
||||
"exec_mode": "cluster",
|
||||
"max_memory_restart": "300M",
|
||||
"env": {
|
||||
"NODE_ENV": "production",
|
||||
"PORT": "8081"
|
||||
},
|
||||
"instances": 4
|
||||
}]
|
||||
}
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* KindEditor - WYSIWYG HTML Editor for Internet
|
||||
* Copyright (C) 2006-2011 kindsoft.net
|
||||
*
|
||||
* @author Roddy <luolonghao@gmail.com>
|
||||
* @site http://www.kindsoft.net/
|
||||
* @licence http://www.kindsoft.net/license.php
|
||||
*******************************************************************************/
|
||||
|
||||
KindEditor.lang({
|
||||
imagedirectupload:'本地图片',
|
||||
more: '切换到更多功能',
|
||||
less: '切换到简单功能',
|
||||
source : 'HTML代码',
|
||||
preview : '预览',
|
||||
undo : '后退(Ctrl+Z)',
|
||||
redo : '前进(Ctrl+Y)',
|
||||
cut : '剪切(Ctrl+X)',
|
||||
copy : '复制(Ctrl+C)',
|
||||
paste : '粘贴(Ctrl+V)',
|
||||
plainpaste : '粘贴为无格式文本',
|
||||
wordpaste : '从Word粘贴',
|
||||
selectall : '全选(Ctrl+A)',
|
||||
justifyleft : '左对齐',
|
||||
justifycenter : '居中',
|
||||
justifyright : '右对齐',
|
||||
justifyfull : '两端对齐',
|
||||
insertorderedlist : '编号',
|
||||
insertunorderedlist : '项目符号',
|
||||
indent : '增加缩进',
|
||||
outdent : '减少缩进',
|
||||
subscript : '下标',
|
||||
superscript : '上标',
|
||||
formatblock : '段落',
|
||||
fontname : '字体',
|
||||
fontsize : '文字大小',
|
||||
forecolor : '文字颜色',
|
||||
hilitecolor : '文字背景',
|
||||
bold : '粗体(Ctrl+B)',
|
||||
italic : '斜体(Ctrl+I)',
|
||||
underline : '下划线(Ctrl+U)',
|
||||
strikethrough : '删除线',
|
||||
removeformat : '删除格式',
|
||||
image : '图片',
|
||||
multiimage : '批量图片上传',
|
||||
flash : 'Flash',
|
||||
media : '视音频',
|
||||
table : '表格',
|
||||
tablecell : '单元格',
|
||||
hr : '插入横线',
|
||||
emoticons : '插入表情',
|
||||
link : '超级链接',
|
||||
unlink : '取消超级链接',
|
||||
fullscreen : '全屏显示',
|
||||
about : '关于',
|
||||
print : '打印(Ctrl+P)',
|
||||
filemanager : '文件空间',
|
||||
code : '插入程序代码',
|
||||
map : 'Google地图',
|
||||
baidumap : '百度地图',
|
||||
lineheight : '行距',
|
||||
clearhtml : '清理HTML代码',
|
||||
pagebreak : '插入分页符',
|
||||
quickformat : '一键排版',
|
||||
insertfile : '插入文件',
|
||||
template : '插入模板',
|
||||
anchor : '锚点',
|
||||
yes : '确定',
|
||||
no : '取消',
|
||||
close : '关闭',
|
||||
editImage : '图片属性',
|
||||
deleteImage : '删除图片',
|
||||
editFlash : 'Flash属性',
|
||||
deleteFlash : '删除Flash',
|
||||
editMedia : '视音频属性',
|
||||
deleteMedia : '删除视音频',
|
||||
editLink : '超级链接属性',
|
||||
deleteLink : '取消超级链接',
|
||||
editAnchor : '锚点属性',
|
||||
deleteAnchor : '删除锚点',
|
||||
tableprop : '表格属性',
|
||||
tablecellprop : '单元格属性',
|
||||
tableinsert : '插入表格',
|
||||
tabledelete : '删除表格',
|
||||
tablecolinsertleft : '左侧插入列',
|
||||
tablecolinsertright : '右侧插入列',
|
||||
tablerowinsertabove : '上方插入行',
|
||||
tablerowinsertbelow : '下方插入行',
|
||||
tablerowmerge : '向下合并单元格',
|
||||
tablecolmerge : '向右合并单元格',
|
||||
tablerowsplit : '拆分行',
|
||||
tablecolsplit : '拆分列',
|
||||
tablecoldelete : '删除列',
|
||||
tablerowdelete : '删除行',
|
||||
noColor : '无颜色',
|
||||
pleaseSelectFile : '请选择文件。',
|
||||
invalidImg : "请输入有效的URL地址。\n只允许jpg,gif,bmp,png格式。",
|
||||
invalidMedia : "请输入有效的URL地址。\n只允许swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb格式。",
|
||||
invalidWidth : "宽度必须为数字。",
|
||||
invalidHeight : "高度必须为数字。",
|
||||
invalidBorder : "边框必须为数字。",
|
||||
invalidUrl : "请输入有效的URL地址。",
|
||||
invalidRows : '行数为必选项,只允许输入大于0的数字。',
|
||||
invalidCols : '列数为必选项,只允许输入大于0的数字。',
|
||||
invalidPadding : '边距必须为数字。',
|
||||
invalidSpacing : '间距必须为数字。',
|
||||
invalidJson : '服务器发生故障。',
|
||||
uploadSuccess : '上传成功。',
|
||||
cutError : '您的浏览器安全设置不允许使用剪切操作,请使用快捷键(Ctrl+X)来完成。',
|
||||
copyError : '您的浏览器安全设置不允许使用复制操作,请使用快捷键(Ctrl+C)来完成。',
|
||||
pasteError : '您的浏览器安全设置不允许使用粘贴操作,请使用快捷键(Ctrl+V)来完成。',
|
||||
ajaxLoading : '加载中,请稍候 ...',
|
||||
uploadLoading : '上传中,请稍候 ...',
|
||||
uploadError : '上传错误',
|
||||
'plainpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',
|
||||
'wordpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',
|
||||
'code.pleaseInput' : '请输入程序代码。',
|
||||
'link.url' : 'URL',
|
||||
'link.linkType' : '打开类型',
|
||||
'link.newWindow' : '新窗口',
|
||||
'link.selfWindow' : '当前窗口',
|
||||
'flash.url' : 'URL',
|
||||
'flash.width' : '宽度',
|
||||
'flash.height' : '高度',
|
||||
'flash.upload' : '上传',
|
||||
'flash.viewServer' : '文件空间',
|
||||
'media.url' : 'URL',
|
||||
'media.width' : '宽度',
|
||||
'media.height' : '高度',
|
||||
'media.autostart' : '自动播放',
|
||||
'media.upload' : '上传',
|
||||
'media.viewServer' : '文件空间',
|
||||
'image.remoteImage' : '网络图片',
|
||||
'image.localImage' : '本地上传',
|
||||
'image.remoteUrl' : '图片地址',
|
||||
'image.localUrl' : '上传文件',
|
||||
'image.size' : '图片大小',
|
||||
'image.width' : '宽',
|
||||
'image.height' : '高',
|
||||
'image.resetSize' : '重置大小',
|
||||
'image.align' : '对齐方式',
|
||||
'image.defaultAlign' : '默认方式',
|
||||
'image.leftAlign' : '左对齐',
|
||||
'image.rightAlign' : '右对齐',
|
||||
'image.imgTitle' : '图片说明',
|
||||
'image.upload' : '浏览...',
|
||||
'image.viewServer' : '图片空间',
|
||||
'multiimage.uploadDesc' : '允许用户同时上传<%=uploadLimit%>张图片,单张图片容量不超过<%=sizeLimit%>',
|
||||
'multiimage.startUpload' : '开始上传',
|
||||
'multiimage.clearAll' : '全部清空',
|
||||
'multiimage.insertAll' : '全部插入',
|
||||
'multiimage.queueLimitExceeded' : '文件数量超过限制。',
|
||||
'multiimage.fileExceedsSizeLimit' : '文件大小超过限制。',
|
||||
'multiimage.zeroByteFile' : '无法上传空文件。',
|
||||
'multiimage.invalidFiletype' : '文件类型不正确。',
|
||||
'multiimage.unknownError' : '发生异常,无法上传。',
|
||||
'multiimage.pending' : '等待上传',
|
||||
'multiimage.uploadError' : '上传失败',
|
||||
'filemanager.emptyFolder' : '空文件夹',
|
||||
'filemanager.moveup' : '移到上一级文件夹',
|
||||
'filemanager.viewType' : '显示方式:',
|
||||
'filemanager.viewImage' : '缩略图',
|
||||
'filemanager.listImage' : '详细信息',
|
||||
'filemanager.orderType' : '排序方式:',
|
||||
'filemanager.fileName' : '名称',
|
||||
'filemanager.fileSize' : '大小',
|
||||
'filemanager.fileType' : '类型',
|
||||
'insertfile.url' : 'URL',
|
||||
'insertfile.title' : '文件说明',
|
||||
'insertfile.upload' : '上传',
|
||||
'insertfile.viewServer' : '文件空间',
|
||||
'table.cells' : '单元格数',
|
||||
'table.rows' : '行数',
|
||||
'table.cols' : '列数',
|
||||
'table.size' : '大小',
|
||||
'table.width' : '宽度',
|
||||
'table.height' : '高度',
|
||||
'table.percent' : '%',
|
||||
'table.px' : 'px',
|
||||
'table.space' : '边距间距',
|
||||
'table.padding' : '边距',
|
||||
'table.spacing' : '间距',
|
||||
'table.align' : '对齐方式',
|
||||
'table.textAlign' : '水平对齐',
|
||||
'table.verticalAlign' : '垂直对齐',
|
||||
'table.alignDefault' : '默认',
|
||||
'table.alignLeft' : '左对齐',
|
||||
'table.alignCenter' : '居中',
|
||||
'table.alignRight' : '右对齐',
|
||||
'table.alignTop' : '顶部',
|
||||
'table.alignMiddle' : '中部',
|
||||
'table.alignBottom' : '底部',
|
||||
'table.alignBaseline' : '基线',
|
||||
'table.border' : '边框',
|
||||
'table.borderWidth' : '边框',
|
||||
'table.borderColor' : '颜色',
|
||||
'table.backgroundColor' : '背景颜色',
|
||||
'map.address' : '地址: ',
|
||||
'map.search' : '搜索',
|
||||
'baidumap.address' : '地址: ',
|
||||
'baidumap.search' : '搜索',
|
||||
'baidumap.insertDynamicMap' : '插入动态地图',
|
||||
'anchor.name' : '锚点名称',
|
||||
'formatblock.formatBlock' : {
|
||||
h1 : '标题 1',
|
||||
h2 : '标题 2',
|
||||
h3 : '标题 3',
|
||||
h4 : '标题 4',
|
||||
p : '正 文'
|
||||
},
|
||||
'fontname.fontName' : {
|
||||
'SimSun' : '宋体',
|
||||
'NSimSun' : '新宋体',
|
||||
'FangSong_GB2312' : '仿宋_GB2312',
|
||||
'KaiTi_GB2312' : '楷体_GB2312',
|
||||
'SimHei' : '黑体',
|
||||
'Microsoft YaHei' : '微软雅黑',
|
||||
'Arial' : 'Arial',
|
||||
'Arial Black' : 'Arial Black',
|
||||
'Times New Roman' : 'Times New Roman',
|
||||
'Courier New' : 'Courier New',
|
||||
'Tahoma' : 'Tahoma',
|
||||
'Verdana' : 'Verdana'
|
||||
},
|
||||
'lineheight.lineHeight' : [
|
||||
{'1' : '单倍行距'},
|
||||
{'1.5' : '1.5倍行距'},
|
||||
{'2' : '2倍行距'},
|
||||
{'2.5' : '2.5倍行距'},
|
||||
{'3' : '3倍行距'}
|
||||
],
|
||||
'template.selectTemplate' : '可选模板',
|
||||
'template.replaceContent' : '替换当前内容',
|
||||
'template.fileList' : {
|
||||
'1.html' : '图片和文字',
|
||||
'2.html' : '表格',
|
||||
'3.html' : '项目编号'
|
||||
}
|
||||
}, 'zh_CN');
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* KindEditor - WYSIWYG HTML Editor for Internet
|
||||
* Copyright (C) 2006-2011 kindsoft.net
|
||||
*
|
||||
* @author Roddy <luolonghao@gmail.com>
|
||||
* @site http://www.kindsoft.net/
|
||||
* @licence http://www.kindsoft.net/license.php
|
||||
*******************************************************************************/
|
||||
|
||||
KindEditor.plugin('autoheight', function(K) {
|
||||
var self = this;
|
||||
//self.autoHeightMode = true;
|
||||
if (!self.autoHeightMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
var minHeight;
|
||||
|
||||
function hideScroll() {
|
||||
var edit = self.edit;
|
||||
var body = edit.doc.body;
|
||||
edit.iframe[0].scroll = 'no';
|
||||
body.style.overflowY = 'hidden';
|
||||
}
|
||||
|
||||
function resetHeight() {
|
||||
var edit = self.edit;
|
||||
var body = edit.doc.body;
|
||||
edit.iframe.height(minHeight);
|
||||
|
||||
//最高418 超过用滚动条
|
||||
self.resize(null, Math.max(
|
||||
(K.IE ? body.scrollHeight : body.offsetHeight) > 385 ? 385+33 : (K.IE ? body.scrollHeight : body.offsetHeight)
|
||||
+ 33, minHeight));
|
||||
|
||||
if( self.height == "418px" ){
|
||||
edit.iframe[0].scroll = 'yes';
|
||||
body.style.overflowY = 'auto';
|
||||
}
|
||||
else{
|
||||
hideScroll();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
minHeight = K.removeUnit(self.height);
|
||||
|
||||
self.edit.afterChange(resetHeight);
|
||||
hideScroll();
|
||||
var edit = self.edit;
|
||||
var body = edit.doc.body;
|
||||
edit.iframe.height(minHeight);
|
||||
self.resize(null, Math.max(
|
||||
((K.IE ? body.scrollHeight : body.offsetHeight) > 250 ? 250 : (K.IE ? body.scrollHeight : body.offsetHeight)) //限制初始化太高的情况
|
||||
+ 33, minHeight));
|
||||
}
|
||||
|
||||
if (self.isCreated) {
|
||||
init();
|
||||
} else {
|
||||
self.afterCreate(init);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 如何实现真正的自动高度?
|
||||
* 修改编辑器高度之后,再次获取body内容高度时,最小值只会是当前iframe的设置高度,这样就导致高度只增不减。
|
||||
* 所以每次获取body内容高度之前,先将iframe的高度重置为最小高度,这样就能获取body的实际高度。
|
||||
* 由此就实现了真正的自动高度
|
||||
* 测试:chrome、firefox、IE9、IE8
|
||||
* */
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
.ke-content {
|
||||
font-family: "微软雅黑","宋体";
|
||||
}
|
||||
.ke-content pre {
|
||||
font-size:9pt;
|
||||
font-family:Courier New,Arial;
|
||||
border:1px solid #ddd;
|
||||
border-left:5px solid #6CE26C;
|
||||
background:#f6f6f6;
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
.ke-content code {
|
||||
margin: 0 2px;
|
||||
padding: 0 5px;
|
||||
white-space: nowrap;
|
||||
border: 1px solid #DDD;
|
||||
background-color: #F6F6F6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.ke-content pre>code {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: pre;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ke-content pre code {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ke-content p {
|
||||
/*margin: 0 0 15px 0;*/
|
||||
/*margin-bottom:15pt;*/
|
||||
line-height:1.5;
|
||||
/*letter-spacing: 1px;*/
|
||||
}
|
||||
|
||||
.ke-content div.ref {border:1px solid #ddd;margin:0 0 10px 0;padding:2px;font-size:9pt;background:#ffe;}
|
||||
.ke-content div.ref h4 {margin:0;padding:1px 3px;background:#CC9966;color:#fff;font-size:9pt;font-weight:normal;}
|
||||
.ke-content div.ref .ref_body {margin:0;padding:2px;line-height:20px;color:#666;font-size:9pt;}
|
||||
|
||||
|
||||
.ke-content blockquote{background: none;border: none;padding: 0px;margin: 0 0 0 40px;}
|
||||
span.at {color:#269ac9;}
|
||||
span.at a{color:#269ac9;text-decoration: none;}
|
||||
|
||||
/*yk*/
|
||||
.ke-content ol li{list-style-type: decimal;}
|
||||
.ke-content ul li{list-style-type: disc;}
|
||||
.ke-content ol,.ke-content ul,.ke-content h1,.ke-content h2,.ke-content h3,.ke-content h4{margin-top:0;margin-bottom: 0;}
|
||||
.ke-content a{color: #136ec2;}
|
||||
.ke-content a:link,.ke-content a:visited{text-decoration:none;}
|
||||
|
|
@ -1,361 +0,0 @@
|
|||
// Generated by CoffeeScript 1.9.0
|
||||
|
||||
/*
|
||||
paste.js is an interface to read data ( text / image ) from clipboard in different browsers. It also contains several hacks.
|
||||
https://github.com/layerssss/paste.js
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var $, Paste, createHiddenEditable, dataURLtoBlob;
|
||||
|
||||
$ = window.jQuery;
|
||||
|
||||
$.paste = function(pasteContainer) {
|
||||
var pm;
|
||||
if (typeof console !== "undefined" && console !== null) {
|
||||
console.log("DEPRECATED: This method is deprecated. Please use $.fn.pastableNonInputable() instead.");
|
||||
}
|
||||
pm = Paste.mountNonInputable(pasteContainer);
|
||||
return pm._container;
|
||||
};
|
||||
|
||||
$.fn.pastableNonInputable = function() {
|
||||
var el, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
el = this[_i];
|
||||
Paste.mountNonInputable(el);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
$.fn.pastableTextarea = function() {
|
||||
var el, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
el = this[_i];
|
||||
Paste.mountTextarea(el);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
$.fn.pastableContenteditable = function() {
|
||||
var el, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
el = this[_i];
|
||||
Paste.mountContenteditable(el);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
dataURLtoBlob = function(dataURL, sliceSize) {
|
||||
var b64Data, byteArray, byteArrays, byteCharacters, byteNumbers, contentType, i, m, offset, slice, _ref;
|
||||
if (sliceSize == null) {
|
||||
sliceSize = 512;
|
||||
}
|
||||
if (!(m = dataURL.match(/^data\:([^\;]+)\;base64\,(.+)$/))) {
|
||||
return null;
|
||||
}
|
||||
_ref = m, m = _ref[0], contentType = _ref[1], b64Data = _ref[2];
|
||||
byteCharacters = atob(b64Data);
|
||||
byteArrays = [];
|
||||
offset = 0;
|
||||
while (offset < byteCharacters.length) {
|
||||
slice = byteCharacters.slice(offset, offset + sliceSize);
|
||||
byteNumbers = new Array(slice.length);
|
||||
i = 0;
|
||||
while (i < slice.length) {
|
||||
byteNumbers[i] = slice.charCodeAt(i);
|
||||
i++;
|
||||
}
|
||||
byteArray = new Uint8Array(byteNumbers);
|
||||
byteArrays.push(byteArray);
|
||||
offset += sliceSize;
|
||||
}
|
||||
return new Blob(byteArrays, {
|
||||
type: contentType
|
||||
});
|
||||
};
|
||||
|
||||
createHiddenEditable = function() {
|
||||
return $(document.createElement('div')).attr('contenteditable', true).css({
|
||||
width: 1,
|
||||
height: 1,
|
||||
position: 'fixed',
|
||||
left: -100,
|
||||
overflow: 'hidden'
|
||||
});
|
||||
};
|
||||
|
||||
Paste = (function() {
|
||||
Paste.prototype._target = null;
|
||||
|
||||
Paste.prototype._container = null;
|
||||
|
||||
Paste.mountNonInputable = function(nonInputable) {
|
||||
var paste;
|
||||
paste = new Paste(createHiddenEditable().appendTo(nonInputable), nonInputable);
|
||||
$(nonInputable).on('click', (function(_this) {
|
||||
return function() {
|
||||
return paste._container.focus();
|
||||
};
|
||||
})(this));
|
||||
paste._container.on('focus', (function(_this) {
|
||||
return function() {
|
||||
return $(nonInputable).addClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
return paste._container.on('blur', (function(_this) {
|
||||
return function() {
|
||||
return $(nonInputable).removeClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
|
||||
Paste.mountTextarea = function(textarea) {
|
||||
var ctlDown, paste;
|
||||
if (-1 !== navigator.userAgent.toLowerCase().indexOf('chrome')) {
|
||||
return this.mountContenteditable(textarea);
|
||||
}
|
||||
paste = new Paste(createHiddenEditable().insertBefore(textarea), textarea);
|
||||
ctlDown = false;
|
||||
$(textarea).on('keyup', function(ev) {
|
||||
var _ref;
|
||||
if ((_ref = ev.keyCode) === 17 || _ref === 224) {
|
||||
return ctlDown = false;
|
||||
}
|
||||
});
|
||||
$(textarea).on('keydown', function(ev) {
|
||||
var _ref;
|
||||
if ((_ref = ev.keyCode) === 17 || _ref === 224) {
|
||||
ctlDown = true;
|
||||
}
|
||||
if (ctlDown && ev.keyCode === 86) {
|
||||
return paste._container.focus();
|
||||
}
|
||||
});
|
||||
$(paste._target).on('pasteImage', (function(_this) {
|
||||
return function() {
|
||||
return $(textarea).focus();
|
||||
};
|
||||
})(this));
|
||||
$(paste._target).on('pasteText', (function(_this) {
|
||||
return function() {
|
||||
return $(textarea).focus();
|
||||
};
|
||||
})(this));
|
||||
$(textarea).on('focus', (function(_this) {
|
||||
return function() {
|
||||
return $(textarea).addClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
return $(textarea).on('blur', (function(_this) {
|
||||
return function() {
|
||||
return $(textarea).removeClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
|
||||
Paste.mountContenteditable = function(contenteditable) {
|
||||
var paste;
|
||||
paste = new Paste(contenteditable, contenteditable);
|
||||
$(contenteditable).on('focus', (function(_this) {
|
||||
return function() {
|
||||
return $(contenteditable).addClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
return $(contenteditable).on('blur', (function(_this) {
|
||||
return function() {
|
||||
return $(contenteditable).removeClass('pastable-focus');
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
|
||||
function Paste(_at__container, _at__target) {
|
||||
this._container = _at__container;
|
||||
this._target = _at__target;
|
||||
this._container = $(this._container);
|
||||
this._target = $(this._target).addClass('pastable');
|
||||
this._container.on('paste', (function(_this) {
|
||||
return function(ev) {
|
||||
var clipboardData, file, item, reader, text, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _results;
|
||||
if (((_ref = ev.originalEvent) != null ? _ref.clipboardData : void 0) != null) {
|
||||
clipboardData = ev.originalEvent.clipboardData;
|
||||
if (clipboardData.items) {
|
||||
_ref1 = clipboardData.items;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
item = _ref1[_i];
|
||||
if (item.type.match(/^image\//)) {
|
||||
reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
return _this._handleImage(event.target.result);
|
||||
};
|
||||
reader.readAsDataURL(item.getAsFile());
|
||||
}
|
||||
if (item.type === 'text/plain') {
|
||||
item.getAsString(function(string) {
|
||||
return _this._target.trigger('pasteText', {
|
||||
text: string
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (-1 !== Array.prototype.indexOf.call(clipboardData.types, 'text/plain')) {
|
||||
text = clipboardData.getData('Text');
|
||||
_this._target.trigger('pasteText', {
|
||||
text: text
|
||||
});
|
||||
}
|
||||
_this._checkImagesInContainer(function(src) {
|
||||
return _this._handleImage(src);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (clipboardData = window.clipboardData) {
|
||||
if ((_ref2 = (text = clipboardData.getData('Text'))) != null ? _ref2.length : void 0) {
|
||||
return _this._target.trigger('pasteText', {
|
||||
text: text
|
||||
});
|
||||
} else {
|
||||
_ref3 = clipboardData.files;
|
||||
_results = [];
|
||||
for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
|
||||
file = _ref3[_j];
|
||||
_this._handleImage(URL.createObjectURL(file));
|
||||
_results.push(_this._checkImagesInContainer(function() {}));
|
||||
}
|
||||
return _results;
|
||||
}
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
Paste.prototype._handleImage = function(src) {
|
||||
var loader;
|
||||
loader = new Image();
|
||||
loader.onload = (function(_this) {
|
||||
return function() {
|
||||
var blob, canvas, ctx, dataURL;
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.width = loader.width;
|
||||
canvas.height = loader.height;
|
||||
ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
|
||||
dataURL = null;
|
||||
try {
|
||||
dataURL = canvas.toDataURL('image/png');
|
||||
blob = dataURLtoBlob(dataURL);
|
||||
} catch (_error) {}
|
||||
if (dataURL) {
|
||||
return _this._target.trigger('pasteImage', {
|
||||
blob: blob,
|
||||
dataURL: dataURL,
|
||||
width: loader.width,
|
||||
height: loader.height
|
||||
});
|
||||
}
|
||||
};
|
||||
})(this);
|
||||
return loader.src = src;
|
||||
};
|
||||
|
||||
Paste.prototype._checkImagesInContainer = function(cb) {
|
||||
var img, timespan, _i, _len, _ref;
|
||||
timespan = Math.floor(1000 * Math.random());
|
||||
_ref = this._container.find('img');
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
img = _ref[_i];
|
||||
img["_paste_marked_" + timespan] = true;
|
||||
}
|
||||
return setTimeout((function(_this) {
|
||||
return function() {
|
||||
var _j, _len1, _ref1, _results;
|
||||
_ref1 = _this._container.find('img');
|
||||
_results = [];
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
img = _ref1[_j];
|
||||
if (!img["_paste_marked_" + timespan]) {
|
||||
cb(img.src);
|
||||
}
|
||||
//firefox问题处理,因为采用了 pastableContenteditable 模式,故只需要删除默认的粘贴
|
||||
if ($(img).attr('src').startsWith('data:image/')) {
|
||||
_results.push($(img).remove());
|
||||
};
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
})(this), 1);
|
||||
};
|
||||
|
||||
return Paste;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
|
||||
KindEditor.plugin('paste', function(K) {
|
||||
var editor = this,
|
||||
name = 'paste';
|
||||
if(editor.edit == undefined || editor.edit.iframe == undefined){
|
||||
return;
|
||||
}
|
||||
var contentWindow = editor.edit.iframe[0].contentWindow;
|
||||
//var contentWindow = editor.iframeDoc;
|
||||
//var contentWindow = document.getElementsByTagName('iframe')[0].contentWindow;
|
||||
var nodeBody = contentWindow.document.getElementsByTagName('body')[0];
|
||||
console.log(nodeBody);
|
||||
$(nodeBody).pastableContenteditable();
|
||||
|
||||
dataURItoBlob = function(dataURI) {
|
||||
// convert base64/URLEncoded data component to raw binary data held in a string
|
||||
var byteString;
|
||||
if (dataURI.split(',')[0].indexOf('base64') >= 0)
|
||||
byteString = atob(dataURI.split(',')[1]);
|
||||
else
|
||||
byteString = unescape(dataURI.split(',')[1]);
|
||||
|
||||
// separate out the mime component
|
||||
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||
|
||||
// write the bytes of the string to a typed array
|
||||
var ia = new Uint8Array(byteString.length);
|
||||
for (var i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
|
||||
return new Blob([ia], {type:mimeString});
|
||||
};
|
||||
|
||||
$(nodeBody).on('pasteImage', function(ev, data) {
|
||||
console.log('pasteImage');
|
||||
console.log("dataURL: " + data.dataURL);
|
||||
console.log("width: " + data.width);
|
||||
console.log("height: " + data.height);
|
||||
var blob = dataURItoBlob(data.dataURL);
|
||||
if (data.blob !== null) {
|
||||
var data = new FormData();
|
||||
// data.append("imgFile",blob, "imageFilename.png");
|
||||
data.append("file",blob, "imageFilename.png");
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
url: '/kindeditor/upload?dir=image',
|
||||
url: '/api/attachments.json',
|
||||
contentType: false,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
console.log(data);
|
||||
// editor.exec('insertimage', JSON.parse(data).url);
|
||||
|
||||
// /api/attachments/227362
|
||||
editor.exec('insertimage', '/api/attachments/' + data.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
return;
|
||||
|
||||
});
|
||||
|
||||
|
|
@ -1,539 +0,0 @@
|
|||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 5081288 */
|
||||
src: url('iconfont.woff2?t=1764899187997') format('woff2'),
|
||||
url('iconfont.woff?t=1764899187997') format('woff'),
|
||||
url('iconfont.ttf?t=1764899187997') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-icon_blackarrow_hover:before {
|
||||
content: "\e78f";
|
||||
}
|
||||
|
||||
.icon-banben:before {
|
||||
content: "\e7a1";
|
||||
}
|
||||
|
||||
.icon-shoucang:before {
|
||||
content: "\e7a0";
|
||||
}
|
||||
|
||||
.icon-liulanliang:before {
|
||||
content: "\e79e";
|
||||
}
|
||||
|
||||
.icon-gongju:before {
|
||||
content: "\e79f";
|
||||
}
|
||||
|
||||
.icon-xiangmu:before {
|
||||
content: "\e79d";
|
||||
}
|
||||
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"id": "5081288",
|
||||
"name": "软件工厂专区",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "46273104",
|
||||
"name": "icon_blackarrow_hover",
|
||||
"font_class": "icon_blackarrow_hover",
|
||||
"unicode": "e78f",
|
||||
"unicode_decimal": 59279
|
||||
},
|
||||
{
|
||||
"icon_id": "46258083",
|
||||
"name": "版本",
|
||||
"font_class": "banben",
|
||||
"unicode": "e7a1",
|
||||
"unicode_decimal": 59297
|
||||
},
|
||||
{
|
||||
"icon_id": "46258084",
|
||||
"name": "收藏",
|
||||
"font_class": "shoucang",
|
||||
"unicode": "e7a0",
|
||||
"unicode_decimal": 59296
|
||||
},
|
||||
{
|
||||
"icon_id": "46258085",
|
||||
"name": "浏览量",
|
||||
"font_class": "liulanliang",
|
||||
"unicode": "e79e",
|
||||
"unicode_decimal": 59294
|
||||
},
|
||||
{
|
||||
"icon_id": "46258086",
|
||||
"name": "工具",
|
||||
"font_class": "gongju",
|
||||
"unicode": "e79f",
|
||||
"unicode_decimal": 59295
|
||||
},
|
||||
{
|
||||
"icon_id": "46258087",
|
||||
"name": "项目",
|
||||
"font_class": "xiangmu",
|
||||
"unicode": "e79d",
|
||||
"unicode_decimal": 59293
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,539 +0,0 @@
|
|||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
@font-face {
|
||||
font-family: "iconfont-color"; /* Project id 5169666 */
|
||||
/* Color fonts */
|
||||
src:
|
||||
url('iconfont.woff2?t=1778741571506') format('woff2'),
|
||||
url('iconfont.woff?t=1778741571506') format('woff'),
|
||||
url('iconfont.ttf?t=1778741571506') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont-color {
|
||||
font-family: "iconfont-color" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-colorqita:before {
|
||||
content: "\e7b3";
|
||||
}
|
||||
|
||||
.icon-coloryidongkaifa:before {
|
||||
content: "\e7b4";
|
||||
}
|
||||
|
||||
.icon-colordaimazhijian:before {
|
||||
content: "\e7b5";
|
||||
}
|
||||
|
||||
.icon-coloryunxiaogongju:before {
|
||||
content: "\e7b6";
|
||||
}
|
||||
|
||||
.icon-coloryouxiyule:before {
|
||||
content: "\e7b7";
|
||||
}
|
||||
|
||||
.icon-colorskill:before {
|
||||
content: "\e7b0";
|
||||
}
|
||||
|
||||
.icon-colorshujuji:before {
|
||||
content: "\e7b1";
|
||||
}
|
||||
|
||||
.icon-colordaimaku1:before {
|
||||
content: "\e7b2";
|
||||
}
|
||||
|
||||
.icon-colormoxingku:before {
|
||||
content: "\e7af";
|
||||
}
|
||||
|
||||
.icon-coloryinpin:before {
|
||||
content: "\e7ad";
|
||||
}
|
||||
|
||||
.icon-colorremenmoxing-1:before {
|
||||
content: "\e7a3";
|
||||
}
|
||||
|
||||
.icon-colorkexueyanjiuhejishufuwuye:before {
|
||||
content: "\e7ae";
|
||||
}
|
||||
|
||||
.icon-colora-zu18210:before {
|
||||
content: "\e7a6";
|
||||
}
|
||||
|
||||
.icon-colora-zu18240:before {
|
||||
content: "\e7a5";
|
||||
}
|
||||
|
||||
.icon-colora-zuixin1:before {
|
||||
content: "\e7a7";
|
||||
}
|
||||
|
||||
.icon-colorziranyuyanchuli:before {
|
||||
content: "\e7a8";
|
||||
}
|
||||
|
||||
.icon-colorshichangtuiguang-01:before {
|
||||
content: "\e7a4";
|
||||
}
|
||||
|
||||
.icon-coloryuyin:before {
|
||||
content: "\e7a9";
|
||||
}
|
||||
|
||||
.icon-colortuxiang:before {
|
||||
content: "\e7aa";
|
||||
}
|
||||
|
||||
.icon-colora-zu18213:before {
|
||||
content: "\e7ab";
|
||||
}
|
||||
|
||||
.icon-colorshipinbofang:before {
|
||||
content: "\e7ac";
|
||||
}
|
||||
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
{
|
||||
"id": "5169666",
|
||||
"name": "newForge-color",
|
||||
"font_family": "iconfont-color",
|
||||
"css_prefix_text": "icon-color",
|
||||
"description": "gitlink/红山开源 带颜色的icon",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "47487873",
|
||||
"name": "其他",
|
||||
"font_class": "qita",
|
||||
"unicode": "e7b3",
|
||||
"unicode_decimal": 59315
|
||||
},
|
||||
{
|
||||
"icon_id": "47487872",
|
||||
"name": "移动开发",
|
||||
"font_class": "yidongkaifa",
|
||||
"unicode": "e7b4",
|
||||
"unicode_decimal": 59316
|
||||
},
|
||||
{
|
||||
"icon_id": "47487870",
|
||||
"name": "代码质检",
|
||||
"font_class": "daimazhijian",
|
||||
"unicode": "e7b5",
|
||||
"unicode_decimal": 59317
|
||||
},
|
||||
{
|
||||
"icon_id": "47487871",
|
||||
"name": "云效工具",
|
||||
"font_class": "yunxiaogongju",
|
||||
"unicode": "e7b6",
|
||||
"unicode_decimal": 59318
|
||||
},
|
||||
{
|
||||
"icon_id": "47487869",
|
||||
"name": "游戏娱乐",
|
||||
"font_class": "youxiyule",
|
||||
"unicode": "e7b7",
|
||||
"unicode_decimal": 59319
|
||||
},
|
||||
{
|
||||
"icon_id": "47487614",
|
||||
"name": "skill",
|
||||
"font_class": "skill",
|
||||
"unicode": "e7b0",
|
||||
"unicode_decimal": 59312
|
||||
},
|
||||
{
|
||||
"icon_id": "47487615",
|
||||
"name": "数据集",
|
||||
"font_class": "shujuji",
|
||||
"unicode": "e7b1",
|
||||
"unicode_decimal": 59313
|
||||
},
|
||||
{
|
||||
"icon_id": "47487613",
|
||||
"name": "代码库",
|
||||
"font_class": "daimaku1",
|
||||
"unicode": "e7b2",
|
||||
"unicode_decimal": 59314
|
||||
},
|
||||
{
|
||||
"icon_id": "47487578",
|
||||
"name": "模型库",
|
||||
"font_class": "moxingku",
|
||||
"unicode": "e7af",
|
||||
"unicode_decimal": 59311
|
||||
},
|
||||
{
|
||||
"icon_id": "47470053",
|
||||
"name": "音频",
|
||||
"font_class": "yinpin",
|
||||
"unicode": "e7ad",
|
||||
"unicode_decimal": 59309
|
||||
},
|
||||
{
|
||||
"icon_id": "47470038",
|
||||
"name": "热门模型-1",
|
||||
"font_class": "remenmoxing-1",
|
||||
"unicode": "e7a3",
|
||||
"unicode_decimal": 59299
|
||||
},
|
||||
{
|
||||
"icon_id": "47470036",
|
||||
"name": "科学研究和技术服务业",
|
||||
"font_class": "kexueyanjiuhejishufuwuye",
|
||||
"unicode": "e7ae",
|
||||
"unicode_decimal": 59310
|
||||
},
|
||||
{
|
||||
"icon_id": "47470068",
|
||||
"name": "组 18210",
|
||||
"font_class": "a-zu18210",
|
||||
"unicode": "e7a6",
|
||||
"unicode_decimal": 59302
|
||||
},
|
||||
{
|
||||
"icon_id": "47470067",
|
||||
"name": "组 18240",
|
||||
"font_class": "a-zu18240",
|
||||
"unicode": "e7a5",
|
||||
"unicode_decimal": 59301
|
||||
},
|
||||
{
|
||||
"icon_id": "47470066",
|
||||
"name": "最新 (1)",
|
||||
"font_class": "a-zuixin1",
|
||||
"unicode": "e7a7",
|
||||
"unicode_decimal": 59303
|
||||
},
|
||||
{
|
||||
"icon_id": "47470060",
|
||||
"name": "自然语言处理",
|
||||
"font_class": "ziranyuyanchuli",
|
||||
"unicode": "e7a8",
|
||||
"unicode_decimal": 59304
|
||||
},
|
||||
{
|
||||
"icon_id": "47470052",
|
||||
"name": "市场推广-01",
|
||||
"font_class": "shichangtuiguang-01",
|
||||
"unicode": "e7a4",
|
||||
"unicode_decimal": 59300
|
||||
},
|
||||
{
|
||||
"icon_id": "47470056",
|
||||
"name": "语音",
|
||||
"font_class": "yuyin",
|
||||
"unicode": "e7a9",
|
||||
"unicode_decimal": 59305
|
||||
},
|
||||
{
|
||||
"icon_id": "47470055",
|
||||
"name": "图像",
|
||||
"font_class": "tuxiang",
|
||||
"unicode": "e7aa",
|
||||
"unicode_decimal": 59306
|
||||
},
|
||||
{
|
||||
"icon_id": "47470057",
|
||||
"name": "组 18213",
|
||||
"font_class": "a-zu18213",
|
||||
"unicode": "e7ab",
|
||||
"unicode_decimal": 59307
|
||||
},
|
||||
{
|
||||
"icon_id": "47470047",
|
||||
"name": "视频播放",
|
||||
"font_class": "shipinbofang",
|
||||
"unicode": "e7ac",
|
||||
"unicode_decimal": 59308
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
|
||||
.CodeMirror-merge {
|
||||
position: relative;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
|
||||
min-height:50px;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 48%; }
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 4%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
|
||||
|
||||
.CodeMirror-merge-pane {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
.CodeMirror-merge-pane-rightmost {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-gap {
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #515151;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-scrolllock-wrap {
|
||||
position: absolute;
|
||||
bottom: 0; left: 50%;
|
||||
}
|
||||
.CodeMirror-merge-scrolllock {
|
||||
position: relative;
|
||||
left: -50%;
|
||||
cursor: pointer;
|
||||
color: #d8d8d8;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
|
||||
position: absolute;
|
||||
left: 0; top: 0;
|
||||
right: 0; bottom: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #ce374b;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy-reverse {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #44c;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
|
||||
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
|
||||
|
||||
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-chunk { background: #9a6868; }
|
||||
.CodeMirror-merge-r-chunk-start { /*border-top: 1px solid #ee8; */}
|
||||
.CodeMirror-merge-r-chunk-end {/* border-bottom: 1px solid #ee8; */}
|
||||
.CodeMirror-merge-r-connect { fill:#9a6868;}
|
||||
|
||||
.CodeMirror-merge-l-chunk { background: #eef; }
|
||||
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
|
||||
|
||||
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
|
||||
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
|
||||
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
|
||||
|
||||
.CodeMirror-merge-collapsed-widget:before {
|
||||
content: "(...)";
|
||||
}
|
||||
.CodeMirror-merge-collapsed-widget {
|
||||
cursor: pointer;
|
||||
color: #88b;
|
||||
background: #eef;
|
||||
border: 1px solid #ddf;
|
||||
font-size: 90%;
|
||||
padding: 0 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
|
||||
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-hans-CN" class="notranslate translated-ltr" translate="no">
|
||||
|
||||
<head>
|
||||
<title>菌队可控开源社区</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="Keywords" content="菌队可控开源社区, git, 开源, 代码托管, 项目管理, 版本控制, 代码分享, 项目协作, 协同开发平台">
|
||||
<meta name="description" content="菌队可控开源社区 是一个新一代的开源创新服务平台,提供分布式协作开发、流水线运维、代码分析等功能,基于 Git 打造分布式代码托管环境。">
|
||||
<meta property="og:title" content="菌队可控开源社区" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image:alt" content="菌队可控开源社区" />
|
||||
<meta property="og:site_name" content="菌队可控开源社区" />
|
||||
<meta property="og:url" content="https://gitlink.org.cn/" />
|
||||
<meta property="og:image" content="https://www.gitlink.org.cn/images/logo.png" />
|
||||
<meta property="og:description" content="菌队可控开源社区 是一个新一代的开源创新服务平台,提供分布式协作开发、流水线运维、代码分析等功能,基于 Git 打造分布式代码托管环境。" />
|
||||
<meta name="keyboard-shortcuts-preference" content="all">
|
||||
<meta name="octolytics-dimension-user_login" content="菌队可控开源社区"></meta>
|
||||
<meta name="octolytics-dimension-repository_nwo" content="菌队可控开源社区"></meta>
|
||||
<meta name="octolytics-dimension-repository_network_root_nwo" content="菌队可控开源社区"></meta>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="referrer" content="always">
|
||||
<meta name="hostname" content="gitlink.org.cn">
|
||||
<meta name="keyboard-shortcuts-preference" content="all">
|
||||
<meta name="expected-hostname" content="gitlink.org.cn">
|
||||
<meta name="go-import" content="gitlink.org.cn git https://gitlink.org.cn">
|
||||
<!-- 按需引用viewport content -->
|
||||
<meta name="viewport" content="">
|
||||
<meta name="keyboard-shortcuts-preference" content="all">
|
||||
<meta name="octolytics-dimension-user_login" content="菌队可控开源社区"></meta>
|
||||
<meta name="octolytics-dimension-repository_nwo" content="菌队可控开源社区"></meta>
|
||||
<meta name="octolytics-dimension-repository_network_root_nwo" content="菌队可控开源社区"></meta>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="twitter:site" content="@gitlink">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="菌队可控开源社区">
|
||||
<meta name="twitter:description" content="菌队可控开源社区 开源创新服务平台 提供分布式协作开发 流水线运维 代码分析等功能 基于 Git 打造分布式代码托管环境">
|
||||
<meta content="always" name="referrer">
|
||||
<link rel="canonical" href="https://gitlink.org.cn" data-turbo-transient="">
|
||||
<link rel="fluid-icon" href="https://www.gitlink.org.cn/images/logo.png" title="GitLink">
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/alex/alex.all.global.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont_color/iconfont.css">
|
||||
<!-- <link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css"> -->
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
|
||||
<!-- <link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/merge.css"> -->
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/gitlink.min.css">
|
||||
<%= htmlWebpackPlugin.tags.headTags %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--用于markdown转html -->
|
||||
<div id="md_div" style="display: none;"></div>
|
||||
<div id="root" class="page -layout-v -fit widthunit"></div>
|
||||
<div id="picture_display" style="display: none;"></div>
|
||||
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/js_min_all.js"></script>
|
||||
<!-- <script src="%PUBLIC_URL%js/common.js"></script> -->
|
||||
<script src="%PUBLIC_URL%js/codemirror/codemirror.js"></script>
|
||||
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
|
||||
<script src="%PUBLIC_URL%js/react.production.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/react-dom.production.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/alex/moment.js"></script>
|
||||
<%= htmlWebpackPlugin.tags.bodyTags %>
|
||||
<script>
|
||||
window.onload=function(){
|
||||
$(".newContainer").delegate("a.anchors","click",function(){
|
||||
let h = $(this).offset().top - 180;
|
||||
$("html,body").animate({scrollTop:h},10);
|
||||
window.location.hash = $(this).attr("name");
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<!-- <title>Educoder</title>-->
|
||||
<!--react-ssr-head-->
|
||||
<script type="text/javascript">
|
||||
window.__isR = true;
|
||||
</script>
|
||||
|
||||
|
||||
<!-- <link rel="stylesheet" type="text/css" href="/css/edu-common.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/edu-public.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/taskstyle.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/font-awesome.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/editormd.min.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/merge.css"> -->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/css_min_all.css">
|
||||
|
||||
<link href="/stylesheets/educoder/edu-all.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_653600_qa9lwwv74z.css">
|
||||
|
||||
|
||||
<!-- <link rel="stylesheet" type="text/css" href="https://www.educoder.net/stylesheets/css/font-awesome.css?1510652321"> -->
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<!--用于markdown转html -->
|
||||
<div id="md_div" style="display: none;"></div>
|
||||
<div id="root" class="page -layout-v -fit">
|
||||
</div>
|
||||
<div id="picture_display" style="display: none;"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
|
||||
<!-- js css合并 文件优先级的问题 -->
|
||||
|
||||
<!---->
|
||||
<script type="text/javascript" src="/js/jquery-1.8.3.min.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="/js/editormd/lib/underscore.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/editormd/lib/marked.min.js"></script>
|
||||
<script type="text/javascript" src="/js/editormd/lib/prettify.min.js"></script>
|
||||
<script type="text/javascript" src="/js/editormd/lib/raphael.min.js"></script>
|
||||
<script type="text/javascript" src="/js/editormd/sequence-diagram.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/editormd/flowchart.min.js"></script>
|
||||
<script type="text/javascript" src="/js/editormd/jquery.flowchart.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="/js/editormd/editormd.min.js"></script>
|
||||
|
||||
<!-- codemirror addon -->
|
||||
<script type="text/javascript" src="/js/codemirror/codemirror.js"></script>
|
||||
|
||||
<!--hint-->
|
||||
<script type="text/javascript" src="/js/codemirror/lib/fuzzysort.js"></script>
|
||||
<script type="text/javascript" src="/js/codemirror/addon/hint/show-hint.js"></script>
|
||||
<!-- <script type="text/javascript" src="/js/codemirror/addon/hint/javascript-hint.js"></script> -->
|
||||
<script type="text/javascript" src="/js/codemirror/addon/hint/anyword-hint.js"></script>
|
||||
<script type="text/javascript" src="/js/codemirror/mode/javascript.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/diff_match_patch.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/merge.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/edu_tpi.js"></script>
|
||||
<script type="text/javascript" src="http://localhost:3000/javascripts/application.js"></script>
|
||||
|
||||
<script type="text/javascript" src="http://localhost:3000/assets/kindeditor/kindeditor.js"></script>
|
||||
|
||||
<!-- // <script type="text/javascript" src="http://localhost:3000/javascripts/create_kindeditor.js"></script> -->
|
||||
<script type="text/javascript" src="/js/create_kindeditor.js"></script>
|
||||
<script type="text/javascript" src="http://localhost:3000/javascripts/educoder/edu_application.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
var WRAP_CLASS = "CodeMirror-activeline";
|
||||
var BACK_CLASS = "CodeMirror-activeline-background";
|
||||
var GUTT_CLASS = "CodeMirror-activeline-gutter";
|
||||
|
||||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
|
||||
var prev = old == CodeMirror.Init ? false : old;
|
||||
if (val == prev) return
|
||||
if (prev) {
|
||||
cm.off("beforeSelectionChange", selectionChange);
|
||||
clearActiveLines(cm);
|
||||
delete cm.state.activeLines;
|
||||
}
|
||||
if (val) {
|
||||
cm.state.activeLines = [];
|
||||
updateActiveLines(cm, cm.listSelections());
|
||||
cm.on("beforeSelectionChange", selectionChange);
|
||||
}
|
||||
});
|
||||
|
||||
function clearActiveLines(cm) {
|
||||
for (var i = 0; i < cm.state.activeLines.length; i++) {
|
||||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
|
||||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
|
||||
cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
function sameArray(a, b) {
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; i++)
|
||||
if (a[i] != b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function updateActiveLines(cm, ranges) {
|
||||
var active = [];
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
var range = ranges[i];
|
||||
var option = cm.getOption("styleActiveLine");
|
||||
if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty())
|
||||
continue
|
||||
var line = cm.getLineHandleVisualStart(range.head.line);
|
||||
if (active[active.length - 1] != line) active.push(line);
|
||||
}
|
||||
if (sameArray(cm.state.activeLines, active)) return;
|
||||
cm.operation(function() {
|
||||
clearActiveLines(cm);
|
||||
for (var i = 0; i < active.length; i++) {
|
||||
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
|
||||
cm.addLineClass(active[i], "background", BACK_CLASS);
|
||||
cm.addLineClass(active[i], "gutter", GUTT_CLASS);
|
||||
}
|
||||
cm.state.activeLines = active;
|
||||
});
|
||||
}
|
||||
|
||||
function selectionChange(cm, sel) {
|
||||
updateActiveLines(cm, sel.ranges);
|
||||
}
|
||||
});
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
// var WORD = /[\w$]+/
|
||||
var WORD = /[A-z]+/
|
||||
, RANGE = 500;
|
||||
|
||||
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
|
||||
var word = options && options.word || WORD;
|
||||
var range = options && options.range || RANGE;
|
||||
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
|
||||
var end = cur.ch, start = end;
|
||||
while (start && word.test(curLine.charAt(start - 1))) --start;
|
||||
var curWord = start != end && curLine.slice(start, end);
|
||||
|
||||
var list = options && options.list || [], seen = {};
|
||||
var re = new RegExp(word.source, "g");
|
||||
for (var dir = -1; dir <= 1; dir += 2) {
|
||||
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
|
||||
for (; line != endLine; line += dir) {
|
||||
var text = editor.getLine(line), m;
|
||||
while (m = re.exec(text)) {
|
||||
if (line == cur.line && m[0] === curWord) continue;
|
||||
if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
|
||||
seen[m[0]] = true;
|
||||
list.push(m[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
|
||||
});
|
||||
});
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
function forEach(arr, f) {
|
||||
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
|
||||
}
|
||||
|
||||
function arrayContains(arr, item) {
|
||||
if (!Array.prototype.indexOf) {
|
||||
var i = arr.length;
|
||||
while (i--) {
|
||||
if (arr[i] === item) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return arr.indexOf(item) != -1;
|
||||
}
|
||||
|
||||
function scriptHint(editor, keywords, getToken, options) {
|
||||
// Find the token at the cursor
|
||||
var cur = editor.getCursor(), token = getToken(editor, cur);
|
||||
if (/\b(?:string|comment)\b/.test(token.type)) return;
|
||||
token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
|
||||
|
||||
// If it's not a 'word-style' token, ignore the token.
|
||||
if (!/^[\w$_]*$/.test(token.string)) {
|
||||
token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
|
||||
type: token.string == "." ? "property" : null};
|
||||
} else if (token.end > cur.ch) {
|
||||
token.end = cur.ch;
|
||||
token.string = token.string.slice(0, cur.ch - token.start);
|
||||
}
|
||||
|
||||
var tprop = token;
|
||||
// If it is a property, find out what it is a property of.
|
||||
while (tprop.type == "property") {
|
||||
tprop = getToken(editor, Pos(cur.line, tprop.start));
|
||||
if (tprop.string != ".") return;
|
||||
tprop = getToken(editor, Pos(cur.line, tprop.start));
|
||||
if (!context) var context = [];
|
||||
context.push(tprop);
|
||||
}
|
||||
// 发消息让其他组件注入 其他hint
|
||||
CodeMirror.signal(editor, "hinting");
|
||||
var myhints = editor.state.myhints
|
||||
var needToClearJSHint = editor.state.needToClearJSHint
|
||||
if (needToClearJSHint) { // 不使用js的hint,可能注入了其他语言的hint
|
||||
keywords = []
|
||||
editor.state.needToClearJSHint = false;
|
||||
}
|
||||
myhints && myhints.forEach(function(item) {
|
||||
if (!arrayContains(keywords, item)) keywords.push(item)
|
||||
})
|
||||
|
||||
return {list: getCompletions(token, context, keywords, options),
|
||||
from: Pos(cur.line, token.start),
|
||||
to: Pos(cur.line, token.end)};
|
||||
}
|
||||
|
||||
function javascriptHint(editor, options) {
|
||||
return scriptHint(editor, javascriptKeywords,
|
||||
function (e, cur) {return e.getTokenAt(cur);},
|
||||
options);
|
||||
};
|
||||
CodeMirror.registerHelper("hint", "javascript", javascriptHint);
|
||||
|
||||
function getCoffeeScriptToken(editor, cur) {
|
||||
// This getToken, it is for coffeescript, imitates the behavior of
|
||||
// getTokenAt method in javascript.js, that is, returning "property"
|
||||
// type and treat "." as indepenent token.
|
||||
var token = editor.getTokenAt(cur);
|
||||
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
|
||||
token.end = token.start;
|
||||
token.string = '.';
|
||||
token.type = "property";
|
||||
}
|
||||
else if (/^\.[\w$_]*$/.test(token.string)) {
|
||||
token.type = "property";
|
||||
token.start++;
|
||||
token.string = token.string.replace(/\./, '');
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
function coffeescriptHint(editor, options) {
|
||||
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
|
||||
}
|
||||
CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
|
||||
|
||||
/* var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
|
||||
"toUpperCase toLowerCase split concat match replace search").split(" ");
|
||||
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
|
||||
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
|
||||
var funcProps = "prototype apply call bind".split(" ");*/
|
||||
var javascriptKeywords = ("double float int long short null true false enum super this void auto for register static const friend mutable explicit virtual template typename printf " +
|
||||
"break continue return do while if else for instanceof switch case default try catch finally throw throws assert import package boolean byte char delete private " +
|
||||
"inline struct union signed unsigned export extern namespace using operator sizeof typedef typeid and del from not as elif or with pass except " +
|
||||
"print exec raise is def lambda private protected public abstract class extends final implements interface native new static strictfp synchronized transient main " +
|
||||
"String string System println vector bool boolean FALSE TRUE function").split(" ");
|
||||
/*
|
||||
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
|
||||
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
|
||||
*/
|
||||
|
||||
function forAllProps(obj, callback) {
|
||||
if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
|
||||
for (var name in obj) callback(name)
|
||||
} else {
|
||||
for (var o = obj; o; o = Object.getPrototypeOf(o))
|
||||
Object.getOwnPropertyNames(o).forEach(callback)
|
||||
}
|
||||
}
|
||||
|
||||
function getCompletions(token, context, keywords, options) {
|
||||
var found = [], start = token.string, global = options && options.globalScope || window;
|
||||
function maybeAdd(str) {
|
||||
// var results = fuzzysort.go(start, [str])
|
||||
// if ( results.total && !arrayContains(found, str) ) found.push(str);
|
||||
|
||||
if (fuzzysort && fuzzysort.single) {
|
||||
// 使用模糊搜索
|
||||
var results = fuzzysort.single(start, str)
|
||||
if ( results && results.score <= 0 && !arrayContains(found, str)) found.push(str);
|
||||
} else {
|
||||
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
|
||||
}
|
||||
}
|
||||
function gatherCompletions(obj) {
|
||||
if (typeof obj == "string") forEach(stringProps, maybeAdd);
|
||||
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
|
||||
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
|
||||
forAllProps(obj, maybeAdd)
|
||||
}
|
||||
|
||||
// 不启用context context强制要求了lib的调用才提示,比如Math.a 就会提示 Math.abs
|
||||
if (false && context && context.length) {
|
||||
// If this is a property, see if it belongs to some object we can
|
||||
// find in the current environment.
|
||||
var obj = context.pop(), base;
|
||||
if (obj.type && obj.type.indexOf("variable") === 0) {
|
||||
if (options && options.additionalContext)
|
||||
base = options.additionalContext[obj.string];
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
base = base || global[obj.string];
|
||||
} else if (obj.type == "string") {
|
||||
base = "";
|
||||
} else if (obj.type == "atom") {
|
||||
base = 1;
|
||||
} else if (obj.type == "function") {
|
||||
if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
|
||||
(typeof global.jQuery == 'function'))
|
||||
base = global.jQuery();
|
||||
else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
|
||||
base = global._();
|
||||
}
|
||||
while (base != null && context.length)
|
||||
base = base[context.pop().string];
|
||||
if (base != null) gatherCompletions(base);
|
||||
} else {
|
||||
// If not, just look in the global object and any local scope
|
||||
// (reading into JS mode internals to get at the local and global variables)
|
||||
/* for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);*/
|
||||
/* for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
gatherCompletions(global);*/
|
||||
|
||||
// forEach(keywords, maybeAdd);
|
||||
|
||||
var result = fuzzysort.go(start, keywords)
|
||||
result && result.forEach(function(item) {
|
||||
found.push(item.target)
|
||||
})
|
||||
}
|
||||
return found;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
.CodeMirror-hints {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
|
||||
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
border-radius: 3px;
|
||||
border: 1px solid silver;
|
||||
|
||||
background: white;
|
||||
font-size: 90%;
|
||||
font-family: monospace;
|
||||
|
||||
max-height: 20em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-hint {
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
white-space: pre;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
background: #08f;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -1,458 +0,0 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
|
||||
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
|
||||
|
||||
// This is the old interface, kept around for now to stay
|
||||
// backwards-compatible.
|
||||
CodeMirror.showHint = function(cm, getHints, options) {
|
||||
if (!getHints) return cm.showHint(options);
|
||||
if (options && options.async) getHints.async = true;
|
||||
var newOpts = {hint: getHints};
|
||||
if (options) for (var prop in options) newOpts[prop] = options[prop];
|
||||
return cm.showHint(newOpts);
|
||||
};
|
||||
|
||||
CodeMirror.defineExtension("showHint", function(options) {
|
||||
options = parseOptions(this, this.getCursor("start"), options);
|
||||
var selections = this.listSelections()
|
||||
if (selections.length > 1) return;
|
||||
// By default, don't allow completion when something is selected.
|
||||
// A hint function can have a `supportsSelection` property to
|
||||
// indicate that it can handle selections.
|
||||
if (this.somethingSelected()) {
|
||||
if (!options.hint.supportsSelection) return;
|
||||
// Don't try with cross-line selections
|
||||
for (var i = 0; i < selections.length; i++)
|
||||
if (selections[i].head.line != selections[i].anchor.line) return;
|
||||
}
|
||||
|
||||
if (this.state.completionActive) this.state.completionActive.close();
|
||||
var completion = this.state.completionActive = new Completion(this, options);
|
||||
if (!completion.options.hint) return;
|
||||
|
||||
CodeMirror.signal(this, "startCompletion", this);
|
||||
completion.update(true);
|
||||
});
|
||||
|
||||
function Completion(cm, options) {
|
||||
this.cm = cm;
|
||||
this.options = options;
|
||||
this.widget = null;
|
||||
this.debounce = 0;
|
||||
this.tick = 0;
|
||||
this.startPos = this.cm.getCursor("start");
|
||||
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
|
||||
|
||||
var self = this;
|
||||
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
|
||||
}
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
||||
return setTimeout(fn, 1000/60);
|
||||
};
|
||||
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
||||
|
||||
Completion.prototype = {
|
||||
close: function() {
|
||||
if (!this.active()) return;
|
||||
this.cm.state.completionActive = null;
|
||||
this.tick = null;
|
||||
this.cm.off("cursorActivity", this.activityFunc);
|
||||
|
||||
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
|
||||
if (this.widget) this.widget.close();
|
||||
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
||||
},
|
||||
|
||||
active: function() {
|
||||
return this.cm.state.completionActive == this;
|
||||
},
|
||||
|
||||
pick: function(data, i) {
|
||||
var completion = data.list[i];
|
||||
if (completion.hint) completion.hint(this.cm, data, completion);
|
||||
else this.cm.replaceRange(getText(completion), completion.from || data.from,
|
||||
completion.to || data.to, "complete");
|
||||
CodeMirror.signal(data, "pick", completion);
|
||||
this.close();
|
||||
},
|
||||
|
||||
cursorActivity: function() {
|
||||
if (this.debounce) {
|
||||
cancelAnimationFrame(this.debounce);
|
||||
this.debounce = 0;
|
||||
}
|
||||
|
||||
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
|
||||
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
|
||||
pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
|
||||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
|
||||
this.close();
|
||||
} else {
|
||||
var self = this;
|
||||
this.debounce = requestAnimationFrame(function() {self.update();});
|
||||
if (this.widget) this.widget.disable();
|
||||
}
|
||||
},
|
||||
|
||||
update: function(first) {
|
||||
if (this.tick == null) return
|
||||
var self = this, myTick = ++this.tick
|
||||
fetchHints(this.options.hint, this.cm, this.options, function(data) {
|
||||
if (self.tick == myTick) self.finishUpdate(data, first)
|
||||
})
|
||||
},
|
||||
|
||||
finishUpdate: function(data, first) {
|
||||
if (this.data) CodeMirror.signal(this.data, "update");
|
||||
|
||||
var picked = (this.widget && this.widget.picked) // || (first && this.options.completeSingle);
|
||||
if (this.widget) this.widget.close();
|
||||
|
||||
if (data && this.data && isNewCompletion(this.data, data)) return;
|
||||
this.data = data;
|
||||
|
||||
if (data && data.list.length) {
|
||||
if (picked && data.list.length == 1) {
|
||||
this.pick(data, 0);
|
||||
} else {
|
||||
// 使得输入完后,刚好输入和hint一样,则不再显示hint
|
||||
if (data.list.length == 1 && data.to.ch - data.from.ch === data.list[0].length) {
|
||||
return;
|
||||
}
|
||||
this.widget = new Widget(this, data);
|
||||
CodeMirror.signal(data, "shown");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function isNewCompletion(old, nw) {
|
||||
var moved = CodeMirror.cmpPos(nw.from, old.from)
|
||||
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
|
||||
}
|
||||
|
||||
function parseOptions(cm, pos, options) {
|
||||
var editor = cm.options.hintOptions;
|
||||
var out = {};
|
||||
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
|
||||
if (editor) for (var prop in editor)
|
||||
if (editor[prop] !== undefined) out[prop] = editor[prop];
|
||||
if (options) for (var prop in options)
|
||||
if (options[prop] !== undefined) out[prop] = options[prop];
|
||||
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
|
||||
return out;
|
||||
}
|
||||
|
||||
function getText(completion) {
|
||||
if (typeof completion == "string") return completion;
|
||||
else return completion.text;
|
||||
}
|
||||
|
||||
function buildKeyMap(completion, handle) {
|
||||
var baseMap = {
|
||||
Up: function() {handle.moveFocus(-1);},
|
||||
Down: function() {handle.moveFocus(1);},
|
||||
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
|
||||
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
|
||||
Home: function() {handle.setFocus(0);},
|
||||
End: function() {handle.setFocus(handle.length - 1);},
|
||||
Enter: handle.pick,
|
||||
Tab: handle.pick,
|
||||
Esc: handle.close
|
||||
};
|
||||
var custom = completion.options.customKeys;
|
||||
var ourMap = custom ? {} : baseMap;
|
||||
function addBinding(key, val) {
|
||||
var bound;
|
||||
if (typeof val != "string")
|
||||
bound = function(cm) { return val(cm, handle); };
|
||||
// This mechanism is deprecated
|
||||
else if (baseMap.hasOwnProperty(val))
|
||||
bound = baseMap[val];
|
||||
else
|
||||
bound = val;
|
||||
ourMap[key] = bound;
|
||||
}
|
||||
if (custom)
|
||||
for (var key in custom) if (custom.hasOwnProperty(key))
|
||||
addBinding(key, custom[key]);
|
||||
var extra = completion.options.extraKeys;
|
||||
if (extra)
|
||||
for (var key in extra) if (extra.hasOwnProperty(key))
|
||||
addBinding(key, extra[key]);
|
||||
return ourMap;
|
||||
}
|
||||
|
||||
function getHintElement(hintsElement, el) {
|
||||
while (el && el != hintsElement) {
|
||||
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
|
||||
el = el.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
function Widget(completion, data) {
|
||||
this.completion = completion;
|
||||
this.data = data;
|
||||
this.picked = false;
|
||||
var widget = this, cm = completion.cm;
|
||||
|
||||
var hints = this.hints = document.createElement("ul");
|
||||
hints.className = "CodeMirror-hints";
|
||||
this.selectedHint = data.selectedHint || 0;
|
||||
|
||||
var completions = data.list;
|
||||
for (var i = 0; i < completions.length; ++i) {
|
||||
var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
|
||||
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
|
||||
if (cur.className != null) className = cur.className + " " + className;
|
||||
elt.className = className;
|
||||
if (cur.render) cur.render(elt, data, cur);
|
||||
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
|
||||
elt.hintId = i;
|
||||
}
|
||||
|
||||
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
|
||||
var left = pos.left, top = pos.bottom, below = true;
|
||||
hints.style.left = left + "px";
|
||||
hints.style.top = top + "px";
|
||||
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
|
||||
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
|
||||
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
||||
(completion.options.container || document.body).appendChild(hints);
|
||||
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
|
||||
var scrolls = hints.scrollHeight > hints.clientHeight + 1
|
||||
var startScroll = cm.getScrollInfo();
|
||||
|
||||
if (overlapY > 0) {
|
||||
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
|
||||
if (curTop - height > 0) { // Fits above cursor
|
||||
hints.style.top = (top = pos.top - height) + "px";
|
||||
below = false;
|
||||
} else if (height > winH) {
|
||||
hints.style.height = (winH - 5) + "px";
|
||||
hints.style.top = (top = pos.bottom - box.top) + "px";
|
||||
var cursor = cm.getCursor();
|
||||
if (data.from.ch != cursor.ch) {
|
||||
pos = cm.cursorCoords(cursor);
|
||||
hints.style.left = (left = pos.left) + "px";
|
||||
box = hints.getBoundingClientRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
var overlapX = box.right - winW;
|
||||
if (overlapX > 0) {
|
||||
if (box.right - box.left > winW) {
|
||||
hints.style.width = (winW - 5) + "px";
|
||||
overlapX -= (box.right - box.left) - winW;
|
||||
}
|
||||
hints.style.left = (left = pos.left - overlapX) + "px";
|
||||
}
|
||||
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
|
||||
node.style.paddingRight = cm.display.nativeBarWidth + "px"
|
||||
|
||||
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
|
||||
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
|
||||
setFocus: function(n) { widget.changeActive(n); },
|
||||
menuSize: function() { return widget.screenAmount(); },
|
||||
length: completions.length,
|
||||
close: function() { completion.close(); },
|
||||
pick: function() { widget.pick(); },
|
||||
data: data
|
||||
}));
|
||||
|
||||
if (completion.options.closeOnUnfocus) {
|
||||
var closingOnBlur;
|
||||
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
|
||||
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
|
||||
}
|
||||
|
||||
cm.on("scroll", this.onScroll = function() {
|
||||
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
|
||||
var newTop = top + startScroll.top - curScroll.top;
|
||||
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
|
||||
if (!below) point += hints.offsetHeight;
|
||||
if (point <= editor.top || point >= editor.bottom) return completion.close();
|
||||
hints.style.top = newTop + "px";
|
||||
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
|
||||
});
|
||||
|
||||
CodeMirror.on(hints, "dblclick", function(e) {
|
||||
var t = getHintElement(hints, e.target || e.srcElement);
|
||||
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
|
||||
});
|
||||
|
||||
CodeMirror.on(hints, "click", function(e) {
|
||||
var t = getHintElement(hints, e.target || e.srcElement);
|
||||
if (t && t.hintId != null) {
|
||||
widget.changeActive(t.hintId);
|
||||
if (completion.options.completeOnSingleClick) widget.pick();
|
||||
}
|
||||
});
|
||||
|
||||
CodeMirror.on(hints, "mousedown", function() {
|
||||
setTimeout(function(){cm.focus();}, 20);
|
||||
});
|
||||
|
||||
CodeMirror.signal(data, "select", completions[0], hints.firstChild);
|
||||
return true;
|
||||
}
|
||||
|
||||
Widget.prototype = {
|
||||
close: function() {
|
||||
if (this.completion.widget != this) return;
|
||||
this.completion.widget = null;
|
||||
this.hints.parentNode.removeChild(this.hints);
|
||||
this.completion.cm.removeKeyMap(this.keyMap);
|
||||
|
||||
var cm = this.completion.cm;
|
||||
if (this.completion.options.closeOnUnfocus) {
|
||||
cm.off("blur", this.onBlur);
|
||||
cm.off("focus", this.onFocus);
|
||||
}
|
||||
cm.off("scroll", this.onScroll);
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
this.completion.cm.removeKeyMap(this.keyMap);
|
||||
var widget = this;
|
||||
this.keyMap = {Enter: function() { widget.picked = true; }};
|
||||
this.completion.cm.addKeyMap(this.keyMap);
|
||||
},
|
||||
|
||||
pick: function() {
|
||||
this.completion.pick(this.data, this.selectedHint);
|
||||
},
|
||||
|
||||
changeActive: function(i, avoidWrap) {
|
||||
if (i >= this.data.list.length)
|
||||
i = avoidWrap ? this.data.list.length - 1 : 0;
|
||||
else if (i < 0)
|
||||
i = avoidWrap ? 0 : this.data.list.length - 1;
|
||||
if (this.selectedHint == i) return;
|
||||
var node = this.hints.childNodes[this.selectedHint];
|
||||
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
|
||||
node = this.hints.childNodes[this.selectedHint = i];
|
||||
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
|
||||
if (node.offsetTop < this.hints.scrollTop)
|
||||
this.hints.scrollTop = node.offsetTop - 3;
|
||||
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
|
||||
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
|
||||
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
|
||||
},
|
||||
|
||||
screenAmount: function() {
|
||||
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
|
||||
}
|
||||
};
|
||||
|
||||
function applicableHelpers(cm, helpers) {
|
||||
if (!cm.somethingSelected()) return helpers
|
||||
var result = []
|
||||
for (var i = 0; i < helpers.length; i++)
|
||||
if (helpers[i].supportsSelection) result.push(helpers[i])
|
||||
return result
|
||||
}
|
||||
|
||||
function fetchHints(hint, cm, options, callback) {
|
||||
if (hint.async) {
|
||||
hint(cm, callback, options)
|
||||
} else {
|
||||
var result = hint(cm, options)
|
||||
if (result && result.then) result.then(callback)
|
||||
else callback(result)
|
||||
}
|
||||
}
|
||||
|
||||
function resolveAutoHints(cm, pos) {
|
||||
var helpers = cm.getHelpers(pos, "hint"), words
|
||||
if (helpers.length) {
|
||||
var resolved = function(cm, callback, options) {
|
||||
var app = applicableHelpers(cm, helpers);
|
||||
function run(i) {
|
||||
if (i == app.length) return callback(null)
|
||||
fetchHints(app[i], cm, options, function(result) {
|
||||
if (result && result.list.length > 0) callback(result)
|
||||
else run(i + 1)
|
||||
})
|
||||
}
|
||||
run(0)
|
||||
}
|
||||
resolved.async = true
|
||||
resolved.supportsSelection = true
|
||||
return resolved
|
||||
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
|
||||
// 发消息让其他组件注入 其他hint
|
||||
CodeMirror.signal(cm, "hinting", words);
|
||||
var myhints = cm.state.myhints
|
||||
var wordsTemp = words.slice(0)
|
||||
myhints && myhints.forEach(function(item) {
|
||||
if (words.indexOf(item) === -1) wordsTemp.push(item)
|
||||
})
|
||||
return function(cm) {
|
||||
return CodeMirror.hint.fromList(cm, {words: wordsTemp})
|
||||
}
|
||||
} else if (CodeMirror.hint.anyword) {
|
||||
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
|
||||
} else {
|
||||
return function() {}
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.registerHelper("hint", "auto", {
|
||||
resolve: resolveAutoHints
|
||||
});
|
||||
|
||||
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
|
||||
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
||||
var to = CodeMirror.Pos(cur.line, token.end);
|
||||
if (token.string && /\w/.test(token.string[token.string.length - 1])) {
|
||||
var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
|
||||
} else {
|
||||
var term = "", from = to;
|
||||
}
|
||||
var found = [];
|
||||
|
||||
if (fuzzysort && fuzzysort.go) {
|
||||
var result = fuzzysort.go(term, options.words)
|
||||
result && result.forEach(function(item) {
|
||||
found.push(item.target)
|
||||
})
|
||||
} else {
|
||||
for (var i = 0; i < options.words.length; i++) {
|
||||
var word = options.words[i];
|
||||
if (word.slice(0, term.length) == term)
|
||||
found.push(word);
|
||||
}
|
||||
}
|
||||
if (found.length) return {list: found, from: from, to: to};
|
||||
});
|
||||
|
||||
CodeMirror.commands.autocomplete = CodeMirror.showHint;
|
||||
|
||||
var defaultOptions = {
|
||||
hint: CodeMirror.hint.auto,
|
||||
completeSingle: true,
|
||||
alignWithWord: true,
|
||||
closeCharacters: /[\s()\[\]{};:>,]/,
|
||||
closeOnUnfocus: true,
|
||||
completeOnSingleClick: true,
|
||||
container: null,
|
||||
customKeys: null,
|
||||
extraKeys: null
|
||||
};
|
||||
|
||||
CodeMirror.defineOption("hintOptions", null);
|
||||
});
|
||||
|
|
@ -1,603 +0,0 @@
|
|||
/*
|
||||
WHAT: SublimeText-like Fuzzy Search
|
||||
USAGE:
|
||||
fuzzysort.single('fs', 'Fuzzy Search') // {score: -16}
|
||||
fuzzysort.single('test', 'test') // {score: 0}
|
||||
fuzzysort.single('doesnt exist', 'target') // null
|
||||
fuzzysort.go('mr', ['Monitor.cpp', 'MeshRenderer.cpp'])
|
||||
// [{score: -18, target: "MeshRenderer.cpp"}, {score: -6009, target: "Monitor.cpp"}]
|
||||
fuzzysort.highlight(fuzzysort.single('fs', 'Fuzzy Search'), '<b>', '</b>')
|
||||
// <b>F</b>uzzy <b>S</b>earch
|
||||
|
||||
https://github.com/farzher/fuzzysort
|
||||
*/
|
||||
|
||||
// UMD (Universal Module Definition) for fuzzysort
|
||||
;(function(root, UMD) {
|
||||
if(typeof define === 'function' && define.amd) define([], UMD)
|
||||
else if(typeof module === 'object' && module.exports) module.exports = UMD()
|
||||
else root.fuzzysort = UMD()
|
||||
})(this, function UMD() { function fuzzysortNew(instanceOptions) {
|
||||
|
||||
var fuzzysort = {
|
||||
|
||||
single: function(search, target, options) {
|
||||
if(!search) return null
|
||||
if(!isObj(search)) search = fuzzysort.getPreparedSearch(search)
|
||||
|
||||
if(!target) return null
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
|
||||
: instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
|
||||
: true
|
||||
var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
|
||||
return algorithm(search, target, search[0])
|
||||
// var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
|
||||
// var result = algorithm(search, target, search[0])
|
||||
// if(result === null) return null
|
||||
// if(result.score < threshold) return null
|
||||
// return result
|
||||
},
|
||||
|
||||
go: function(search, targets, options) {
|
||||
if(!search) return noResults
|
||||
search = fuzzysort.prepareSearch(search)
|
||||
var searchLowerCode = search[0]
|
||||
|
||||
var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
|
||||
var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
|
||||
var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
|
||||
: instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
|
||||
: true
|
||||
var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
|
||||
var resultsLen = 0; var limitedCount = 0
|
||||
var targetsLen = targets.length
|
||||
|
||||
// This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
|
||||
|
||||
// options.keys
|
||||
if(options && options.keys) {
|
||||
var scoreFn = options.scoreFn || defaultScoreFn
|
||||
var keys = options.keys
|
||||
var keysLen = keys.length
|
||||
for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
|
||||
var objResults = new Array(keysLen)
|
||||
for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
|
||||
var key = keys[keyI]
|
||||
var target = getValue(obj, key)
|
||||
if(!target) { objResults[keyI] = null; continue }
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
objResults[keyI] = algorithm(search, target, searchLowerCode)
|
||||
}
|
||||
objResults.obj = obj // before scoreFn so scoreFn can use it
|
||||
var score = scoreFn(objResults)
|
||||
if(score === null) continue
|
||||
if(score < threshold) continue
|
||||
objResults.score = score
|
||||
if(resultsLen < limit) { q.add(objResults); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(score > q.peek().score) q.replaceTop(objResults)
|
||||
}
|
||||
}
|
||||
|
||||
// options.key
|
||||
} else if(options && options.key) {
|
||||
var key = options.key
|
||||
for(var i = targetsLen - 1; i >= 0; --i) { var obj = targets[i]
|
||||
var target = getValue(obj, key)
|
||||
if(!target) continue
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
var result = algorithm(search, target, searchLowerCode)
|
||||
if(result === null) continue
|
||||
if(result.score < threshold) continue
|
||||
|
||||
// have to clone result so duplicate targets from different obj can each reference the correct obj
|
||||
result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
|
||||
|
||||
if(resultsLen < limit) { q.add(result); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(result.score > q.peek().score) q.replaceTop(result)
|
||||
}
|
||||
}
|
||||
|
||||
// no keys
|
||||
} else {
|
||||
for(var i = targetsLen - 1; i >= 0; --i) { var target = targets[i]
|
||||
if(!target) continue
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
var result = algorithm(search, target, searchLowerCode)
|
||||
if(result === null) continue
|
||||
if(result.score < threshold) continue
|
||||
if(resultsLen < limit) { q.add(result); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(result.score > q.peek().score) q.replaceTop(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(resultsLen === 0) return noResults
|
||||
var results = new Array(resultsLen)
|
||||
for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
|
||||
results.total = resultsLen + limitedCount
|
||||
return results
|
||||
},
|
||||
|
||||
goAsync: function(search, targets, options) {
|
||||
var canceled = false
|
||||
var p = new Promise(function(resolve, reject) {
|
||||
if(!search) return resolve(noResults)
|
||||
search = fuzzysort.prepareSearch(search)
|
||||
var searchLowerCode = search[0]
|
||||
|
||||
var q = fastpriorityqueue()
|
||||
var iCurrent = targets.length - 1
|
||||
var threshold = options && options.threshold || instanceOptions && instanceOptions.threshold || -9007199254740991
|
||||
var limit = options && options.limit || instanceOptions && instanceOptions.limit || 9007199254740991
|
||||
var allowTypo = options && options.allowTypo!==undefined ? options.allowTypo
|
||||
: instanceOptions && instanceOptions.allowTypo!==undefined ? instanceOptions.allowTypo
|
||||
: true
|
||||
var algorithm = allowTypo ? fuzzysort.algorithm : fuzzysort.algorithmNoTypo
|
||||
var resultsLen = 0; var limitedCount = 0
|
||||
function step() {
|
||||
if(canceled) return reject('canceled')
|
||||
|
||||
var startMs = Date.now()
|
||||
|
||||
// This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
|
||||
|
||||
// options.keys
|
||||
if(options && options.keys) {
|
||||
var scoreFn = options.scoreFn || defaultScoreFn
|
||||
var keys = options.keys
|
||||
var keysLen = keys.length
|
||||
for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
|
||||
var objResults = new Array(keysLen)
|
||||
for (var keyI = keysLen - 1; keyI >= 0; --keyI) {
|
||||
var key = keys[keyI]
|
||||
var target = getValue(obj, key)
|
||||
if(!target) { objResults[keyI] = null; continue }
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
objResults[keyI] = algorithm(search, target, searchLowerCode)
|
||||
}
|
||||
objResults.obj = obj // before scoreFn so scoreFn can use it
|
||||
var score = scoreFn(objResults)
|
||||
if(score === null) continue
|
||||
if(score < threshold) continue
|
||||
objResults.score = score
|
||||
if(resultsLen < limit) { q.add(objResults); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(score > q.peek().score) q.replaceTop(objResults)
|
||||
}
|
||||
|
||||
if(iCurrent%1000/*itemsPerCheck*/ === 0) {
|
||||
if(Date.now() - startMs >= 10/*asyncInterval*/) {
|
||||
isNode?setImmediate(step):setTimeout(step)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// options.key
|
||||
} else if(options && options.key) {
|
||||
var key = options.key
|
||||
for(; iCurrent >= 0; --iCurrent) { var obj = targets[iCurrent]
|
||||
var target = getValue(obj, key)
|
||||
if(!target) continue
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
var result = algorithm(search, target, searchLowerCode)
|
||||
if(result === null) continue
|
||||
if(result.score < threshold) continue
|
||||
|
||||
// have to clone result so duplicate targets from different obj can each reference the correct obj
|
||||
result = {target:result.target, _targetLowerCodes:null, _nextBeginningIndexes:null, score:result.score, indexes:result.indexes, obj:obj} // hidden
|
||||
|
||||
if(resultsLen < limit) { q.add(result); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(result.score > q.peek().score) q.replaceTop(result)
|
||||
}
|
||||
|
||||
if(iCurrent%1000/*itemsPerCheck*/ === 0) {
|
||||
if(Date.now() - startMs >= 10/*asyncInterval*/) {
|
||||
isNode?setImmediate(step):setTimeout(step)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no keys
|
||||
} else {
|
||||
for(; iCurrent >= 0; --iCurrent) { var target = targets[iCurrent]
|
||||
if(!target) continue
|
||||
if(!isObj(target)) target = fuzzysort.getPrepared(target)
|
||||
|
||||
var result = algorithm(search, target, searchLowerCode)
|
||||
if(result === null) continue
|
||||
if(result.score < threshold) continue
|
||||
if(resultsLen < limit) { q.add(result); ++resultsLen }
|
||||
else {
|
||||
++limitedCount
|
||||
if(result.score > q.peek().score) q.replaceTop(result)
|
||||
}
|
||||
|
||||
if(iCurrent%1000/*itemsPerCheck*/ === 0) {
|
||||
if(Date.now() - startMs >= 10/*asyncInterval*/) {
|
||||
isNode?setImmediate(step):setTimeout(step)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(resultsLen === 0) return resolve(noResults)
|
||||
var results = new Array(resultsLen)
|
||||
for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll()
|
||||
results.total = resultsLen + limitedCount
|
||||
resolve(results)
|
||||
}
|
||||
|
||||
isNode?setImmediate(step):step()
|
||||
})
|
||||
p.cancel = function() { canceled = true }
|
||||
return p
|
||||
},
|
||||
|
||||
highlight: function(result, hOpen, hClose) {
|
||||
if(result === null) return null
|
||||
if(hOpen === undefined) hOpen = '<b>'
|
||||
if(hClose === undefined) hClose = '</b>'
|
||||
var highlighted = ''
|
||||
var matchesIndex = 0
|
||||
var opened = false
|
||||
var target = result.target
|
||||
var targetLen = target.length
|
||||
var matchesBest = result.indexes
|
||||
for(var i = 0; i < targetLen; ++i) { var char = target[i]
|
||||
if(matchesBest[matchesIndex] === i) {
|
||||
++matchesIndex
|
||||
if(!opened) { opened = true
|
||||
highlighted += hOpen
|
||||
}
|
||||
|
||||
if(matchesIndex === matchesBest.length) {
|
||||
highlighted += char + hClose + target.substr(i+1)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if(opened) { opened = false
|
||||
highlighted += hClose
|
||||
}
|
||||
}
|
||||
highlighted += char
|
||||
}
|
||||
|
||||
return highlighted
|
||||
},
|
||||
|
||||
prepare: function(target) {
|
||||
if(!target) return
|
||||
return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:null, score:null, indexes:null, obj:null} // hidden
|
||||
},
|
||||
prepareSlow: function(target) {
|
||||
if(!target) return
|
||||
return {target:target, _targetLowerCodes:fuzzysort.prepareLowerCodes(target), _nextBeginningIndexes:fuzzysort.prepareNextBeginningIndexes(target), score:null, indexes:null, obj:null} // hidden
|
||||
},
|
||||
prepareSearch: function(search) {
|
||||
if(!search) return
|
||||
return fuzzysort.prepareLowerCodes(search)
|
||||
},
|
||||
|
||||
|
||||
|
||||
// Below this point is only internal code
|
||||
// Below this point is only internal code
|
||||
// Below this point is only internal code
|
||||
// Below this point is only internal code
|
||||
|
||||
|
||||
|
||||
getPrepared: function(target) {
|
||||
if(target.length > 999) return fuzzysort.prepare(target) // don't cache huge targets
|
||||
var targetPrepared = preparedCache.get(target)
|
||||
if(targetPrepared !== undefined) return targetPrepared
|
||||
targetPrepared = fuzzysort.prepare(target)
|
||||
preparedCache.set(target, targetPrepared)
|
||||
return targetPrepared
|
||||
},
|
||||
getPreparedSearch: function(search) {
|
||||
if(search.length > 999) return fuzzysort.prepareSearch(search) // don't cache huge searches
|
||||
var searchPrepared = preparedSearchCache.get(search)
|
||||
if(searchPrepared !== undefined) return searchPrepared
|
||||
searchPrepared = fuzzysort.prepareSearch(search)
|
||||
preparedSearchCache.set(search, searchPrepared)
|
||||
return searchPrepared
|
||||
},
|
||||
|
||||
algorithm: function(searchLowerCodes, prepared, searchLowerCode) {
|
||||
var targetLowerCodes = prepared._targetLowerCodes
|
||||
var searchLen = searchLowerCodes.length
|
||||
var targetLen = targetLowerCodes.length
|
||||
var searchI = 0 // where we at
|
||||
var targetI = 0 // where you at
|
||||
var typoSimpleI = 0
|
||||
var matchesSimpleLen = 0
|
||||
|
||||
// very basic fuzzy match; to remove non-matching targets ASAP!
|
||||
// walk through target. find sequential matches.
|
||||
// if all chars aren't found then exit
|
||||
for(;;) {
|
||||
var isMatch = searchLowerCode === targetLowerCodes[targetI]
|
||||
if(isMatch) {
|
||||
matchesSimple[matchesSimpleLen++] = targetI
|
||||
++searchI; if(searchI === searchLen) break
|
||||
searchLowerCode = searchLowerCodes[typoSimpleI===0?searchI : (typoSimpleI===searchI?searchI+1 : (typoSimpleI===searchI-1?searchI-1 : searchI))]
|
||||
}
|
||||
|
||||
++targetI; if(targetI >= targetLen) { // Failed to find searchI
|
||||
// Check for typo or exit
|
||||
// we go as far as possible before trying to transpose
|
||||
// then we transpose backwards until we reach the beginning
|
||||
for(;;) {
|
||||
if(searchI <= 1) return null // not allowed to transpose first char
|
||||
if(typoSimpleI === 0) { // we haven't tried to transpose yet
|
||||
--searchI
|
||||
var searchLowerCodeNew = searchLowerCodes[searchI]
|
||||
if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
|
||||
typoSimpleI = searchI
|
||||
} else {
|
||||
if(typoSimpleI === 1) return null // reached the end of the line for transposing
|
||||
--typoSimpleI
|
||||
searchI = typoSimpleI
|
||||
searchLowerCode = searchLowerCodes[searchI + 1]
|
||||
var searchLowerCodeNew = searchLowerCodes[searchI]
|
||||
if(searchLowerCode === searchLowerCodeNew) continue // doesn't make sense to transpose a repeat char
|
||||
}
|
||||
matchesSimpleLen = searchI
|
||||
targetI = matchesSimple[matchesSimpleLen - 1] + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var searchI = 0
|
||||
var typoStrictI = 0
|
||||
var successStrict = false
|
||||
var matchesStrictLen = 0
|
||||
|
||||
var nextBeginningIndexes = prepared._nextBeginningIndexes
|
||||
if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
|
||||
var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
|
||||
|
||||
// Our target string successfully matched all characters in sequence!
|
||||
// Let's try a more advanced and strict test to improve the score
|
||||
// only count it as a match if it's consecutive or a beginning character!
|
||||
if(targetI !== targetLen) for(;;) {
|
||||
if(targetI >= targetLen) {
|
||||
// We failed to find a good spot for this search char, go back to the previous search char and force it forward
|
||||
if(searchI <= 0) { // We failed to push chars forward for a better match
|
||||
// transpose, starting from the beginning
|
||||
++typoStrictI; if(typoStrictI > searchLen-2) break
|
||||
if(searchLowerCodes[typoStrictI] === searchLowerCodes[typoStrictI+1]) continue // doesn't make sense to transpose a repeat char
|
||||
targetI = firstPossibleI
|
||||
continue
|
||||
}
|
||||
|
||||
--searchI
|
||||
var lastMatch = matchesStrict[--matchesStrictLen]
|
||||
targetI = nextBeginningIndexes[lastMatch]
|
||||
|
||||
} else {
|
||||
var isMatch = searchLowerCodes[typoStrictI===0?searchI : (typoStrictI===searchI?searchI+1 : (typoStrictI===searchI-1?searchI-1 : searchI))] === targetLowerCodes[targetI]
|
||||
if(isMatch) {
|
||||
matchesStrict[matchesStrictLen++] = targetI
|
||||
++searchI; if(searchI === searchLen) { successStrict = true; break }
|
||||
++targetI
|
||||
} else {
|
||||
targetI = nextBeginningIndexes[targetI]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // tally up the score & keep track of matches for highlighting later
|
||||
if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
|
||||
else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
|
||||
var score = 0
|
||||
var lastTargetI = -1
|
||||
for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
|
||||
// score only goes down if they're not consecutive
|
||||
if(lastTargetI !== targetI - 1) score -= targetI
|
||||
lastTargetI = targetI
|
||||
}
|
||||
if(!successStrict) {
|
||||
score *= 1000
|
||||
if(typoSimpleI !== 0) score += -20/*typoPenalty*/
|
||||
} else {
|
||||
if(typoStrictI !== 0) score += -20/*typoPenalty*/
|
||||
}
|
||||
score -= targetLen - searchLen
|
||||
prepared.score = score
|
||||
prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
|
||||
|
||||
return prepared
|
||||
}
|
||||
},
|
||||
|
||||
algorithmNoTypo: function(searchLowerCodes, prepared, searchLowerCode) {
|
||||
var targetLowerCodes = prepared._targetLowerCodes
|
||||
var searchLen = searchLowerCodes.length
|
||||
var targetLen = targetLowerCodes.length
|
||||
var searchI = 0 // where we at
|
||||
var targetI = 0 // where you at
|
||||
var matchesSimpleLen = 0
|
||||
|
||||
// very basic fuzzy match; to remove non-matching targets ASAP!
|
||||
// walk through target. find sequential matches.
|
||||
// if all chars aren't found then exit
|
||||
for(;;) {
|
||||
var isMatch = searchLowerCode === targetLowerCodes[targetI]
|
||||
if(isMatch) {
|
||||
matchesSimple[matchesSimpleLen++] = targetI
|
||||
++searchI; if(searchI === searchLen) break
|
||||
searchLowerCode = searchLowerCodes[searchI]
|
||||
}
|
||||
++targetI; if(targetI >= targetLen) return null // Failed to find searchI
|
||||
}
|
||||
|
||||
var searchI = 0
|
||||
var successStrict = false
|
||||
var matchesStrictLen = 0
|
||||
|
||||
var nextBeginningIndexes = prepared._nextBeginningIndexes
|
||||
if(nextBeginningIndexes === null) nextBeginningIndexes = prepared._nextBeginningIndexes = fuzzysort.prepareNextBeginningIndexes(prepared.target)
|
||||
var firstPossibleI = targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1]
|
||||
|
||||
// Our target string successfully matched all characters in sequence!
|
||||
// Let's try a more advanced and strict test to improve the score
|
||||
// only count it as a match if it's consecutive or a beginning character!
|
||||
if(targetI !== targetLen) for(;;) {
|
||||
if(targetI >= targetLen) {
|
||||
// We failed to find a good spot for this search char, go back to the previous search char and force it forward
|
||||
if(searchI <= 0) break // We failed to push chars forward for a better match
|
||||
|
||||
--searchI
|
||||
var lastMatch = matchesStrict[--matchesStrictLen]
|
||||
targetI = nextBeginningIndexes[lastMatch]
|
||||
|
||||
} else {
|
||||
var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI]
|
||||
if(isMatch) {
|
||||
matchesStrict[matchesStrictLen++] = targetI
|
||||
++searchI; if(searchI === searchLen) { successStrict = true; break }
|
||||
++targetI
|
||||
} else {
|
||||
targetI = nextBeginningIndexes[targetI]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // tally up the score & keep track of matches for highlighting later
|
||||
if(successStrict) { var matchesBest = matchesStrict; var matchesBestLen = matchesStrictLen }
|
||||
else { var matchesBest = matchesSimple; var matchesBestLen = matchesSimpleLen }
|
||||
var score = 0
|
||||
var lastTargetI = -1
|
||||
for(var i = 0; i < searchLen; ++i) { var targetI = matchesBest[i]
|
||||
// score only goes down if they're not consecutive
|
||||
if(lastTargetI !== targetI - 1) score -= targetI
|
||||
lastTargetI = targetI
|
||||
}
|
||||
if(!successStrict) score *= 1000
|
||||
score -= targetLen - searchLen
|
||||
prepared.score = score
|
||||
prepared.indexes = new Array(matchesBestLen); for(var i = matchesBestLen - 1; i >= 0; --i) prepared.indexes[i] = matchesBest[i]
|
||||
|
||||
return prepared
|
||||
}
|
||||
},
|
||||
|
||||
prepareLowerCodes: function(str) {
|
||||
var strLen = str.length
|
||||
var lowerCodes = [] // new Array(strLen) sparse array is too slow
|
||||
var lower = str.toLowerCase()
|
||||
for(var i = 0; i < strLen; ++i) lowerCodes[i] = lower.charCodeAt(i)
|
||||
return lowerCodes
|
||||
},
|
||||
prepareBeginningIndexes: function(target) {
|
||||
var targetLen = target.length
|
||||
var beginningIndexes = []; var beginningIndexesLen = 0
|
||||
var wasUpper = false
|
||||
var wasAlphanum = false
|
||||
for(var i = 0; i < targetLen; ++i) {
|
||||
var targetCode = target.charCodeAt(i)
|
||||
var isUpper = targetCode>=65&&targetCode<=90
|
||||
var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57
|
||||
var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum
|
||||
wasUpper = isUpper
|
||||
wasAlphanum = isAlphanum
|
||||
if(isBeginning) beginningIndexes[beginningIndexesLen++] = i
|
||||
}
|
||||
return beginningIndexes
|
||||
},
|
||||
prepareNextBeginningIndexes: function(target) {
|
||||
var targetLen = target.length
|
||||
var beginningIndexes = fuzzysort.prepareBeginningIndexes(target)
|
||||
var nextBeginningIndexes = [] // new Array(targetLen) sparse array is too slow
|
||||
var lastIsBeginning = beginningIndexes[0]
|
||||
var lastIsBeginningI = 0
|
||||
for(var i = 0; i < targetLen; ++i) {
|
||||
if(lastIsBeginning > i) {
|
||||
nextBeginningIndexes[i] = lastIsBeginning
|
||||
} else {
|
||||
lastIsBeginning = beginningIndexes[++lastIsBeginningI]
|
||||
nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning
|
||||
}
|
||||
}
|
||||
return nextBeginningIndexes
|
||||
},
|
||||
|
||||
cleanup: cleanup,
|
||||
new: fuzzysortNew,
|
||||
}
|
||||
return fuzzysort
|
||||
} // fuzzysortNew
|
||||
|
||||
// This stuff is outside fuzzysortNew, because it's shared with instances of fuzzysort.new()
|
||||
var isNode = typeof require !== 'undefined' && typeof window === 'undefined'
|
||||
// var MAX_INT = Number.MAX_SAFE_INTEGER
|
||||
// var MIN_INT = Number.MIN_VALUE
|
||||
var preparedCache = new Map()
|
||||
var preparedSearchCache = new Map()
|
||||
var noResults = []; noResults.total = 0
|
||||
var matchesSimple = []; var matchesStrict = []
|
||||
function cleanup() { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = [] }
|
||||
function defaultScoreFn(a) {
|
||||
var max = -9007199254740991
|
||||
for (var i = a.length - 1; i >= 0; --i) {
|
||||
var result = a[i]; if(result === null) continue
|
||||
var score = result.score
|
||||
if(score > max) max = score
|
||||
}
|
||||
if(max === -9007199254740991) return null
|
||||
return max
|
||||
}
|
||||
|
||||
// prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
|
||||
// prop = 'key1.key2' 10ms
|
||||
// prop = ['key1', 'key2'] 27ms
|
||||
function getValue(obj, prop) {
|
||||
var tmp = obj[prop]; if(tmp !== undefined) return tmp
|
||||
var segs = prop
|
||||
if(!Array.isArray(prop)) segs = prop.split('.')
|
||||
var len = segs.length
|
||||
var i = -1
|
||||
while (obj && (++i < len)) obj = obj[segs[i]]
|
||||
return obj
|
||||
}
|
||||
|
||||
function isObj(x) { return typeof x === 'object' } // faster as a function
|
||||
|
||||
// Hacked version of https://github.com/lemire/FastPriorityQueue.js
|
||||
var fastpriorityqueue=function(){var r=[],o=0,e={};function n(){for(var e=0,n=r[e],c=1;c<o;){var f=c+1;e=c,f<o&&r[f].score<r[c].score&&(e=f),r[e-1>>1]=r[e],c=1+(e<<1)}for(var a=e-1>>1;e>0&&n.score<r[a].score;a=(e=a)-1>>1)r[e]=r[a];r[e]=n}return e.add=function(e){var n=o;r[o++]=e;for(var c=n-1>>1;n>0&&e.score<r[c].score;c=(n=c)-1>>1)r[n]=r[c];r[n]=e},e.poll=function(){if(0!==o){var e=r[0];return r[0]=r[--o],n(),e}},e.peek=function(e){if(0!==o)return r[0]},e.replaceTop=function(o){r[0]=o,n()},e};
|
||||
var q = fastpriorityqueue() // reuse this, except for async, it needs to make its own
|
||||
|
||||
return fuzzysortNew()
|
||||
}) // UMD
|
||||
|
||||
// TODO: (performance) wasm version!?
|
||||
|
||||
// TODO: (performance) layout memory in an optimal way to go fast by avoiding cache misses
|
||||
|
||||
// TODO: (performance) preparedCache is a memory leak
|
||||
|
||||
// TODO: (like sublime) backslash === forwardslash
|
||||
|
||||
// TODO: (performance) i have no idea how well optizmied the allowing typos algorithm is
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
|
||||
.CodeMirror-merge {
|
||||
position: relative;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
|
||||
min-height:50px;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 48%; }
|
||||
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 4%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
|
||||
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
|
||||
|
||||
.CodeMirror-merge-pane {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
.CodeMirror-merge-pane-rightmost {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-gap {
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #515151;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-scrolllock-wrap {
|
||||
position: absolute;
|
||||
bottom: 0; left: 50%;
|
||||
}
|
||||
.CodeMirror-merge-scrolllock {
|
||||
position: relative;
|
||||
left: -50%;
|
||||
cursor: pointer;
|
||||
color: #d8d8d8;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
|
||||
position: absolute;
|
||||
left: 0; top: 0;
|
||||
right: 0; bottom: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #ce374b;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copy-reverse {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
color: #44c;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
|
||||
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
|
||||
|
||||
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
|
||||
background-position: bottom left;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.CodeMirror-merge-r-chunk { background: #9a6868; }
|
||||
.CodeMirror-merge-r-chunk-start { /*border-top: 1px solid #ee8; */}
|
||||
.CodeMirror-merge-r-chunk-end {/* border-bottom: 1px solid #ee8; */}
|
||||
.CodeMirror-merge-r-connect { fill:#9a6868;}
|
||||
|
||||
.CodeMirror-merge-l-chunk { background: #eef; }
|
||||
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
|
||||
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
|
||||
|
||||
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
|
||||
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
|
||||
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
|
||||
|
||||
.CodeMirror-merge-collapsed-widget:before {
|
||||
content: "(...)";
|
||||
}
|
||||
.CodeMirror-merge-collapsed-widget {
|
||||
cursor: pointer;
|
||||
color: #88b;
|
||||
background: #eef;
|
||||
border: 1px solid #ddf;
|
||||
font-size: 90%;
|
||||
padding: 0 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
|
||||
|
|
@ -1,692 +0,0 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// mode javascript
|
||||
// TODO actually recognize syntax of TypeScript constructs
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit;
|
||||
var statementIndent = parserConfig.statementIndent;
|
||||
var jsonldMode = parserConfig.jsonld;
|
||||
var jsonMode = parserConfig.json || jsonldMode;
|
||||
var isTS = parserConfig.typescript;
|
||||
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
|
||||
|
||||
// Tokenizer
|
||||
|
||||
var keywords = function(){
|
||||
function kw(type) {return {type: type, style: "keyword"};}
|
||||
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
||||
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||
|
||||
var jsKeywords = {
|
||||
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
|
||||
"var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||
"function": kw("function"), "catch": kw("catch"),
|
||||
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||
"in": operator, "typeof": operator, "instanceof": operator,
|
||||
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
||||
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
|
||||
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
||||
};
|
||||
|
||||
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||
if (isTS) {
|
||||
var type = {type: "variable", style: "variable-3"};
|
||||
var tsKeywords = {
|
||||
// object-like things
|
||||
"interface": kw("interface"),
|
||||
"extends": kw("extends"),
|
||||
"constructor": kw("constructor"),
|
||||
|
||||
// scope modifiers
|
||||
"public": kw("public"),
|
||||
"private": kw("private"),
|
||||
"protected": kw("protected"),
|
||||
"static": kw("static"),
|
||||
|
||||
// types
|
||||
"string": type, "number": type, "bool": type, "any": type
|
||||
};
|
||||
|
||||
for (var attr in tsKeywords) {
|
||||
jsKeywords[attr] = tsKeywords[attr];
|
||||
}
|
||||
}
|
||||
|
||||
return jsKeywords;
|
||||
}();
|
||||
|
||||
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
|
||||
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
|
||||
|
||||
function readRegexp(stream) {
|
||||
var escaped = false, next, inSet = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (!escaped) {
|
||||
if (next == "/" && !inSet) return;
|
||||
if (next == "[") inSet = true;
|
||||
else if (inSet && next == "]") inSet = false;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
}
|
||||
|
||||
// Used as scratch variables to communicate multiple values without
|
||||
// consing up tons of objects.
|
||||
var type, content;
|
||||
function ret(tp, style, cont) {
|
||||
type = tp; content = cont;
|
||||
return style;
|
||||
}
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
|
||||
return ret("number", "number");
|
||||
} else if (ch == "." && stream.match("..")) {
|
||||
return ret("spread", "meta");
|
||||
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||
return ret(ch);
|
||||
} else if (ch == "=" && stream.eat(">")) {
|
||||
return ret("=>", "operator");
|
||||
} else if (ch == "0" && stream.eat(/x/i)) {
|
||||
stream.eatWhile(/[\da-f]/i);
|
||||
return ret("number", "number");
|
||||
} else if (/\d/.test(ch)) {
|
||||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||
return ret("number", "number");
|
||||
} else if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
} else if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return ret("comment", "comment");
|
||||
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||
readRegexp(stream);
|
||||
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
|
||||
return ret("regexp", "string-2");
|
||||
} else {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", "operator", stream.current());
|
||||
}
|
||||
} else if (ch == "`") {
|
||||
state.tokenize = tokenQuasi;
|
||||
return tokenQuasi(stream, state);
|
||||
} else if (ch == "#") {
|
||||
stream.skipToEnd();
|
||||
return ret("error", "error");
|
||||
} else if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return ret("operator", "operator", stream.current());
|
||||
} else if (wordRE.test(ch)) {
|
||||
stream.eatWhile(wordRE);
|
||||
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
||||
ret("variable", "variable", word);
|
||||
}
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next;
|
||||
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
|
||||
state.tokenize = tokenBase;
|
||||
return ret("jsonld-keyword", "meta");
|
||||
}
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) break;
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (!escaped) state.tokenize = tokenBase;
|
||||
return ret("string", "string");
|
||||
};
|
||||
}
|
||||
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
function tokenQuasi(stream, state) {
|
||||
var escaped = false, next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return ret("quasi", "string-2", stream.current());
|
||||
}
|
||||
|
||||
var brackets = "([{}])";
|
||||
// This is a crude lookahead trick to try and notice that we're
|
||||
// parsing the argument patterns for a fat-arrow function before we
|
||||
// actually hit the arrow token. It only works if the arrow is on
|
||||
// the same line as the arguments and there's no strange noise
|
||||
// (comments) in between. Fallback is to only notice when we hit the
|
||||
// arrow, and not declare the arguments as locals for the arrow
|
||||
// body.
|
||||
function findFatArrow(stream, state) {
|
||||
if (state.fatArrowAt) state.fatArrowAt = null;
|
||||
var arrow = stream.string.indexOf("=>", stream.start);
|
||||
if (arrow < 0) return;
|
||||
|
||||
var depth = 0, sawSomething = false;
|
||||
for (var pos = arrow - 1; pos >= 0; --pos) {
|
||||
var ch = stream.string.charAt(pos);
|
||||
var bracket = brackets.indexOf(ch);
|
||||
if (bracket >= 0 && bracket < 3) {
|
||||
if (!depth) { ++pos; break; }
|
||||
if (--depth == 0) break;
|
||||
} else if (bracket >= 3 && bracket < 6) {
|
||||
++depth;
|
||||
} else if (wordRE.test(ch)) {
|
||||
sawSomething = true;
|
||||
} else if (/["'\/]/.test(ch)) {
|
||||
return;
|
||||
} else if (sawSomething && !depth) {
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sawSomething && !depth) state.fatArrowAt = pos;
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
||||
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
|
||||
|
||||
function JSLexical(indented, column, type, align, prev, info) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.prev = prev;
|
||||
this.info = info;
|
||||
if (align != null) this.align = align;
|
||||
}
|
||||
|
||||
function inScope(state, varname) {
|
||||
for (var v = state.localVars; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
for (var cx = state.context; cx; cx = cx.prev) {
|
||||
for (var v = cx.vars; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
}
|
||||
}
|
||||
|
||||
function parseJS(state, style, type, content, stream) {
|
||||
var cc = state.cc;
|
||||
// Communicate our context to the combinators.
|
||||
// (Less wasteful than consing up a hundred closures on every call.)
|
||||
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
|
||||
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = true;
|
||||
|
||||
while(true) {
|
||||
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||
if (combinator(type, content)) {
|
||||
while(cc.length && cc[cc.length - 1].lex)
|
||||
cc.pop()();
|
||||
if (cx.marked) return cx.marked;
|
||||
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||
return style;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combinator utils
|
||||
|
||||
var cx = {state: null, column: null, marked: null, cc: null};
|
||||
function pass() {
|
||||
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||
}
|
||||
function cont() {
|
||||
pass.apply(null, arguments);
|
||||
return true;
|
||||
}
|
||||
function register(varname) {
|
||||
function inList(list) {
|
||||
for (var v = list; v; v = v.next)
|
||||
if (v.name == varname) return true;
|
||||
return false;
|
||||
}
|
||||
var state = cx.state;
|
||||
if (state.context) {
|
||||
cx.marked = "def";
|
||||
if (inList(state.localVars)) return;
|
||||
state.localVars = {name: varname, next: state.localVars};
|
||||
} else {
|
||||
if (inList(state.globalVars)) return;
|
||||
if (parserConfig.globalVars)
|
||||
state.globalVars = {name: varname, next: state.globalVars};
|
||||
}
|
||||
}
|
||||
|
||||
// Combinators
|
||||
|
||||
var defaultVars = {name: "this", next: {name: "arguments"}};
|
||||
function pushcontext() {
|
||||
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
|
||||
cx.state.localVars = defaultVars;
|
||||
}
|
||||
function popcontext() {
|
||||
cx.state.localVars = cx.state.context.vars;
|
||||
cx.state.context = cx.state.context.prev;
|
||||
}
|
||||
function pushlex(type, info) {
|
||||
var result = function() {
|
||||
var state = cx.state, indent = state.indented;
|
||||
if (state.lexical.type == "stat") indent = state.lexical.indented;
|
||||
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
|
||||
indent = outer.indented;
|
||||
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
|
||||
};
|
||||
result.lex = true;
|
||||
return result;
|
||||
}
|
||||
function poplex() {
|
||||
var state = cx.state;
|
||||
if (state.lexical.prev) {
|
||||
if (state.lexical.type == ")")
|
||||
state.indented = state.lexical.indented;
|
||||
state.lexical = state.lexical.prev;
|
||||
}
|
||||
}
|
||||
poplex.lex = true;
|
||||
|
||||
function expect(wanted) {
|
||||
function exp(type) {
|
||||
if (type == wanted) return cont();
|
||||
else if (wanted == ";") return pass();
|
||||
else return cont(exp);
|
||||
};
|
||||
return exp;
|
||||
}
|
||||
|
||||
function statement(type, value) {
|
||||
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
|
||||
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
||||
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||
if (type == "{") return cont(pushlex("}"), block, poplex);
|
||||
if (type == ";") return cont();
|
||||
if (type == "if") {
|
||||
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
|
||||
cx.state.cc.pop()();
|
||||
return cont(pushlex("form"), expression, statement, poplex, maybeelse);
|
||||
}
|
||||
if (type == "function") return cont(functiondef);
|
||||
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
|
||||
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
||||
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
||||
block, poplex, poplex);
|
||||
if (type == "case") return cont(expression, expect(":"));
|
||||
if (type == "default") return cont(expect(":"));
|
||||
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
||||
statement, poplex, popcontext);
|
||||
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
|
||||
if (type == "class") return cont(pushlex("form"), className, poplex);
|
||||
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
|
||||
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
|
||||
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||
}
|
||||
function expression(type) {
|
||||
return expressionInner(type, false);
|
||||
}
|
||||
function expressionNoComma(type) {
|
||||
return expressionInner(type, true);
|
||||
}
|
||||
function expressionInner(type, noComma) {
|
||||
if (cx.state.fatArrowAt == cx.stream.start) {
|
||||
var body = noComma ? arrowBodyNoComma : arrowBody;
|
||||
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
|
||||
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
||||
}
|
||||
|
||||
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||
if (type == "function") return cont(functiondef, maybeop);
|
||||
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
|
||||
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
|
||||
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
||||
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
|
||||
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
|
||||
if (type == "quasi") { return pass(quasi, maybeop); }
|
||||
return cont();
|
||||
}
|
||||
function maybeexpression(type) {
|
||||
if (type.match(/[;\}\)\],]/)) return pass();
|
||||
return pass(expression);
|
||||
}
|
||||
function maybeexpressionNoComma(type) {
|
||||
if (type.match(/[;\}\)\],]/)) return pass();
|
||||
return pass(expressionNoComma);
|
||||
}
|
||||
|
||||
function maybeoperatorComma(type, value) {
|
||||
if (type == ",") return cont(expression);
|
||||
return maybeoperatorNoComma(type, value, false);
|
||||
}
|
||||
function maybeoperatorNoComma(type, value, noComma) {
|
||||
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
||||
var expr = noComma == false ? expression : expressionNoComma;
|
||||
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
||||
if (type == "operator") {
|
||||
if (/\+\+|--/.test(value)) return cont(me);
|
||||
if (value == "?") return cont(expression, expect(":"), expr);
|
||||
return cont(expr);
|
||||
}
|
||||
if (type == "quasi") { return pass(quasi, me); }
|
||||
if (type == ";") return;
|
||||
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
|
||||
if (type == ".") return cont(property, me);
|
||||
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
||||
}
|
||||
function quasi(type, value) {
|
||||
if (type != "quasi") return pass();
|
||||
if (value.slice(value.length - 2) != "${") return cont(quasi);
|
||||
return cont(expression, continueQuasi);
|
||||
}
|
||||
function continueQuasi(type) {
|
||||
if (type == "}") {
|
||||
cx.marked = "string-2";
|
||||
cx.state.tokenize = tokenQuasi;
|
||||
return cont(quasi);
|
||||
}
|
||||
}
|
||||
function arrowBody(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
return pass(type == "{" ? statement : expression);
|
||||
}
|
||||
function arrowBodyNoComma(type) {
|
||||
findFatArrow(cx.stream, cx.state);
|
||||
return pass(type == "{" ? statement : expressionNoComma);
|
||||
}
|
||||
function maybelabel(type) {
|
||||
if (type == ":") return cont(poplex, statement);
|
||||
return pass(maybeoperatorComma, expect(";"), poplex);
|
||||
}
|
||||
function property(type) {
|
||||
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||
}
|
||||
function objprop(type, value) {
|
||||
if (type == "variable" || cx.style == "keyword") {
|
||||
cx.marked = "property";
|
||||
if (value == "get" || value == "set") return cont(getterSetter);
|
||||
return cont(afterprop);
|
||||
} else if (type == "number" || type == "string") {
|
||||
cx.marked = jsonldMode ? "property" : (cx.style + " property");
|
||||
return cont(afterprop);
|
||||
} else if (type == "jsonld-keyword") {
|
||||
return cont(afterprop);
|
||||
} else if (type == "[") {
|
||||
return cont(expression, expect("]"), afterprop);
|
||||
}
|
||||
}
|
||||
function getterSetter(type) {
|
||||
if (type != "variable") return pass(afterprop);
|
||||
cx.marked = "property";
|
||||
return cont(functiondef);
|
||||
}
|
||||
function afterprop(type) {
|
||||
if (type == ":") return cont(expressionNoComma);
|
||||
if (type == "(") return pass(functiondef);
|
||||
}
|
||||
function commasep(what, end) {
|
||||
function proceed(type) {
|
||||
if (type == ",") {
|
||||
var lex = cx.state.lexical;
|
||||
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
|
||||
return cont(what, proceed);
|
||||
}
|
||||
if (type == end) return cont();
|
||||
return cont(expect(end));
|
||||
}
|
||||
return function(type) {
|
||||
if (type == end) return cont();
|
||||
return pass(what, proceed);
|
||||
};
|
||||
}
|
||||
function contCommasep(what, end, info) {
|
||||
for (var i = 3; i < arguments.length; i++)
|
||||
cx.cc.push(arguments[i]);
|
||||
return cont(pushlex(end, info), commasep(what, end), poplex);
|
||||
}
|
||||
function block(type) {
|
||||
if (type == "}") return cont();
|
||||
return pass(statement, block);
|
||||
}
|
||||
function maybetype(type) {
|
||||
if (isTS && type == ":") return cont(typedef);
|
||||
}
|
||||
function typedef(type) {
|
||||
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
||||
}
|
||||
function vardef() {
|
||||
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||
}
|
||||
function pattern(type, value) {
|
||||
if (type == "variable") { register(value); return cont(); }
|
||||
if (type == "[") return contCommasep(pattern, "]");
|
||||
if (type == "{") return contCommasep(proppattern, "}");
|
||||
}
|
||||
function proppattern(type, value) {
|
||||
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
||||
register(value);
|
||||
return cont(maybeAssign);
|
||||
}
|
||||
if (type == "variable") cx.marked = "property";
|
||||
return cont(expect(":"), pattern, maybeAssign);
|
||||
}
|
||||
function maybeAssign(_type, value) {
|
||||
if (value == "=") return cont(expressionNoComma);
|
||||
}
|
||||
function vardefCont(type) {
|
||||
if (type == ",") return cont(vardef);
|
||||
}
|
||||
function maybeelse(type, value) {
|
||||
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
|
||||
}
|
||||
function forspec(type) {
|
||||
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
|
||||
}
|
||||
function forspec1(type) {
|
||||
if (type == "var") return cont(vardef, expect(";"), forspec2);
|
||||
if (type == ";") return cont(forspec2);
|
||||
if (type == "variable") return cont(formaybeinof);
|
||||
return pass(expression, expect(";"), forspec2);
|
||||
}
|
||||
function formaybeinof(_type, value) {
|
||||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||
return cont(maybeoperatorComma, forspec2);
|
||||
}
|
||||
function forspec2(type, value) {
|
||||
if (type == ";") return cont(forspec3);
|
||||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||
return pass(expression, expect(";"), forspec3);
|
||||
}
|
||||
function forspec3(type) {
|
||||
if (type != ")") cont(expression);
|
||||
}
|
||||
function functiondef(type, value) {
|
||||
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
||||
if (type == "variable") {register(value); return cont(functiondef);}
|
||||
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
|
||||
}
|
||||
function funarg(type) {
|
||||
if (type == "spread") return cont(funarg);
|
||||
return pass(pattern, maybetype);
|
||||
}
|
||||
function className(type, value) {
|
||||
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||
}
|
||||
function classNameAfter(type, value) {
|
||||
if (value == "extends") return cont(expression, classNameAfter);
|
||||
if (type == "{") return cont(pushlex("}"), classBody, poplex);
|
||||
}
|
||||
function classBody(type, value) {
|
||||
if (type == "variable" || cx.style == "keyword") {
|
||||
cx.marked = "property";
|
||||
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
|
||||
return cont(functiondef, classBody);
|
||||
}
|
||||
if (value == "*") {
|
||||
cx.marked = "keyword";
|
||||
return cont(classBody);
|
||||
}
|
||||
if (type == ";") return cont(classBody);
|
||||
if (type == "}") return cont();
|
||||
}
|
||||
function classGetterSetter(type) {
|
||||
if (type != "variable") return pass();
|
||||
cx.marked = "property";
|
||||
return cont();
|
||||
}
|
||||
function afterModule(type, value) {
|
||||
if (type == "string") return cont(statement);
|
||||
if (type == "variable") { register(value); return cont(maybeFrom); }
|
||||
}
|
||||
function afterExport(_type, value) {
|
||||
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
||||
return pass(statement);
|
||||
}
|
||||
function afterImport(type) {
|
||||
if (type == "string") return cont();
|
||||
return pass(importSpec, maybeFrom);
|
||||
}
|
||||
function importSpec(type, value) {
|
||||
if (type == "{") return contCommasep(importSpec, "}");
|
||||
if (type == "variable") register(value);
|
||||
return cont();
|
||||
}
|
||||
function maybeFrom(_type, value) {
|
||||
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||
}
|
||||
function arrayLiteral(type) {
|
||||
if (type == "]") return cont();
|
||||
return pass(expressionNoComma, maybeArrayComprehension);
|
||||
}
|
||||
function maybeArrayComprehension(type) {
|
||||
if (type == "for") return pass(comprehension, expect("]"));
|
||||
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
|
||||
return pass(commasep(expressionNoComma, "]"));
|
||||
}
|
||||
function comprehension(type) {
|
||||
if (type == "for") return cont(forspec, comprehension);
|
||||
if (type == "if") return cont(expression, comprehension);
|
||||
}
|
||||
|
||||
function isContinuedStatement(state, textAfter) {
|
||||
return state.lastType == "operator" || state.lastType == "," ||
|
||||
isOperatorChar.test(textAfter.charAt(0)) ||
|
||||
/[,.]/.test(textAfter.charAt(0));
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
var state = {
|
||||
tokenize: tokenBase,
|
||||
lastType: "sof",
|
||||
cc: [],
|
||||
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||
localVars: parserConfig.localVars,
|
||||
context: parserConfig.localVars && {vars: parserConfig.localVars},
|
||||
indented: 0
|
||||
};
|
||||
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
|
||||
state.globalVars = parserConfig.globalVars;
|
||||
return state;
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.sol()) {
|
||||
if (!state.lexical.hasOwnProperty("align"))
|
||||
state.lexical.align = false;
|
||||
state.indented = stream.indentation();
|
||||
findFatArrow(stream, state);
|
||||
}
|
||||
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if (type == "comment") return style;
|
||||
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
||||
return parseJS(state, style, type, content, stream);
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize == tokenComment) return CodeMirror.Pass;
|
||||
if (state.tokenize != tokenBase) return 0;
|
||||
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
|
||||
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
||||
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
|
||||
var c = state.cc[i];
|
||||
if (c == poplex) lexical = lexical.prev;
|
||||
else if (c != maybeelse) break;
|
||||
}
|
||||
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
|
||||
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
||||
lexical = lexical.prev;
|
||||
var type = lexical.type, closing = firstChar == type;
|
||||
|
||||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
|
||||
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||
else if (type == "form") return lexical.indented + indentUnit;
|
||||
else if (type == "stat")
|
||||
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
|
||||
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
|
||||
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||
},
|
||||
|
||||
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
|
||||
blockCommentStart: jsonMode ? null : "/*",
|
||||
blockCommentEnd: jsonMode ? null : "*/",
|
||||
lineComment: jsonMode ? null : "//",
|
||||
fold: "brace",
|
||||
|
||||
helperType: jsonMode ? "json" : "javascript",
|
||||
jsonldMode: jsonldMode,
|
||||
jsonMode: jsonMode
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
|
||||
|
||||
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||
CodeMirror.defineMIME("text/ecmascript", "javascript");
|
||||
CodeMirror.defineMIME("application/javascript", "javascript");
|
||||
CodeMirror.defineMIME("application/x-javascript", "javascript");
|
||||
CodeMirror.defineMIME("application/ecmascript", "javascript");
|
||||
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
|
||||
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
|
||||
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
|
||||
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
|
||||
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
|
||||
|
||||
});
|
||||