├── .editorconfig
├── .eslintrc.js
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── __static
├── app
│ ├── cache.manifest
│ ├── ddms_frame_callback.html
│ ├── html
│ │ ├── bookmark.html
│ │ ├── components.html
│ │ ├── donate.html
│ │ ├── main.html
│ │ ├── scripts.html
│ │ ├── sourcecode.html
│ │ └── styles.html
│ ├── index.html
│ ├── resources
│ │ ├── css
│ │ │ ├── bootstrap.min.css
│ │ │ ├── font-awesome.min.css
│ │ │ ├── prettify.css
│ │ │ └── style.css
│ │ ├── fonts
│ │ │ ├── Dressedless_Three.svg
│ │ │ ├── Dressedless_Three.ttf
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ ├── fontawesome-webfont.woff
│ │ │ └── fontawesome-webfont.woff2
│ │ └── images
│ │ │ ├── codelf_logo.png
│ │ │ ├── paypal.png
│ │ │ ├── twohardtings.jpg
│ │ │ ├── wechatpay.jpg
│ │ │ └── zhifubao.png
│ ├── scss
│ │ ├── _animate.scss
│ │ ├── _bookmark.scss
│ │ ├── _components.scss
│ │ ├── _donate.scss
│ │ ├── _main.scss
│ │ ├── _sourcecode.scss
│ │ ├── _util.scss
│ │ └── style.scss
│ ├── src
│ │ ├── App.js
│ │ ├── AppBundle.js
│ │ ├── Util.js
│ │ ├── lib
│ │ │ ├── all.js
│ │ │ ├── bootstrap.min.js
│ │ │ ├── clipboard.min.js
│ │ │ ├── fastclick.js
│ │ │ ├── jquery.highlight.js
│ │ │ ├── jquery.min.js
│ │ │ ├── lovefield.min.js
│ │ │ ├── prettify.js
│ │ │ └── tether.min.js
│ │ ├── model
│ │ │ ├── BookmarkModel.js
│ │ │ ├── DDMSModel.js
│ │ │ ├── Database.js
│ │ │ ├── Model.js
│ │ │ ├── SearchcodeModel.js
│ │ │ └── YoudaoTranslateModel.js
│ │ └── view
│ │ │ ├── BookmarkView.js
│ │ │ └── View.js
│ └── sw.js
├── data
│ └── repos.json
└── images
│ ├── codelf_logo.png
│ ├── demo1.jpg
│ ├── demo2.jpg
│ ├── paypal.png
│ ├── twohardtings.png
│ ├── twohardtings2.png
│ ├── wechatpay.jpg
│ └── zhifubao.png
├── app
├── ddms_frame_callback.html
├── index.html
└── opensearch.xml
├── assets
├── codelf_logo.psd
├── fonts
│ ├── Dressedless_Three.svg
│ ├── Dressedless_Three.ttf
│ ├── FontAwesome.otf
│ ├── LatoLatin-Bold.woff2
│ ├── LatoLatin-BoldItalic.woff2
│ ├── LatoLatin-Italic.woff2
│ ├── LatoLatin-Regular.woff2
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
└── images
│ ├── codelf_logo.png
│ ├── paypal.png
│ ├── twohardtings.jpg
│ ├── wechatdonate.jpg
│ ├── wechatpay.jpg
│ └── zhifubao.png
├── babel.config.js
├── build-system
├── build.js
├── clean.js
├── default.js
├── dist.js
├── lint.js
├── server.js
└── util.js
├── dist
├── css
│ ├── app.css
│ ├── app.f1364fce.css
│ ├── lib.b0f67b98.css
│ ├── lib.css
│ └── themes
│ │ └── default
│ │ └── assets
│ │ ├── fonts
│ │ ├── brand-icons.eot
│ │ ├── brand-icons.svg
│ │ ├── brand-icons.ttf
│ │ ├── brand-icons.woff
│ │ ├── brand-icons.woff2
│ │ ├── icons.eot
│ │ ├── icons.otf
│ │ ├── icons.svg
│ │ ├── icons.ttf
│ │ ├── icons.woff
│ │ ├── icons.woff2
│ │ ├── outline-icons.eot
│ │ ├── outline-icons.svg
│ │ ├── outline-icons.ttf
│ │ ├── outline-icons.woff
│ │ └── outline-icons.woff2
│ │ └── images
│ │ └── flags.png
├── ddms_frame_callback.html
├── fonts
│ ├── Dressedless_Three.svg
│ ├── Dressedless_Three.ttf
│ ├── FontAwesome.otf
│ ├── LatoLatin-Bold.woff2
│ ├── LatoLatin-BoldItalic.woff2
│ ├── LatoLatin-Italic.woff2
│ ├── LatoLatin-Regular.woff2
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── images
│ ├── codelf_logo.f4ae25bd.png
│ ├── codelf_logo.png
│ ├── paypal.69412e83.png
│ ├── paypal.png
│ ├── twohardtings.0db8462a.jpg
│ ├── twohardtings.jpg
│ ├── wechatdonate.3ba3a9d8.jpg
│ ├── wechatdonate.jpg
│ ├── wechatpay.5f11f80c.jpg
│ ├── wechatpay.jpg
│ ├── zhifubao.70c19370.png
│ └── zhifubao.png
├── index.html
├── js
│ ├── app.792fa086.js
│ ├── app.js
│ ├── app.js.map
│ ├── lib.5e430a5b.js
│ └── lib.js
├── opensearch.xml
└── sw.js
├── gulpfile.js
├── lib.config.js
├── package.json
├── src
├── App.js
├── components
│ ├── Bookmark.js
│ ├── Copybook.js
│ ├── Donate.js
│ ├── Doodle.js
│ ├── Loading.js
│ ├── SearchBar.js
│ ├── SearchError.js
│ ├── SourceCode.js
│ ├── Suggestion.js
│ ├── TitleLogo.js
│ ├── VariableItem.js
│ ├── VariableList.js
│ └── hooks
│ │ └── useCodeHighlighting.js
├── constants
│ └── Configs.js
├── containers
│ ├── CopybookContainer.js
│ ├── MainContainer.js
│ ├── NavBarContainer.js
│ └── NoticeContainer.js
├── models
│ ├── AppModel.js
│ ├── BaseModel.js
│ ├── CopybookModel.js
│ ├── DDMSModel.js
│ ├── ErrorModel.js
│ ├── SearchCodeModel.js
│ ├── Store.js
│ └── metadata
│ │ ├── BaiduTranslateData.js
│ │ ├── BingTranslateData.js
│ │ ├── BookmarkData.js
│ │ ├── GitHubData.js
│ │ └── YoudaoTranslateData.js
├── sw.js
├── utils
│ ├── FormHandler.js
│ ├── HashHandler.js
│ ├── JSONP.js
│ ├── LocalStorage.js
│ ├── Navigator.js
│ ├── Param.js
│ ├── Tools.js
│ └── TranslateHandler.js
└── vendors
│ ├── prettify.css
│ └── prettify.js
├── styles
├── _animation.scss
├── _common.scss
├── _components.scss
├── _constants.scss
├── _containers.scss
├── _copybook-container.scss
├── _donate.scss
├── _doodle.scss
├── _logo.scss
├── _main-container.scss
├── _nav-bar-container.scss
├── _notice-container.scss
├── _source-code.scss
├── _utils.scss
└── app.scss
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'extends': [
3 | 'eslint:recommended',
4 | 'plugin:react/recommended'
5 | ],
6 | 'plugins': [
7 | 'react-hooks'
8 | ],
9 | 'rules': {
10 | 'no-unused-vars': [2, {'vars': 'all', 'args': 'none'}],
11 | 'no-empty': [0],
12 | 'react/prop-types': [0],
13 | 'react/no-unescaped-entities': [0],
14 | 'react-hooks/rules-of-hooks': 'error',
15 | 'no-useless-escape': [0],
16 | 'no-control-regex': [0]
17 | },
18 | 'env': {
19 | 'es6': true,
20 | 'node': true,
21 | 'browser': true
22 | },
23 | 'globals': {
24 | 'React': true,
25 | 'ReactDOM': true,
26 | 'Promise': true,
27 | 'd3': true,
28 | 'NProgress': true,
29 | 'ClipboardJS': true,
30 | 'PR': true,
31 | 'Mark': true
32 | },
33 | 'parser': 'babel-eslint',
34 | 'parserOptions': {
35 | 'sourceType': 'module'
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | dist -diff
2 | assets -diff
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile ~/.gitignore_global
6 | .DS_Store
7 | Thumbs.db
8 | .sass-cache
9 | .idea
10 | .vscode
11 | lib-cov
12 | *.seed
13 | *.log
14 | *.csv
15 | *.dat
16 | *.out
17 | *.pid
18 | *.gz
19 |
20 | pids
21 | logs
22 | results
23 |
24 | package-lock.json
25 | npm-debug.log
26 | node_modules
27 | docs/html
28 | app/css
29 | app/js
30 | app/images
31 | app/fonts
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | SAY NO TO SUICIDE PUBLIC LICENSE
2 |
3 | Version 1.0, September 2017
4 |
5 | https://github.com/unbug/snts
6 |
7 | Copyright (C) 2017 @unbug
8 |
9 | Everyone is permitted to copy and distribute verbatim copies
10 | of this license document.
11 |
12 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, MODIFICATION, AND DISTRIBUTION
13 |
14 | 1. You can do anything with the original copy,
15 | whenever, whatever, no limitation.
16 |
17 | 2. When you are in despair, just talk to someone you trust,
18 | someone you love. Getting help from your family, your friends,
19 | the police, the community, the public.
20 |
21 | 3. Keep yourself alive and say no to suicide.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CODELF(变量命名神器)
6 | =================
7 | A search tool helps dev to solve the naming things problem.
8 |
9 | Search over projects from Github, Bitbucket, Google Code, Codeplex, Sourceforge, Fedora Project, GitLab to find real-world usage variable names.
10 |
11 | Also a daily Algorithm Copybook.
12 |
13 | Also a GitHub stars, repositories tagger and organizer tool.
14 |
15 | >There are only two hard things in Computer Science: cache invalidation and naming things.-- Phil Karlton
16 | >
17 | >
18 |
19 | 
20 |
21 | WIKI
22 | =================
23 | [简体中文](https://github.com/unbug/codelf/wiki)
24 |
25 | Plugins
26 | =================
27 | ### Codelf for VS Code
28 |
29 | ##### Install
30 | Codelf is on VS Code Extension Marketplace. Just search "codelf" on VS Code EXTENSIONS pane and click install.
31 |
32 | ##### Usage
33 | 1. Select text, right-click and select "Codelf".
34 |
35 |
36 |
37 | ### Codelf for Atom
38 |
39 | ##### Install
40 | Codelf is [on Atom package](https://atom.io/packages/codelf). Search "codelf" on Atom setting pane and click install.Please see [Atom Packages in the Atom Flight Manual](http://flight-manual.atom.io/using-atom/sections/atom-packages/)
41 |
42 | ##### Usage
43 | 1. Select text, right-click and click "Codelf".
44 | 2. Open Packages menu select "Codelf"
45 | 3. Press CTRL+ALT+E to open Codelf
46 |
47 |
48 |
49 | Also see [How to use Codelf on Atom](https://github.com/unbug/atom-codelf#usage)
50 |
51 |
52 | ### Codelf for Sublime Text
53 |
54 | ##### Install
55 | 1. [Download Codelf for Sublime](https://github.com/unbug/codelf/archive/st-0.0.5.zip) or [Select a "st-" version to download](https://github.com/unbug/codelf/tags)
56 | 2. Unzip and rename the folder to `Codelf`
57 | 3. Copy the folder into `Packages` directory, which you can find using the menu item `Sublime Text -> Preferences -> Browse Packages...`
58 | 4. Restart Sublime Text
59 |
60 | ##### Usage
61 | 1. Select text, right-click and click "Codelf".
62 |
63 | 
64 | 2. Open Command Palette using menu item Tools -> Command Palette... --> Type "E" or "Codelf" -->Select "Search Selection" or "Search From Input"
65 |
66 | 
67 |
68 | Apps
69 | =================
70 | [Codelf Chrome App](https://chrome.google.com/webstore/detail/codelf-best-github-stars/jnmjaglhmmcplekpfnblniiammmdpaan)
71 |
72 |
73 | Find me
74 | =================
75 | * Twitter [@unbug](https://twitter.com/unbug)
76 | * 微博 [@听奏](http://weibo.com/unbug)
77 |
78 | Videos
79 | ===============
80 | [](https://youtu.be/Uqg8HWaa-2c)
81 |
82 | Screenshots
83 | ================
84 |
85 | ### Search variable
86 |
87 | 
88 |
89 | 
90 |
91 | ### Daily Algorithm Copybook
92 |
93 | 
94 |
95 | 
96 |
97 | ### GitHub stars, repositories tagger and organizer tool
98 |
99 | 
100 |
101 | 
102 |
--------------------------------------------------------------------------------
/__static/app/cache.manifest:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 | # Build: _BUILD_VERSION_
3 |
4 | CACHE:
5 | _FILES_
6 |
7 | NETWORK:
8 | *
9 |
--------------------------------------------------------------------------------
/__static/app/ddms_frame_callback.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/__static/app/html/components.html:
--------------------------------------------------------------------------------
1 |
11 |
23 |
--------------------------------------------------------------------------------
/__static/app/html/donate.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 赞助 @听奏 这个月的房租
5 |
6 |
7 |

8 |

9 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/__static/app/html/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Search over projects from GitHub, Bitbucket, GitLab to find
5 | real-world usage variable names
6 |
7 |
49 |
56 |
57 |
58 |
59 |
68 |
69 |
70 |
71 |
72 |
75 |
76 |
77 |
78 |
79 |
80 |
86 |
94 |
--------------------------------------------------------------------------------
/__static/app/html/scripts.html:
--------------------------------------------------------------------------------
1 |
2 |
9 |
12 |
143 |
--------------------------------------------------------------------------------
/__static/app/html/sourcecode.html:
--------------------------------------------------------------------------------
1 |
37 |
--------------------------------------------------------------------------------
/__static/app/html/styles.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/__static/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | CODELF
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | @@include("html/styles.html")
15 |
21 |
22 |
23 | @@include("html/main.html")
24 | @@include("html/sourcecode.html")
25 | @@include("html/bookmark.html")
26 | @@include("html/donate.html")
27 | @@include("html/components.html")
28 |
29 | @@include("html/scripts.html")
30 |
31 |
32 |
--------------------------------------------------------------------------------
/__static/app/resources/css/prettify.css:
--------------------------------------------------------------------------------
1 | .pln {
2 | color: #000
3 | }
4 |
5 | @media screen {
6 | .str {
7 | color: #080
8 | }
9 |
10 | .kwd {
11 | color: #008
12 | }
13 |
14 | .com {
15 | color: #800
16 | }
17 |
18 | .typ {
19 | color: #606
20 | }
21 |
22 | .lit {
23 | color: #066
24 | }
25 |
26 | .pun, .opn, .clo {
27 | color: #660
28 | }
29 |
30 | .tag {
31 | color: #008
32 | }
33 |
34 | .atn {
35 | color: #606
36 | }
37 |
38 | .atv {
39 | color: #080
40 | }
41 |
42 | .dec, .var {
43 | color: #606
44 | }
45 |
46 | .fun {
47 | color: red
48 | }
49 | }
50 |
51 | @media print, projection {
52 | .str {
53 | color: #060
54 | }
55 |
56 | .kwd {
57 | color: #006;
58 | font-weight: bold
59 | }
60 |
61 | .com {
62 | color: #600;
63 | font-style: italic
64 | }
65 |
66 | .typ {
67 | color: #404;
68 | font-weight: bold
69 | }
70 |
71 | .lit {
72 | color: #044
73 | }
74 |
75 | .pun, .opn, .clo {
76 | color: #440
77 | }
78 |
79 | .tag {
80 | color: #006;
81 | font-weight: bold
82 | }
83 |
84 | .atn {
85 | color: #404
86 | }
87 |
88 | .atv {
89 | color: #060
90 | }
91 | }
92 |
93 | pre.prettyprint {
94 | padding: 2px;
95 | border: 1px solid #888
96 | }
97 |
98 | ol.linenums {
99 | margin-top: 0;
100 | margin-bottom: 0
101 | }
102 |
103 | li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
104 | list-style-type: none
105 | }
106 |
107 | li.L1, li.L3, li.L5, li.L7, li.L9 {
108 | background: #eee
109 | }
110 |
--------------------------------------------------------------------------------
/__static/app/resources/fonts/Dressedless_Three.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/Dressedless_Three.ttf
--------------------------------------------------------------------------------
/__static/app/resources/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/__static/app/resources/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/__static/app/resources/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/__static/app/resources/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/__static/app/resources/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/__static/app/resources/images/codelf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/images/codelf_logo.png
--------------------------------------------------------------------------------
/__static/app/resources/images/paypal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/images/paypal.png
--------------------------------------------------------------------------------
/__static/app/resources/images/twohardtings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/images/twohardtings.jpg
--------------------------------------------------------------------------------
/__static/app/resources/images/wechatpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/images/wechatpay.jpg
--------------------------------------------------------------------------------
/__static/app/resources/images/zhifubao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/app/resources/images/zhifubao.png
--------------------------------------------------------------------------------
/__static/app/scss/_animate.scss:
--------------------------------------------------------------------------------
1 | .animated {
2 | animation-duration: 1s;
3 | animation-fill-mode: both;
4 | }
5 |
6 | .animated.infinite {
7 | animation-iteration-count: infinite;
8 | }
9 |
10 | .animated.hinge {
11 | animation-duration: 2s;
12 | }
13 |
14 | @keyframes fadeIn {
15 | from {
16 | opacity: 0;
17 | }
18 |
19 | to {
20 | opacity: 1;
21 | }
22 | }
23 |
24 | @keyframes fadeInDown {
25 | from {
26 | opacity: 0;
27 | transform: translate3d(0, -100%, 0);
28 | }
29 |
30 | to {
31 | opacity: 1;
32 | transform: none;
33 | }
34 | }
35 |
36 | .fadeIn {
37 | animation-name: fadeIn;
38 | }
39 |
40 | .fadeInDown {
41 | animation-name: fadeInDown;
42 | }
43 |
--------------------------------------------------------------------------------
/__static/app/scss/_bookmark.scss:
--------------------------------------------------------------------------------
1 | .bookmark-logo {
2 | cursor: pointer;
3 | color: #70B7FD;
4 | }
5 |
6 | .bookmark-modal {
7 | .modal-header{
8 | .btn, .btn-group{
9 | margin-right: .4rem;
10 | &:last-child{
11 | margin-right: 0;
12 | }
13 | }
14 | .btn-group{
15 | padding: 0;
16 | margin: 0;
17 | }
18 | }
19 | .modal-body {
20 | padding: 0;
21 | > .hd {
22 | display: none;
23 | padding: 1rem;
24 | > div {
25 | display: none;
26 | }
27 | &.loading, &.empty, &.loading > .loading, &.empty > .empty {
28 | display: block;
29 | margin: 0 auto;
30 | }
31 | > .empty {
32 | text-align: center;
33 | .top {
34 | margin: 2rem;
35 | }
36 | .tip {
37 | text-align: left;
38 | }
39 | }
40 | }
41 | }
42 | .card-block, .card-header {
43 | padding: .5rem;
44 | color: #373a3c;
45 | }
46 | .card-footer {
47 | padding: 0 0 .2rem .2rem;
48 | }
49 | .repo-list {
50 | padding-right: 0;
51 | padding-left: 0;
52 | padding-bottom: 0;
53 | }
54 | .repo-group-item {
55 | border: 0;
56 | margin-bottom: 0;
57 | > .hd {
58 | .dropdown-menu {
59 | min-width: initial;
60 | }
61 | .search {
62 | display: none;
63 | cursor: pointer;
64 | max-width: 70%;
65 | margin-top: -0.25rem;
66 | }
67 | }
68 | &[data-id="0"] > .hd .search {
69 | display: block;
70 | }
71 | .hd .ctrl > div {
72 | display: inline-block;
73 | padding: 0 .4rem;
74 | cursor: pointer;
75 | }
76 | &[data-id="0"] > .hd .ctrl {
77 | display: none;
78 | }
79 | .repo-item {
80 | border-top: 0;
81 | border-bottom: 0;
82 | border-left: 0;
83 | border-right: 0;
84 | border-radius: 0;
85 | &:last-child {
86 | margin-bottom: 0;
87 | }
88 | .card-footer {
89 | border-top: 0;
90 | }
91 | a {
92 | word-break: break-all;
93 | }
94 | }
95 | }
96 | .dropdown-menu .dropdown-item.add-repo {
97 | .label {
98 | width: 1.15rem;
99 | height: 1.15rem;
100 | margin-bottom: -0.2rem;
101 | i {
102 | display: none;
103 | color: #fff;
104 | }
105 | }
106 | &[data-selected] .label {
107 | padding-left: 0;
108 | padding-right: 0;
109 | i {
110 | display: inline-block;
111 | }
112 | }
113 | }
114 | .tag-dots span {
115 | margin-left: .25rem;
116 | }
117 | }
118 |
119 | .bookmark-user-modal {
120 | .user-item:first-child {
121 | margin-top: 1rem;
122 | }
123 | .user-list .ctrl {
124 | margin-top: -0.25rem;
125 | }
126 | }
127 |
128 | @media (max-width: 34em) {
129 | .bookmark-modal {
130 | .tag-dots span {
131 | margin-left: -.25rem;
132 | }
133 | .modal-header {
134 | .btn{
135 | padding: .25rem;
136 | margin-right: .25rem;
137 | }
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/__static/app/scss/_components.scss:
--------------------------------------------------------------------------------
1 | /*
2 | http://www.fontspace.com/538fonts/dressedless
3 | https://everythingfonts.com/ttf-to-svg
4 | */
5 | @font-face {
6 | font-family: 'Dressedless Three';
7 | src: url('resources/fonts/Dressedless_Three.ttf') format("truetype"), url('resources/fonts/Dressedless_Three.svg') format("svg");
8 | /* Legacy iOS */
9 | }
10 | /*https://github.com/tobiasahlin/SpinKit*/
11 | /* spinner */
12 | .spinner {
13 | -webkit-animation: sk-rotateplane 1.2s infinite cubic-bezier(0.4, 0, 0.2, 1);
14 | animation: sk-rotateplane 1.2s infinite cubic-bezier(0.4, 0, 0.2, 1);
15 | }
16 |
17 | @-webkit-keyframes sk-rotateplane {
18 | 0% {
19 | -webkit-transform: perspective(120px);
20 | }
21 |
22 | 50% {
23 | -webkit-transform: perspective(120px) rotateY(180deg);
24 | }
25 |
26 | 100% {
27 | -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg);
28 | }
29 | }
30 |
31 |
32 | @keyframes sk-rotateplane {
33 | 0% {
34 | transform: perspective(120px) rotateX(0deg) rotateY(0deg);
35 | -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
36 | }
37 |
38 | 50% {
39 | transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
40 | -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
41 | }
42 |
43 | 100% {
44 | transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
45 | -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
46 | }
47 | }
48 | /*end spinner*/
49 | .logo {
50 | margin: 0 auto;
51 | width: 3rem;
52 | height: 3rem;
53 | img {
54 | display: inherit;
55 | width: 100%;
56 | height: 100%;
57 | border-radius: 20%;
58 | }
59 | }
60 | .nav-bar{
61 | position: absolute;
62 | top: 0.15rem;;
63 | right: 5%;
64 | z-index: 10;
65 | display: inline-block;
66 | transition: all 1s;
67 | >*{
68 | float: left;
69 | display: inline-block;
70 | margin-right: .45rem;
71 | }
72 | &:last-child{
73 | margin-right: 0;
74 | }
75 | i{
76 | color: #70B7FD;
77 | &:hover,&:active{
78 | color: #59AAF9;
79 | }
80 | }
81 | $anim-delay: 150ms;
82 | $anim-duration: 500ms;
83 | @for $i from 1 through 5 {
84 | >*:nth-child(#{$i}) {
85 | animation-duration: $anim-duration;
86 | animation-delay: 500 + $anim-delay*($i - 1);
87 | }
88 | }
89 | }
90 | @media (max-width: 34em) {
91 | .nav-bar{
92 | right: 1%;
93 | }
94 | }
95 | @media (min-width: 100em) {
96 | .nav-bar{
97 | right: 15%;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/__static/app/scss/_donate.scss:
--------------------------------------------------------------------------------
1 | .donate {
2 | display: block;
3 | padding-bottom: 5rem;
4 | margin-top: 1rem;
5 | text-align: center;
6 | form {
7 | display: inline-block;
8 | }
9 | .title {
10 | padding-bottom: .8rem;
11 | text-align: center;
12 | .lang {
13 | display: none;
14 | }
15 | &.cn .cn, &.en .en {
16 | display: block;
17 | }
18 | }
19 | .bd {
20 | display: block;
21 | width: 100%;
22 | margin: 0 auto;
23 | text-align: center;
24 | }
25 | }
26 |
27 | .zhifubao, .wechatpay {
28 | margin-right: 1rem;
29 | margin-top: -3rem;
30 | width: 5rem;
31 | }
32 |
33 | .paypal {
34 | width: 5rem;
35 | }
36 |
37 | body.dark {
38 | .zhifubao, .wechatpay, .paypal {
39 | background-color: #fff;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/__static/app/scss/_main.scss:
--------------------------------------------------------------------------------
1 | .main {
2 | padding-top: 2.5rem;
3 | }
4 |
5 | .main-title {
6 | text-align: center;
7 | padding: 0 1.2rem;
8 | > header a {
9 | color: inherit;
10 | text-decoration: none;
11 | &:visited, &:link, &:active, &:hover {
12 | color: inherit;
13 | text-decoration: none;
14 | }
15 | }
16 | h1 {
17 | font-family: "Dressedless Three",Roboto,"Helvetica Neue",Helvetica,Arial,sans-serif;
18 | text-transform: uppercase;
19 | font-size: 3.5rem;
20 | &.animated span {
21 | transition: color 250ms linear;
22 | /*C*/
23 | &:nth-child(1) {
24 | color: #3369e8;
25 | transition-delay: 200ms;
26 | }
27 | /*O*/
28 | &:nth-child(2) {
29 | color: #d50f25;
30 | transition-delay: 350ms;
31 | }
32 | /*D*/
33 | &:nth-child(3) {
34 | color: #eeb211;
35 | transition-delay: 500ms;
36 | }
37 | /*E*/
38 | &:nth-child(4) {
39 | color: #3369e8;
40 | transition-delay: 650ms;
41 | }
42 | /*L*/
43 | &:nth-child(5) {
44 | color: #009925;
45 | transition-delay: 800ms;
46 | }
47 | /*F*/
48 | &:nth-child(6) {
49 | color: #d50f25;
50 | transition-delay: 950ms;
51 | }
52 | }
53 | }
54 | h5 {
55 | max-height: 300px;
56 | transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1);
57 | overflow: hidden;
58 |
59 | .label {
60 | background-color: #71b7fd;
61 | }
62 | }
63 | }
64 |
65 | .search-form {
66 | padding: 1rem 0;
67 | .input-group{
68 | height: 44px;
69 | border-radius: 2px;
70 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16), 0 0 0 1px rgba(0,0,0,0.08);
71 | transition: box-shadow 200ms cubic-bezier(0.4, 0.0, 0.2, 1);
72 | &:focus, &:active, &:hover {
73 | box-shadow: 0 3px 8px 0 rgba(0,0,0,0.2), 0 0 0 1px rgba(0,0,0,0.08);
74 | }
75 | }
76 | input, button, a {
77 | height: 44px;
78 | line-height: 44px;
79 | padding-top: 0;
80 | padding-bottom: 0;
81 | border: 0 !important;
82 | }
83 | .dropdown-menu {
84 | max-height: 320px;
85 | overflow-y: scroll;
86 | -webkit-overflow-scrolling: touch;
87 | transform: translate3d(0, 0, 0);
88 | }
89 | button.search{
90 | .more{
91 | display: none;
92 | }
93 | &.more{
94 | .normal{
95 | display: none;
96 | }
97 | .more{
98 | display: inline-block;
99 | }
100 | }
101 | }
102 | }
103 | .search-relate a:hover {
104 | text-decoration: underline;
105 | }
106 |
107 | .search-result {
108 | padding-top: .8rem;
109 | .ct {
110 | border-left: .15rem solid #eceeef;
111 | background: none;
112 | &.ct--white {
113 | border-left: 0;
114 | }
115 | }
116 | .variable-wrap {
117 | display: inline-block;
118 | cursor: pointer;
119 | .btn-sm {
120 | margin-right: .4rem;
121 | padding: 0 .4em;
122 | font-weight: bold;
123 | }
124 | }
125 | a:hover {
126 | text-decoration: underline;
127 | }
128 | .hd {
129 | text-align: center;
130 | > div {
131 | text-align: center;
132 | display: none;
133 | }
134 | &.loading .loading, &.error .error {
135 | display: block;
136 | margin: 0 auto;
137 | }
138 | .logo {
139 | margin: 0 auto 1rem;
140 | }
141 | }
142 | }
143 | .notice-link{
144 | position: fixed;
145 | bottom: 0;
146 | left: 0;
147 | width: 100%;
148 | height: 3rem;
149 | padding: 1rem;
150 | text-align: center;
151 | background: #fff;
152 | }
153 | .notice-link a {
154 | display: none;
155 | }
156 | .popover--variable {
157 | background-color: transparent;
158 | border-left: 0;
159 | border-right: 0;
160 | border-top: 0;
161 | border-color: #ccc;
162 | .popover-content {
163 | padding: 0;
164 | }
165 | .btn {
166 | border-bottom: 0;
167 | }
168 | }
169 | .variable-btns > .variable-btns__copy {
170 | display: none;
171 | }
172 | body.mobile .variable-btns__copy {
173 | display: none !important;
174 | }
175 | body.dark {
176 | .search-form .input-group {
177 | box-shadow: 0 2px 2px 0 rgba(255,255,255,0.16), 0 0 0 1px rgba(255,255,255,0.08);
178 | &:focus, &:active, &:hover {
179 | box-shadow: 0 3px 12px 0 rgba(255,255,255,0.2), 0 0 0 1px rgba(255,255,255,0.08);
180 | }
181 | }
182 | .search-result {
183 | .ct, hr {
184 | border-color: rgba(0,0,0,.16);
185 | }
186 | }
187 | .notice-link {
188 | background: #272b38;
189 | }
190 | .popover--variable {
191 | border-bottom: 0;
192 | }
193 | }
194 | @media (max-width: 767px){
195 | .search-form {
196 | button.search{
197 | border-top-right-radius: .25rem !important;
198 | border-bottom-right-radius: .25rem !important;;
199 | }
200 | }
201 | }
202 | @media (max-width: 34em) {
203 | .search-result {
204 | .ct {
205 | overflow-x: scroll;
206 | -webkit-overflow-scrolling: touch;
207 | }
208 | }
209 | }
210 | @media (min-width: 62em) {
211 | .main-title h1 {
212 | font-size: 4.5rem;
213 | }
214 | .search-relate {
215 | padding-bottom: 1.8rem;
216 | }
217 | .search-result .ct {
218 | overflow-x: auto;
219 | }
220 | .variable-btns > .variable-btns__copy {
221 | display: block;
222 | }
223 | }
224 | @media (min-width: 100em) {
225 | .main {
226 | padding-top: 5rem;
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/__static/app/scss/_sourcecode.scss:
--------------------------------------------------------------------------------
1 | .sourcecode-modal {
2 | .dropdown-menu {
3 | max-height: 320px;
4 | overflow-y: scroll;
5 | -webkit-overflow-scrolling: touch;
6 | transform: translate3d(0, 0, 0);
7 | }
8 | .cur-repo {
9 | margin-left: .4rem;
10 | }
11 | code {
12 | display: inline-block;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/__static/app/scss/_util.scss:
--------------------------------------------------------------------------------
1 | .fix-break-word, p {
2 | word-break: break-all;
3 | word-break: break-word;
4 | -webkit-hyphens: auto;
5 | hyphens: auto;
6 | }
7 | .label {
8 | margin-right: .4rem;
9 | }
10 | .blockquote {
11 | border: none;
12 | text-align: center;
13 | img {
14 | max-width: 100%;
15 | height: auto;
16 | }
17 | }
18 | .jumbotron{
19 | margin-bottom: 0;
20 | }
21 | .highlight {
22 | background-color: #FFFF88;
23 | }
24 | .modal-header .close {
25 | padding-left: .65rem;
26 | }
27 |
28 | .modal--fix {
29 | max-height: 98%;
30 | .modal-dialog {
31 | height: 100%;
32 | max-width: 100%;
33 | overflow: hidden;
34 | }
35 | .modal-content {
36 | height: 100%;
37 | max-width: 100%;
38 | overflow: hidden;
39 | padding-bottom: 8%;
40 | }
41 | .modal-body {
42 | max-height: 98%;
43 | overflow: scroll;
44 | -webkit-overflow-scrolling: touch;
45 | }
46 | }
47 | @media (min-width: 62em) {
48 | .modal--fix {
49 | max-height: none;
50 | .modal-dialog, .modal-content, .modal-body {
51 | height: auto;
52 | overflow: auto;
53 | }
54 | .modal-content {
55 | padding-bottom: 0;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/__static/app/scss/style.scss:
--------------------------------------------------------------------------------
1 | html, body {
2 | width: 100%;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
4 | -webkit-font-smoothing: antialiased;
5 | transition: all 350ms cubic-bezier(0.4, 0, 0.2, 1);
6 | }
7 | @import "util.scss";
8 | @import "animate.scss";
9 | @import "components.scss";
10 | @import "main.scss";
11 | @import "donate.scss";
12 | @import "sourcecode.scss";
13 | @import "bookmark.scss";
14 |
15 | body.dark {
16 | background: #272b38;
17 | color: #fff;
18 | }
19 |
--------------------------------------------------------------------------------
/__static/app/src/App.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 | require('./view/View.js');
3 | require('./view/BookmarkView.js');
4 | });
5 |
--------------------------------------------------------------------------------
/__static/app/src/lib/all.js:
--------------------------------------------------------------------------------
1 | @@include("jquery.min.js")
2 | @@include("jquery.highlight.js")
3 | @@include("tether.min.js")
4 | @@include("bootstrap.min.js")
5 | @@include("prettify.js")
6 | @@include("clipboard.min.js")
7 | @@include("lovefield.min.js")
8 | @@include("fastclick.js")
9 |
--------------------------------------------------------------------------------
/__static/app/src/lib/jquery.highlight.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Highlight plugin
3 | *
4 | * Based on highlight v3 by Johann Burkard
5 | * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
6 | *
7 | * Code a little bit refactored and cleaned (in my humble opinion).
8 | * Most important changes:
9 | * - has an option to highlight only entire words (wordsOnly - false by default),
10 | * - has an option to be case sensitive (caseSensitive - false by default)
11 | * - highlight element tag and class names can be specified in options
12 | *
13 | * Usage:
14 | * // wrap every occurrance of text 'lorem' in content
15 | * // with (default options)
16 | * $('#content').highlight('lorem');
17 | *
18 | * // search for and highlight more terms at once
19 | * // so you can save some time on traversing DOM
20 | * $('#content').highlight(['lorem', 'ipsum']);
21 | * $('#content').highlight('lorem ipsum');
22 | *
23 | * // search only for entire word 'lorem'
24 | * $('#content').highlight('lorem', { wordsOnly: true });
25 | *
26 | * // don't ignore case during search of term 'lorem'
27 | * $('#content').highlight('lorem', { caseSensitive: true });
28 | *
29 | * // wrap every occurrance of term 'ipsum' in content
30 | * // with
31 | * $('#content').highlight('ipsum', { element: 'em', className: 'important' });
32 | *
33 | * // remove default highlight
34 | * $('#content').unhighlight();
35 | *
36 | * // remove custom highlight
37 | * $('#content').unhighlight({ element: 'em', className: 'important' });
38 | *
39 | *
40 | * Copyright (c) 2009 Bartek Szopka
41 | *
42 | * Licensed under MIT license.
43 | *
44 | */
45 |
46 | jQuery.extend({
47 | highlight: function (node, re, nodeName, className) {
48 | if (node.nodeType === 3) {
49 | var match = node.data.match(re);
50 | if (match) {
51 | var highlight = document.createElement(nodeName || 'span');
52 | highlight.className = className || 'highlight';
53 | var wordNode = node.splitText(match.index);
54 | wordNode.splitText(match[0].length);
55 | var wordClone = wordNode.cloneNode(true);
56 | highlight.appendChild(wordClone);
57 | wordNode.parentNode.replaceChild(highlight, wordNode);
58 | return 1; //skip added node in parent
59 | }
60 | } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
61 | !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
62 | !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
63 | for (var i = 0; i < node.childNodes.length; i++) {
64 | i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
65 | }
66 | }
67 | return 0;
68 | }
69 | });
70 |
71 | jQuery.fn.unhighlight = function (options) {
72 | var settings = { className: 'highlight', element: 'span' };
73 | jQuery.extend(settings, options);
74 |
75 | return this.find(settings.element + "." + settings.className).each(function () {
76 | var parent = this.parentNode;
77 | parent.replaceChild(this.firstChild, this);
78 | parent.normalize();
79 | }).end();
80 | };
81 |
82 | jQuery.fn.highlight = function (words, options) {
83 | var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
84 | jQuery.extend(settings, options);
85 |
86 | if (words.constructor === String) {
87 | words = [words];
88 | }
89 | words = jQuery.grep(words, function(word, i){
90 | return word != '';
91 | });
92 | words = jQuery.map(words, function(word, i) {
93 | return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
94 | });
95 | if (words.length == 0) { return this; };
96 |
97 | var flag = settings.caseSensitive ? "" : "i";
98 | var pattern = "(" + words.join("|") + ")";
99 | if (settings.wordsOnly) {
100 | pattern = "\\b" + pattern + "\\b";
101 | }
102 | var re = new RegExp(pattern, flag);
103 |
104 | return this.each(function () {
105 | jQuery.highlight(this, re, settings.element, settings.className);
106 | });
107 | };
108 |
109 |
--------------------------------------------------------------------------------
/__static/app/src/model/DDMSModel.js:
--------------------------------------------------------------------------------
1 | var Util = require('Util.js');
2 |
3 | module.exports = new function () {
4 | var formAction = '//ddms.mihtool.com/apis/v1/formdata/';
5 | var formDataAction = '//ddms.mihtool.com/apis/v1/formdata_detail/';
6 | var persistKeyWordsName = 'codelf_ddms_keywords';
7 | var persistOrganizerName = 'codelf_ddms_group_sync_id';
8 | var persistKeyWordsTimerName = persistKeyWordsName + '_timer';
9 | var cacheKeyWords = (Util.localStorage.get(persistKeyWordsName) || '').split(',');
10 | var ot = new Date(Util.localStorage.get(persistKeyWordsTimerName) || 0);
11 | var nt = new Date().getTime();
12 | var OrganizerSyncId;
13 |
14 | if ((nt - ot) > 1000 * 60 * 60 * 24) {
15 | cacheKeyWords = [];
16 | Util.localStorage.set(persistKeyWordsTimerName, nt);
17 | }
18 | function saveKeyWords(val) {
19 | if (!Util.isInArray(cacheKeyWords, val)) {
20 | cacheKeyWords.push(val);
21 | Util.localStorage.set(persistKeyWordsName, cacheKeyWords.join(',').replace(/^,*/g, '').replace(/,*&/g, ''));
22 | }
23 | }
24 |
25 | this.setOrganizerSyncId = function (val) {
26 | OrganizerSyncId = val;
27 | Util.localStorage.set(persistOrganizerName, val);
28 | }
29 |
30 | this.getOrganizerSyncId = function () {
31 | return OrganizerSyncId || Util.localStorage.get(persistOrganizerName);
32 | }
33 |
34 | this.postKeyWords = function (val) {
35 | if (val && !Util.isInArray(cacheKeyWords, val)) {
36 | Util.FormHandler.asyncSubmit(formAction, {
37 | formid: '56e58775ade3a8e84dbacadf',
38 | keyword: val
39 | });
40 | saveKeyWords(val);
41 | }
42 | }
43 | this.postBookmarkUser = function (val) {
44 | if (val) {
45 | Util.FormHandler.asyncSubmit(formAction, {
46 | formid: '56e587a9ade3a8e84dbacae1',
47 | account: val
48 | });
49 | }
50 | }
51 | this.postBookmarkGroup = function (repoid,repourl,groupname,lang,stars) {
52 | if (repoid) {
53 | Util.FormHandler.asyncSubmit(formAction, {
54 | formid: '56e587ecade3a8e84dbacae3',
55 | repoid: repoid,
56 | repourl: repourl,
57 | groupname: groupname,
58 | lang: lang,
59 | stars: stars
60 | });
61 | }
62 | }
63 | this.postBookmarkOrganizer = function (data, callback) {
64 | if (data) {
65 | window.afterPostBookmarkOrganizer = callback;
66 | Util.FormHandler.asyncSubmit(formAction, {
67 | formid: '56fb7d9dade3a8e84dbacaf0',
68 | success_url: Util.thisPath+'ddms_frame_callback.html?frame_callback=afterPostBookmarkOrganizer',
69 | data: data
70 | });
71 | }
72 | }
73 | this.postUpdateBookmarkOrganizer = function (id, data, callback) {
74 | if (id && data) {
75 | window.afterPostUpdateBookmarkOrganizer = callback;
76 | Util.FormHandler.asyncSubmit(formDataAction, {
77 | id: id,
78 | success_url: Util.thisPath+'ddms_frame_callback.html?frame_callback=afterPostUpdateBookmarkOrganizer',
79 | data: data
80 | });
81 | }
82 | }
83 | this.getBookmarkOrganizer = function (id, callback) {
84 | $.getJSON(formDataAction+'?callback=?',
85 | {
86 | id: id
87 | },
88 | function (data) {
89 | if (data) {
90 | callback && callback(data);
91 | }
92 | });
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/__static/app/src/model/Database.js:
--------------------------------------------------------------------------------
1 | var Util = require('Util.js');
2 |
3 | exports.schemaBuilder = lf.schema.create('Codelf', 6);
4 | exports.eventType = {
5 | C: 'CREATE',
6 | U: 'UPDATED',
7 | D: 'DELETE'
8 | };
9 |
10 |
--------------------------------------------------------------------------------
/__static/app/src/model/Model.js:
--------------------------------------------------------------------------------
1 | var Util = require('Util.js');
2 | var Database = require('model/Database.js');
3 |
4 | //model
5 | //http://githut.info/
6 | exports.TopProgramLan = [{"id": "22,106", "language": "JavaScript, CoffeeScript"}, {
7 | "id": "133,135",
8 | "language": "CSS"
9 | }, {"id": "3,39", "language": "HTML"}, {"id": 137, "language": "Swift"}, {
10 | "id": 35,
11 | "language": "Objective-C"
12 | }, {"id": 23, "language": "Java"}, {"id": 19, "language": "Python"}, {"id": 24, "language": "PHP"}, {
13 | "id": 32,
14 | "language": "Ruby"
15 | }, {"id": 28, "language": "C"}, {"id": 16, "language": "C++"}, {"id": 6, "language": "C#"}, {
16 | "id": 55,
17 | "language": "Go"
18 | }, {"id": 51, "language": "Perl"}, {"id": "104,109", "language": "Clojure, ClojureScript"}, {
19 | "id": 40,
20 | "language": "Haskell"
21 | }, {"id": 54, "language": "Lua"}, {"id": 20, "language": "Matlab"}, {"id": 144, "language": "R"}, {
22 | "id": 47,
23 | "language": "Scala"
24 | }, {"id": "69,78,146", "language": "Shell"}, {"id": 29, "language": "Lisp"}, {"id": 42, "language": "ActionScript"}];
25 |
26 | exports.BeanHelpers = new function () {
27 | this.getRandomLabelType = function () {
28 | var types = ['primary', 'secondary', 'success', 'info', 'warning', 'danger'];
29 | return Util.randomList(types, 1)[0];
30 | };
31 |
32 | this.getKeyWordReg = function (key) {
33 | return new RegExp('([\\-_\\w\\d\\/\\$]{0,}){0,1}' + key + '([\\-_\\w\\d\\$]{0,}){0,1}', 'gi');
34 | }
35 | };
36 | exports.Searchcode = require('./SearchcodeModel');
37 | exports.YoudaoTranslate = require('./YoudaoTranslateModel');
38 | exports.Bookmark = require('./BookmarkModel');
39 | exports.DDMS = require('./DDMSModel');
40 |
41 | //init DB
42 | Database.schemaBuilder.connect({
43 | storeType: Util.os.ios?lf.schema.DataStoreType.WEB_SQL: null
44 | }).then(function (db) {
45 | $(window).trigger('DB:ready',db);
46 | });
47 |
--------------------------------------------------------------------------------
/__static/app/src/model/SearchcodeModel.js:
--------------------------------------------------------------------------------
1 | var Util = require('Util.js');
2 | var Database = require('model/Database.js');
3 |
4 |
5 | module.exports = new function () {
6 | var _this = this;
7 | var DB;
8 | var schemaBuilder = Database.schemaBuilder;
9 | var Tables;
10 | var DBEventType = Database.eventType;
11 | var win = $(window);
12 |
13 | schemaBuilder
14 | .createTable('SourceCode')
15 | .addColumn('id', lf.Type.INTEGER)
16 | .addColumn('sid', lf.Type.OBJECT)
17 | .addColumn('htm', lf.Type.OBJECT)
18 | .addColumn('create', lf.Type.DATE_TIME)
19 | .addPrimaryKey(['id'], true);
20 |
21 | var persistLangsName = 'codelf_langs_selected';
22 | var langs = Util.localStorage.get(persistLangsName), langQuery;
23 | var page = 0;
24 | var lastVal;
25 | var cacheSourceCodes = {};
26 | var cacheSourceCodeHtmls = {};
27 | var afterRequestSearchcode;
28 |
29 | genLangQuery(langs);
30 |
31 | this.resetPage = function () {
32 | page = 0;
33 | }
34 |
35 | this.setLang = function (val) {
36 | langs = val || null;
37 | genLangQuery(val);
38 | this.resetPage();
39 | Util.localStorage[langs ? 'set' : 'del'](persistLangsName, langs);
40 | }
41 |
42 | this.getLang = function () {
43 | return langs;
44 | }
45 |
46 | function genLangQuery(val) {
47 | if (!!val) {
48 | var arr1 = val.replace(/\s+/g, ',').split(','),
49 | arr2 = [];
50 | arr1.forEach(function (key) {
51 | arr2.push('lan=' + key);
52 | });
53 | langQuery = arr2.join('&');
54 | } else {
55 | langQuery = null;
56 | }
57 | }
58 |
59 | win.on('DB:ready', function (ev,db) {
60 | DB = db;
61 | Tables = {
62 | SourceCode: DB.getSchema().table('SourceCode')
63 | };
64 | _this.SourceCodeTable.getAll(function(rows){
65 | rows.forEach(function (key) {
66 | cacheSourceCodeHtmls[key.sid] = key.htm;
67 | });
68 | });
69 | });
70 |
71 | this.SourceCodeTable = new function () {
72 | this.add = function (sid, htm, callback) {
73 | if (!sid) {
74 | return;
75 | }
76 | var row = Tables.SourceCode.createRow({
77 | 'sid': sid,
78 | 'htm': htm,
79 | 'create': new Date()
80 | });
81 | DB.insertOrReplace().into(Tables.SourceCode).values([row])
82 | .exec().then(function () {
83 | callback && callback();
84 | win.trigger('DB:Table.SourceCode.onchange', {type: DBEventType.C});
85 | });
86 | }
87 |
88 | this.getAll = function (callback) {
89 | DB.select()
90 | .from(Tables.SourceCode)
91 | .orderBy(Tables.SourceCode.id, lf.Order.DESC)
92 | .exec().then(function (rows) {
93 | callback && callback(rows);
94 | });
95 | }
96 | };
97 |
98 | this.setCacheSourceCodeHtmlById = function(id,htm){
99 | cacheSourceCodeHtmls[id] = htm;
100 | _this.SourceCodeTable.add(id,htm);
101 | }
102 | this.getCacheSourceCodeHtmlById = function(id){
103 | return cacheSourceCodeHtmls[id];
104 | }
105 |
106 | //search code by query
107 | this.request = function (val, callback) {
108 | afterRequestSearchcode = callback;
109 | if (val != lastVal) {
110 | this.resetPage();
111 | }
112 | lastVal = val;
113 | lastVal && $.ajax({
114 | type: 'GET',
115 | dataType: 'jsonp',
116 | //dataType: 'json',
117 | //url: 'https://searchcode.com/api/codesearch_I/' + (langQuery ? ('?' + langQuery) : ''),
118 | url: 'https://searchcode.com/api/jsonp_codesearch_I/' + (langQuery ? ('?' + langQuery) : ''),
119 | data: {
120 | q: lastVal,
121 | p: page,
122 | per_page: 42,
123 | callback: 'afterRequestSearchcode'
124 | },
125 | jsonp: false,
126 | jsonpCallback: false,
127 | success: function (data) {
128 | callback && callback(data, page);
129 | page++;
130 | }
131 | })
132 | };
133 |
134 | window.afterRequestSearchcode = function(data){
135 | afterRequestSearchcode && afterRequestSearchcode(data, page);
136 | page++;
137 | }
138 |
139 | //get source code by id
140 | this.requestSourceCode = function (id, callback) {
141 | if (cacheSourceCodes[id]) {
142 | callback && callback(cacheSourceCodes[id]);
143 | return;
144 | }
145 | id && $.ajax({
146 | type: 'GET',
147 | dataType: 'json',
148 | url: 'https://searchcode.com/api/result/' + id + '/',
149 | success: function (data) {
150 | cacheSourceCodes[id] = data;
151 | callback && callback(data);
152 | }
153 | });
154 | }
155 | };
156 |
--------------------------------------------------------------------------------
/__static/app/src/model/YoudaoTranslateModel.js:
--------------------------------------------------------------------------------
1 | var Util = require('Util.js');
2 |
3 | module.exports = new function () {
4 | var lastVal;
5 | var translateRequestCallback;
6 | this.request = function (val, callback) {
7 | lastVal = val;
8 | translateRequestCallback = callback;
9 | lastVal && $.getJSON('//fanyi.youdao.com/openapi.do?callback=?&keyfrom=Codelf&key=2023743559&type=data&doctype=jsonp&version=1.1',
10 | {
11 | q: lastVal
12 | },
13 | function (data) {
14 | if (data) {
15 | translateRequestCallback && translateRequestCallback(data);
16 | }
17 | });
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/__static/app/sw.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 Google Inc. All Rights Reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 | http://www.apache.org/licenses/LICENSE-2.0
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
12 | */
13 |
14 | // While overkill for this specific sample in which there is only one cache,
15 | // this is one best practice that can be followed in general to keep track of
16 | // multiple caches used by a given service worker, and keep them all versioned.
17 | // It maps a shorthand identifier for a cache to a specific, versioned cache name.
18 |
19 | // Note that since global state is discarded in between service worker restarts, these
20 | // variables will be reinitialized each time the service worker handles an event, and you
21 | // should not attempt to change their values inside an event handler. (Treat them as constants.)
22 |
23 | // If at any point you want to force pages that use this service worker to start using a fresh
24 | // cache, then increment the CACHE_VERSION value. It will kick off the service worker update
25 | // flow and the old cache(s) will be purged as part of the activate event handler when the
26 | // updated service worker is activated.
27 | var CACHE_VERSION = _BUILD_VERSION_;
28 | var CURRENT_CACHES = {
29 | prefetch: 'prefetch-cache-v' + CACHE_VERSION
30 | };
31 |
32 | self.addEventListener('install', function(event) {
33 | var now = Date.now();
34 |
35 | var urlsToPrefetch = [_FILES_];
36 |
37 | // All of these logging statements should be visible via the "Inspect" interface
38 | // for the relevant SW accessed via chrome://serviceworker-internals
39 | console.log('Handling install event. Resources to prefetch:', urlsToPrefetch);
40 |
41 | event.waitUntil(
42 | caches.open(CURRENT_CACHES.prefetch).then(function(cache) {
43 | var cachePromises = urlsToPrefetch.map(function(urlToPrefetch) {
44 | // This constructs a new URL object using the service worker's script location as the base
45 | // for relative URLs.
46 | var url = new URL(urlToPrefetch, location.href);
47 | // Append a cache-bust=TIMESTAMP URL parameter to each URL's query string.
48 | // This is particularly important when precaching resources that are later used in the
49 | // fetch handler as responses directly, without consulting the network (i.e. cache-first).
50 | // If we were to get back a response from the HTTP browser cache for this precaching request
51 | // then that stale response would be used indefinitely, or at least until the next time
52 | // the service worker script changes triggering the install flow.
53 | url.search += (url.search ? '&' : '?') + 'cache-bust=' + now;
54 |
55 | // It's very important to use {mode: 'no-cors'} if there is any chance that
56 | // the resources being fetched are served off of a server that doesn't support
57 | // CORS (http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
58 | // In this example, www.chromium.org doesn't support CORS, and the fetch()
59 | // would fail if the default mode of 'cors' was used for the fetch() request.
60 | // The drawback of hardcoding {mode: 'no-cors'} is that the response from all
61 | // cross-origin hosts will always be opaque
62 | // (https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cross-origin-resources)
63 | // and it is not possible to determine whether an opaque response represents a success or failure
64 | // (https://github.com/whatwg/fetch/issues/14).
65 | var request = new Request(url, {mode: 'no-cors'});
66 | return fetch(request).then(function(response) {
67 | if (response.status >= 400) {
68 | throw new Error('request for ' + urlToPrefetch +
69 | ' failed with status ' + response.statusText);
70 | }
71 |
72 | // Use the original URL without the cache-busting parameter as the key for cache.put().
73 | return cache.put(urlToPrefetch, response);
74 | }).catch(function(error) {
75 | console.error('Not caching ' + urlToPrefetch + ' due to ' + error);
76 | });
77 | });
78 |
79 | return Promise.all(cachePromises).then(function() {
80 | console.log('Pre-fetching complete.');
81 | });
82 | }).catch(function(error) {
83 | console.error('Pre-fetching failed:', error);
84 | })
85 | );
86 | });
87 |
88 | self.addEventListener('activate', function(event) {
89 | // Delete all caches that aren't named in CURRENT_CACHES.
90 | // While there is only one cache in this example, the same logic will handle the case where
91 | // there are multiple versioned caches.
92 | var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) {
93 | return CURRENT_CACHES[key];
94 | });
95 |
96 | event.waitUntil(
97 | caches.keys().then(function(cacheNames) {
98 | return Promise.all(
99 | cacheNames.map(function(cacheName) {
100 | if (expectedCacheNames.indexOf(cacheName) === -1) {
101 | // If this cache name isn't present in the array of "expected" cache names, then delete it.
102 | console.log('Deleting out of date cache:', cacheName);
103 | return caches.delete(cacheName);
104 | }
105 | })
106 | );
107 | })
108 | );
109 | });
110 |
111 | self.addEventListener('fetch', function(event) {
112 | console.log('Handling fetch event for', event.request.url);
113 | var requestURL = new URL(event.request.url);
114 | requestURL.origin == location.origin && event.respondWith(
115 | // caches.match() will look for a cache entry in all of the caches available to the service worker.
116 | // It's an alternative to first opening a specific named cache and then matching on that.
117 | caches.match(event.request).then(function(response) {
118 | if (response) {
119 | console.log('Found response in cache:', response);
120 |
121 | return response;
122 | }
123 |
124 | console.log('No response found in cache. About to fetch from network...');
125 |
126 | // event.request will always have the proper mode set ('cors, 'no-cors', etc.) so we don't
127 | // have to hardcode 'no-cors' like we do when fetch()ing in the install handler.
128 | return fetch(event.request).then(function(response) {
129 | console.log('Response from network is:', response);
130 |
131 | return response;
132 | }).catch(function(error) {
133 | // This catch() will handle exceptions thrown from the fetch() operation.
134 | // Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
135 | // It will return a normal response object that has the appropriate error code set.
136 | console.error('Fetching failed:', error);
137 |
138 | throw error;
139 | });
140 | })
141 | );
142 | });
143 |
--------------------------------------------------------------------------------
/__static/images/codelf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/codelf_logo.png
--------------------------------------------------------------------------------
/__static/images/demo1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/demo1.jpg
--------------------------------------------------------------------------------
/__static/images/demo2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/demo2.jpg
--------------------------------------------------------------------------------
/__static/images/paypal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/paypal.png
--------------------------------------------------------------------------------
/__static/images/twohardtings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/twohardtings.png
--------------------------------------------------------------------------------
/__static/images/twohardtings2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/twohardtings2.png
--------------------------------------------------------------------------------
/__static/images/wechatpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/wechatpay.jpg
--------------------------------------------------------------------------------
/__static/images/zhifubao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/__static/images/zhifubao.png
--------------------------------------------------------------------------------
/app/ddms_frame_callback.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | CODELF
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/app/opensearch.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | CODELF
4 | Search CODELF
5 | UTF-8
6 | CODELF Search
7 | logo
8 |
9 |
10 |
--------------------------------------------------------------------------------
/assets/codelf_logo.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/codelf_logo.psd
--------------------------------------------------------------------------------
/assets/fonts/Dressedless_Three.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/Dressedless_Three.ttf
--------------------------------------------------------------------------------
/assets/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/assets/fonts/LatoLatin-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/LatoLatin-Bold.woff2
--------------------------------------------------------------------------------
/assets/fonts/LatoLatin-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/LatoLatin-BoldItalic.woff2
--------------------------------------------------------------------------------
/assets/fonts/LatoLatin-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/LatoLatin-Italic.woff2
--------------------------------------------------------------------------------
/assets/fonts/LatoLatin-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/LatoLatin-Regular.woff2
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/assets/images/codelf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/codelf_logo.png
--------------------------------------------------------------------------------
/assets/images/paypal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/paypal.png
--------------------------------------------------------------------------------
/assets/images/twohardtings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/twohardtings.jpg
--------------------------------------------------------------------------------
/assets/images/wechatdonate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/wechatdonate.jpg
--------------------------------------------------------------------------------
/assets/images/wechatpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/wechatpay.jpg
--------------------------------------------------------------------------------
/assets/images/zhifubao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/assets/images/zhifubao.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties",
8 | "@babel/plugin-proposal-optional-chaining"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/build-system/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const $ = require('./util');
5 | const webpack = require('webpack');
6 | const webpackConfig = require('../webpack.config.js');
7 | const env = process.env.NODE_ENV;
8 |
9 | // Builds the app scripts.
10 | gulp.task('build:app-js', () => {
11 | return new Promise(resolve => webpack(webpackConfig[env === 'production' ? 'prod' : 'dev'], (err, stats) => {
12 | if (err) throw new $.util.PluginError('webpack', err);
13 | let errorStats = stats.toString('errors-only');
14 | if (errorStats != '') $.util.log('[webpack]', errorStats);
15 | resolve();
16 | }));
17 | });
18 |
19 | // Builds the app style.
20 | gulp.task('build:app-css', cb => {
21 | gulp.src(['./styles/**/*.scss'], { buffer: true })
22 | .pipe($.sass({
23 | outputStyle: 'expanded',
24 | sourceMap: 'app.css.map',
25 | sourceMapContents: true,
26 | sourceMapEmbed: false,
27 | includePaths: ['./node_modules/']
28 | }).on('error', $.sass.logError))
29 | .pipe($.cached('sass-cache', {
30 | optimizeMemory: true
31 | }))
32 | .pipe($.autoprefixer())
33 | .pipe(gulp.dest('./app/css/'))
34 | .on('end', function () {
35 | cb();
36 | });
37 | });
38 |
39 | // Builds the lib scripts.
40 | gulp.task('build:lib-js', () => {
41 | return gulp.src(require('../lib.config').js)
42 | .pipe($.concat('lib.js'))
43 | .pipe(gulp.dest('./app/js/'));
44 | });
45 |
46 | // Builds the lib style.
47 | gulp.task('build:lib-css', () => {
48 | return gulp.src(require('../lib.config').css)
49 | .pipe($.concat('lib.css'))
50 | .pipe($.replace('@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin);', ''))
51 | .pipe(gulp.dest('./app/css/'));
52 | });
53 |
54 | // Builds the images.
55 | gulp.task('build:images', () => {
56 | return gulp.src('./assets/images/**/*.*')
57 | .pipe(gulp.dest('./app/images/'));
58 | });
59 |
60 | // Builds the fonts.
61 | gulp.task('build:fonts', () => {
62 | return gulp.src('./assets/fonts/**/*.*')
63 | .pipe(gulp.dest('./app/fonts/'));
64 | });
65 |
66 | // Builds extra files.
67 | gulp.task('build:extra', () => {
68 | return Promise.all(require('../lib.config').extra.map(key => {
69 | const dest = Object.keys(key);
70 | const path = key[dest];
71 | return gulp.src(path)
72 | .pipe(gulp.dest(`./app/${dest}`));
73 | }));
74 | });
75 |
76 | // Builds the app.
77 | gulp.task('build', gulp.parallel('build:extra', 'build:fonts', 'build:images', 'build:app-js', 'build:lib-css', 'build:app-css', 'build:lib-js'));
78 |
--------------------------------------------------------------------------------
/build-system/clean.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const del = require('del');
5 |
6 | // Cleans dist files.
7 | gulp.task('clean:dist', () => {
8 | return del(['./dist/**'], { force: true });
9 | });
10 |
11 | // Cleans files.
12 | gulp.task('clean', gulp.series('clean:dist'));
13 |
--------------------------------------------------------------------------------
/build-system/default.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const $ = require('./util');
5 |
6 | function watch(files, task) {
7 | const watcher = gulp.watch(files, task);
8 | ['add', 'addDir', 'change', 'unlink', 'unlinkDir'].forEach(type => {
9 | watcher.on(type, (path, stats) => {
10 | $.util.log($.util.colors.bold('File ' + path + ' was ' + type + ', running tasks...'));
11 | });
12 | });
13 | }
14 |
15 | // Watches for changes in files.
16 | gulp.task('watch', cb => {
17 | watch(['lib.config.js'], gulp.series('lint', 'build:extra', 'build:lib-js', 'build:lib-css'));
18 | watch(['styles/**/*.*'], gulp.series('lint', 'build:app-css'));
19 | cb();
20 | });
21 |
--------------------------------------------------------------------------------
/build-system/dist.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const $ = require('./util');
5 | const pngquant = require('imagemin-pngquant');
6 | const cachebust = $.cachebust();
7 | const through2 = require('through2');
8 |
9 | const distPath = './dist';
10 | const buildVersion = (new Date()).toISOString();
11 |
12 | // Copy all to dist.
13 | gulp.task('dist:all', () => {
14 | return gulp.src(['./app/**/**'])
15 | .pipe(gulp.dest(distPath))
16 | .pipe($.size({ title: 'dist:all' }));
17 | });
18 |
19 | // Compress images to dist.
20 | gulp.task('dist:images', () => {
21 | return gulp.src(['./app/images/**/*'])
22 | .pipe($.imagemin({
23 | use: [pngquant()]
24 | }))
25 | .pipe(cachebust.resources())
26 | .pipe(gulp.dest(distPath + '/images/'))
27 | .pipe($.size({ title: 'dist:images' }));
28 | });
29 |
30 | // Compress css to dist.
31 | gulp.task('dist:css', () => {
32 | return gulp.src('./app/css/**/*.css')
33 | .pipe(cachebust.references())
34 | .pipe($.csso({ comments: false }))
35 | .pipe(cachebust.resources())
36 | .pipe(gulp.dest(distPath + '/css'))
37 | .pipe($.size({ title: 'dist:css' }));
38 | });
39 |
40 | // Compress js to dist.
41 | gulp.task('dist:js', () => {
42 | return gulp.src(['./app/js/*.js'])
43 | .pipe(cachebust.references())
44 | .pipe($.minify())
45 | .pipe(cachebust.resources())
46 | .pipe(gulp.dest(distPath + '/js/'))
47 | .pipe($.size({ title: 'dist:js' }));
48 | });
49 |
50 | // Compress html to dist.
51 | gulp.task('dist:html', () => {
52 | return gulp.src(['./app/*.html'])
53 | .pipe(cachebust.references())
54 | .pipe($.htmlmin({ collapseWhitespace: true, minifyCSS: true, minifyJS: true }))
55 | .pipe(gulp.dest(distPath))
56 | .pipe($.size({ title: 'dist:html' }));
57 | });
58 |
59 | //generate service workers
60 | gulp.task('dist:serviceworkers', cb => {
61 | const swConfig = require('../lib.config').serviceWorker;
62 | const rootPath = __dirname.replace('build-system', '') + 'dist/';
63 | let resources = ['"./"'];
64 | gulp.src([distPath + '/**/*.*'])
65 | .pipe(through2.obj(function (file, enc, next) {
66 | !/sw\.js|\.html|\.map/.test(file.path) && this.push('"' + file.path.replace(rootPath, '') + '"');
67 | next();
68 | }))
69 | .on('data', data => {
70 | resources.push(data)
71 | })
72 | .on('end', function () {
73 | gulp.src(['./src/sw.js'])
74 | .pipe($.replace(/_BUILD_VERSION_/g, buildVersion))
75 | .pipe($.replace(/_FILES_/g, resources.join(',\n')))
76 | .pipe($.replace(/_INCLUDED_/g, swConfig.included.join(',\n')))
77 | .pipe($.replace(/_NETWORK_ONLY_/g, swConfig.networkOnly.join(',\n')))
78 | .pipe($.replace(/_CACHE_ONLY_/g, swConfig.cacheOnly.join(',\n')))
79 | .pipe($.replace(/_EXCLUDED_/g, swConfig.excluded.join(',\n')))
80 | .pipe($.minify())
81 | .pipe(gulp.dest(distPath))
82 | .on('end', cb);
83 | });
84 | });
85 |
86 | // Dist the app.
87 | gulp.task('dist', gulp.series('clean:dist', 'dist:all', 'dist:images', 'dist:css', 'dist:js', 'dist:html', 'dist:serviceworkers'));
88 |
--------------------------------------------------------------------------------
/build-system/lint.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const $ = require('./util');
5 |
6 | // Lint JS files.
7 | gulp.task('lint', () => {
8 | return gulp.src(['gulpfile.js', 'build-system/**/*.js', 'src/**/*.js*', '!src/vendors/**/**.*', '!src/sw.js'])
9 | .pipe($.eslint())
10 | .pipe($.eslint.format());
11 | });
12 |
--------------------------------------------------------------------------------
/build-system/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const browserSync = require('browser-sync').create();
5 | const $ = require('./util');
6 | const serveIndex = require('serve-index');
7 | const webpackDevMiddleware = require('webpack-dev-middleware');
8 | const webpackHotMiddleware = require('webpack-hot-middleware');
9 | const webpack = require('webpack');
10 | const webpackConfig = require('../webpack.config.js');
11 |
12 | // Starts a HTTP(s) server for debug.
13 | gulp.task('server', () => {
14 | return new Promise(resolve => {
15 | const compiler = webpack(webpackConfig.dev, () => {
16 | const config = {
17 | open: false,
18 | cors: true,
19 | reloadDelay: 1000,
20 | reloadDebounce: 3000,
21 | ghostMode: false,
22 | logPrefix: 'Debug Server',
23 | codeSync: $.util.argv['bs_code_sync'] != 'false',
24 | notify: false,
25 | server: {
26 | baseDir: ['./'],
27 | },
28 | https: $.util.argv['bs_https'] != 'false',
29 | serveStatic: ['./'],
30 | middleware: [
31 | serveIndex('.'),
32 | webpackDevMiddleware(compiler, {
33 | publicPath: webpackConfig.dev.output.publicPath,
34 | stats: { colors: true },
35 | writeToDisk: true,
36 | logTime: true,
37 | logLevel: 'error'
38 | }),
39 | webpackHotMiddleware(compiler)
40 | ]
41 | };
42 | if ($.util.argv['bs_proxy']) {
43 | config.server = false;
44 | config.proxy = $.util.argv['bs_proxy'];
45 | }
46 | // disable Browsersync scripts in browser
47 | if (!$.util.argv['bs_code_sync']) {
48 | config.scriptPath = () => '';
49 | } else {
50 | gulp.watch(['./app/**/*.*'], browserSync.reload);
51 | }
52 | browserSync.init(config, resolve);
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/build-system/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | let util = require('gulp-load-plugins')();
4 | const argv = require('minimist')(process.argv.slice(2));
5 | const log = require('fancy-log');
6 | const colors = require('ansi-colors');
7 | const PluginError = require('plugin-error');
8 | const replace = require('gulp-replace');
9 |
10 | util.util = {
11 | argv: argv,
12 | log: log,
13 | colors: colors,
14 | PluginError: PluginError,
15 | replace: replace
16 | };
17 |
18 | util.minify = function (options) {
19 | return util.babelMinify(
20 | Object.assign({
21 | evaluate: false,
22 | builtIns: false,
23 | simplifyComparisons: false
24 | }, options),
25 | {
26 | comments: false
27 | }
28 | );
29 | };
30 |
31 | module.exports = util;
32 |
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/brand-icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/brand-icons.eot
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/brand-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/brand-icons.ttf
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/brand-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/brand-icons.woff
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/brand-icons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/brand-icons.woff2
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/icons.eot
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/icons.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/icons.otf
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/icons.ttf
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/icons.woff
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/icons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/icons.woff2
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/outline-icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/outline-icons.eot
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/outline-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/outline-icons.ttf
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/outline-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/outline-icons.woff
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/fonts/outline-icons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/fonts/outline-icons.woff2
--------------------------------------------------------------------------------
/dist/css/themes/default/assets/images/flags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/css/themes/default/assets/images/flags.png
--------------------------------------------------------------------------------
/dist/ddms_frame_callback.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/fonts/Dressedless_Three.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/Dressedless_Three.ttf
--------------------------------------------------------------------------------
/dist/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/dist/fonts/LatoLatin-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/LatoLatin-Bold.woff2
--------------------------------------------------------------------------------
/dist/fonts/LatoLatin-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/LatoLatin-BoldItalic.woff2
--------------------------------------------------------------------------------
/dist/fonts/LatoLatin-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/LatoLatin-Italic.woff2
--------------------------------------------------------------------------------
/dist/fonts/LatoLatin-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/LatoLatin-Regular.woff2
--------------------------------------------------------------------------------
/dist/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/dist/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/dist/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/dist/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/dist/images/codelf_logo.f4ae25bd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/codelf_logo.f4ae25bd.png
--------------------------------------------------------------------------------
/dist/images/codelf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/codelf_logo.png
--------------------------------------------------------------------------------
/dist/images/paypal.69412e83.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/paypal.69412e83.png
--------------------------------------------------------------------------------
/dist/images/paypal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/paypal.png
--------------------------------------------------------------------------------
/dist/images/twohardtings.0db8462a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/twohardtings.0db8462a.jpg
--------------------------------------------------------------------------------
/dist/images/twohardtings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/twohardtings.jpg
--------------------------------------------------------------------------------
/dist/images/wechatdonate.3ba3a9d8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/wechatdonate.3ba3a9d8.jpg
--------------------------------------------------------------------------------
/dist/images/wechatdonate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/wechatdonate.jpg
--------------------------------------------------------------------------------
/dist/images/wechatpay.5f11f80c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/wechatpay.5f11f80c.jpg
--------------------------------------------------------------------------------
/dist/images/wechatpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/wechatpay.jpg
--------------------------------------------------------------------------------
/dist/images/zhifubao.70c19370.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/zhifubao.70c19370.png
--------------------------------------------------------------------------------
/dist/images/zhifubao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/dist/images/zhifubao.png
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 | CODELF
--------------------------------------------------------------------------------
/dist/opensearch.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | CODELF
4 | Search CODELF
5 | UTF-8
6 | CODELF Search
7 | logo
8 |
9 |
10 |
--------------------------------------------------------------------------------
/dist/sw.js:
--------------------------------------------------------------------------------
1 | function asyncGeneratorStep(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){return void c(a)}h.done?b(i):Promise.resolve(i).then(d,e)}function _asyncToGenerator(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){function f(a){asyncGeneratorStep(h,d,e,f,g,"next",a)}function g(a){asyncGeneratorStep(h,d,e,f,g,"throw",a)}var h=a.apply(b,c);f(void 0)})}}var CACHE_VERSION="2023-02-10T14:15:46.873Z",CURRENT_CACHES={prefetch:"prefetch-cache-v"+CACHE_VERSION},INCLUDED=["searchcode.com","fanyi.youdao.com","api.cognitive.microsofttranslator.com","api.github.com"],CACHE_ONLY=["fanyi.youdao.com","api.cognitive.microsofttranslator.com","api.github.com"],NETWORK_ONLY=[],EXCLUDED=[];function matchLocation(a,b){return b.find(function(b){return-1!==a.indexOf(b)})}self.addEventListener("install",function(a){self.skipWaiting();var b=Date.now(),c=["./","opensearch.xml","css/app.css","css/app.f1364fce.css","css/lib.b0f67b98.css","css/lib.css","fonts/Dressedless_Three.svg","fonts/Dressedless_Three.ttf","fonts/FontAwesome.otf","fonts/LatoLatin-Bold.woff2","fonts/LatoLatin-BoldItalic.woff2","fonts/LatoLatin-Italic.woff2","fonts/LatoLatin-Regular.woff2","fonts/fontawesome-webfont.eot","fonts/fontawesome-webfont.svg","fonts/fontawesome-webfont.ttf","fonts/fontawesome-webfont.woff","fonts/fontawesome-webfont.woff2","images/codelf_logo.f4ae25bd.png","images/codelf_logo.png","images/paypal.69412e83.png","images/paypal.png","images/twohardtings.0db8462a.jpg","images/twohardtings.jpg","images/wechatdonate.3ba3a9d8.jpg","images/wechatdonate.jpg","images/wechatpay.5f11f80c.jpg","images/wechatpay.jpg","images/zhifubao.70c19370.png","images/zhifubao.png","js/app.792fa086.js","js/app.js","js/lib.5e430a5b.js","js/lib.js","css/themes/default/assets/fonts/brand-icons.eot","css/themes/default/assets/fonts/brand-icons.svg","css/themes/default/assets/fonts/brand-icons.ttf","css/themes/default/assets/fonts/brand-icons.woff","css/themes/default/assets/fonts/brand-icons.woff2","css/themes/default/assets/fonts/icons.eot","css/themes/default/assets/fonts/icons.otf","css/themes/default/assets/fonts/icons.svg","css/themes/default/assets/fonts/icons.ttf","css/themes/default/assets/fonts/icons.woff","css/themes/default/assets/fonts/icons.woff2","css/themes/default/assets/fonts/outline-icons.eot","css/themes/default/assets/fonts/outline-icons.svg","css/themes/default/assets/fonts/outline-icons.ttf","css/themes/default/assets/fonts/outline-icons.woff","css/themes/default/assets/fonts/outline-icons.woff2","css/themes/default/assets/images/flags.png"];console.log("Handling install event. Resources to prefetch:",c),a.waitUntil(caches.open(CURRENT_CACHES.prefetch).then(function(a){var d=c.map(function(c){var d=new URL(c,location.href);d.search+=(d.search?"&":"?")+"cache-bust="+b;var e=new Request(d,{mode:"no-cors"});return fetch(e).then(function(b){if(400<=b.status)throw new Error("request for "+c+" failed with status "+b.statusText);return a.put(c,b)})["catch"](function(a){console.error("Not caching "+c+" due to "+a)})});return Promise.all(d).then(function(){console.log("Pre-fetching complete.")})})["catch"](function(a){console.error("Pre-fetching failed:",a)}))}),self.addEventListener("activate",function(a){var b=Object.keys(CURRENT_CACHES).map(function(a){return CURRENT_CACHES[a]});a.waitUntil(caches.keys().then(function(a){return Promise.all(a.map(function(a){if(-1===b.indexOf(a))return console.log("Deleting out of date cache:",a),caches["delete"](a)}))}))}),self.addEventListener("fetch",function(a){console.log("Handling fetch event for",a.request.url);var b=new URL(a.request.url);"navigate"===a.request.mode?(console.log("request mode:",a.request.mode),a.respondWith(_asyncToGenerator(regeneratorRuntime.mark(function c(){var d,e,f;return regeneratorRuntime.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:return d=b,d.search="",e=fetch(d),f=e.then(function(a){return a.clone()}),a.waitUntil(_asyncToGenerator(regeneratorRuntime.mark(function a(){var b;return regeneratorRuntime.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return a.next=2,caches.open(CURRENT_CACHES.prefetch);case 2:return b=a.sent,a.t0=b,a.t1=d,a.next=7,f;case 7:return a.t2=a.sent,a.next=10,a.t0.put.call(a.t0,a.t1,a.t2);case 10:case"end":return a.stop();}},a)}))()),c.next=7,caches.match(d);case 7:if(c.t0=c.sent,c.t0){c.next=10;break}c.t0=e;case 10:return c.abrupt("return",c.t0);case 11:case"end":return c.stop();}},c)}))())):matchLocation(b.href,INCLUDED)&&!matchLocation(b.href,EXCLUDED)&&/get/i.test(a.request.method)?matchLocation(b.href,NETWORK_ONLY)?(console.log("network-falling-back-to-caches:",a.request.url),a.respondWith(caches.open(CURRENT_CACHES.prefetch).then(function(b){return fetch(a.request).then(function(c){return b.put(a.request,c.clone()),c})["catch"](function(){return b.match(a.request).then(function(a){return a})})}))):matchLocation(b.href,CACHE_ONLY)?(console.log("cache-falling-back-to-network:",a.request.url),a.respondWith(caches.open(CURRENT_CACHES.prefetch).then(function(b){return b.match(a.request).then(function(c){return c||fetch(a.request).then(function(c){return b.put(a.request,c.clone()),c})})}))):(console.log("cache-then-network:",a.request.url),a.respondWith(caches.open(CURRENT_CACHES.prefetch).then(function(b){return b.match(a.request).then(function(c){var d=fetch(a.request).then(function(c){return b.put(a.request,c.clone()),c});return c||d})}))):b.origin==location.origin&&(console.log("request origin:",b.origin),a.respondWith(caches.match(a.request).then(function(b){return b?(console.log("Found response in cache:",b),b):(console.log("No response found in cache. About to fetch from network..."),fetch(a.request).then(function(a){return console.log("Response from network is:",a),a})["catch"](function(a){throw console.error("Fetching failed:",a),a}))})))}),"storage"in navigator&&"estimate"in navigator.storage&&navigator.storage.estimate().then(function(a){console.log("Using ".concat(a.usage," out of ").concat(a.quota," bytes."))});
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const $ = require('./build-system/util');
5 | const requireDir = require('require-dir');
6 | requireDir('./build-system');
7 |
8 | gulp.task('help', cb => {
9 | $.util.log(
10 | `
11 | Usage
12 | gulp [TASK] [OPTIONS...]
13 |
14 | Available tasks
15 | build Builds the app.
16 | build:app-css Builds the app style.
17 | build:app-js Builds the app scripts.
18 | build:extra Builds extra files.
19 | build:images Builds the app style.
20 | build:lib-css Builds the lib style.
21 | build:lib-js Builds the lib scripts.
22 | clean Cleans files.
23 | clean:dist Cleans dist files.
24 | default
25 | dist Dist the app.
26 | dist:all Copy all to dist.
27 | dist:css Compress css to dist.
28 | dist:html Compress html to dist.
29 | dist:images Compress images to dist.
30 | dist:js Compress js to dist.
31 | help Display this help text.
32 | lint Lint JS files.
33 | server Starts a HTTP(s) server for debug.
34 | watch Watches for changes in files.
35 | `
36 | );
37 | cb();
38 | });
39 |
40 | // Run tasks: lint, build, docs, watch, server
41 | gulp.task('default', cb => {
42 | $.util.log(
43 | $.util.colors.green('Building and watching for changes ...')
44 | );
45 | gulp.series(
46 | 'lint',
47 | 'build:extra', 'build:images', 'build:app-css', 'build:lib-js', 'build:lib-css', 'watch', 'server', () => {
48 | $.util.log(
49 | $.util.colors.green('Ready! Run "gulp help" for more build command usages.'), '\n'
50 | );
51 | })(cb);
52 | });
53 |
--------------------------------------------------------------------------------
/lib.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | exports.js = [
4 | './node_modules/react/umd/react.production.min.js',
5 | './node_modules/react-dom/umd/react-dom.production.min.js',
6 | './node_modules/clipboard/dist/clipboard.min.js',
7 | './src/vendors/prettify.js',
8 | './node_modules/mark.js/dist/mark.min.js'
9 | ];
10 |
11 | exports.css = [
12 | './node_modules/semantic-ui-css/semantic.min.css',
13 | './node_modules/animate.css/animate.min.css',
14 | './src/vendors/prettify.css'
15 | ];
16 |
17 | exports.extra = [{
18 | 'css/themes': './node_modules/semantic-ui-css/themes/**'
19 | }];
20 |
21 | // configs for service worker, get request only, not in "included" url won't be cached
22 | exports.serviceWorker = {
23 | included: [ // cache then network, url must start with it's host
24 | '"searchcode.com"',
25 | '"fanyi.youdao.com"',
26 | '"api.cognitive.microsofttranslator.com"',
27 | '"api.github.com"'
28 | ],
29 | networkOnly: [ // network falling back to cache, url|path|etc must included in "included"
30 | ],
31 | cacheOnly: [ // cache fallback to network, url|path|etc must included in "included"
32 | '"fanyi.youdao.com"',
33 | '"api.cognitive.microsofttranslator.com"',
34 | '"api.github.com"'
35 | ],
36 | excluded: [ // won't be cache, url|path|etc must included in "included"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Codelf",
3 | "version": "8.1.0",
4 | "description": "A search tool helps dev to solve the naming things problem.",
5 | "keywords": [
6 | "Codelf",
7 | "real-world usage variable names",
8 | "searchcode"
9 | ],
10 | "author": "unbug",
11 | "license": "snts",
12 | "scripts": {
13 | "test": "echo \"Error: no test specified\" && exit 1",
14 | "start": "gulp",
15 | "build": "NODE_ENV=production gulp build",
16 | "dist": "NODE_ENV=production gulp build && gulp dist",
17 | "gh-pages": "npm run dist && sleep 3 && git add dist/ && git commit -m \"build dist\" && git push origin `git subtree split --prefix dist HEAD`:gh-pages --force"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.7.4",
21 | "@babel/plugin-proposal-class-properties": "^7.7.4",
22 | "@babel/plugin-proposal-optional-chaining": "^7.7.4",
23 | "@babel/preset-env": "^7.7.4",
24 | "@babel/preset-react": "^7.7.4",
25 | "ansi-colors": "^4.1.1",
26 | "babel-eslint": "^10.0.3",
27 | "babel-loader": "^8.0.6",
28 | "browser-sync": "^2.26.7",
29 | "css-loader": "^3.2.1",
30 | "cssnano": "^4.1.10",
31 | "del": "^5.1.0",
32 | "eslint": "^6.7.2",
33 | "eslint-plugin-react": "^7.17.0",
34 | "eslint-plugin-react-hooks": "^2.3.0",
35 | "fancy-log": "^1.3.3",
36 | "gulp": "^4.0.2",
37 | "gulp-autoprefixer": "^7.0.1",
38 | "gulp-babel-minify": "^0.5.1",
39 | "gulp-cachebust": "0.0.10",
40 | "gulp-cached": "^1.1.1",
41 | "gulp-concat": "^2.6.1",
42 | "gulp-csso": "^3.0.1",
43 | "gulp-eslint": "^6.0.0",
44 | "gulp-htmlmin": "^5.0.1",
45 | "gulp-if": "^3.0.0",
46 | "gulp-imagemin": "^6.2.0",
47 | "gulp-load-plugins": "^2.0.1",
48 | "gulp-replace": "^1.0.0",
49 | "gulp-sass": "^4.0.2",
50 | "gulp-sass-lint": "^1.4.0",
51 | "gulp-size": "^3.0.0",
52 | "gulp-watch": "^5.0.1",
53 | "imagemin-pngquant": "^8.0.0",
54 | "minimist": "^1.2.0",
55 | "node-sass": "^4.13.0",
56 | "plugin-error": "^1.0.1",
57 | "require-dir": "^1.2.0",
58 | "sass-loader": "^8.0.0",
59 | "serve-index": "^1.9.1",
60 | "through2": "^3.0.0",
61 | "webpack": "^4.41.2",
62 | "webpack-cli": "^3.3.10",
63 | "webpack-dev-server": "^3.9.0",
64 | "webpack-hot-middleware": "^2.25.0",
65 | "webpack-merge": "^4.2.2"
66 | },
67 | "dependencies": {
68 | "@babel/polyfill": "^7.7.0",
69 | "animate.css": "^3.7.2",
70 | "clipboard": "^2.0.4",
71 | "code-prettify": "^0.1.0",
72 | "css-doodle": "^0.7.6",
73 | "events": "^3.0.0",
74 | "file-saver": "^2.0.2",
75 | "lodash": "^4.17.15",
76 | "mark.js": "^8.11.1",
77 | "nprogress": "^0.2.0",
78 | "react": "^16.12.0",
79 | "react-dom": "^16.12.0",
80 | "react-router-dom": "^5.1.2",
81 | "semantic-ui-css": "^2.4.1",
82 | "semantic-ui-react": "^0.88.1",
83 | "spark-md5": "^3.0.0",
84 | "whatwg-fetch": "^3.0.0"
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import 'whatwg-fetch';
2 | import ReactDOM from 'react-dom';
3 | import MainContainer from './containers/MainContainer';
4 | // import CopybookContainer from './containers/CopybookContainer';
5 | import NoticeContainer from './containers/NoticeContainer';
6 | import NavBarContainer from './containers/NavBarContainer';
7 |
8 | function App() {
9 | return (
10 | <>
11 |
12 |
13 | {/* */}
14 |
15 | >
16 | );
17 | }
18 |
19 | ReactDOM.render(, document.querySelector('.app'));
20 |
--------------------------------------------------------------------------------
/src/components/Bookmark.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unbug/codelf/0bfb88a8d297ca0f65abbf8f83f7826311df42a3/src/components/Bookmark.js
--------------------------------------------------------------------------------
/src/components/Copybook.js:
--------------------------------------------------------------------------------
1 | import React, { useRef } from 'react';
2 | import { Button, Dropdown, Modal } from 'semantic-ui-react';
3 | import Loading from "./Loading";
4 | import useCodeHighlighting from './hooks/useCodeHighlighting';
5 |
6 | export default function Copybook(props) {
7 | const codeEl = useCodeHighlighting([props.copybookFileContent, props.copybookVisible]);
8 | const editorEl = useRef(null);
9 |
10 | function handleClose() {
11 | props.onCloseCopybook();
12 | }
13 |
14 | function handleDropdownChange(e, { searchQuery, value }) {
15 | if (value != props.copybookSelectedFile.path) {
16 | props.onRequestCopybookFile(
17 | props.copybookFileList.find(f => f.path === value)
18 | );
19 | }
20 | }
21 |
22 | function renderDropdownItem() {
23 | if (!props.copybookFileList) {
24 | return null;
25 | }
26 | return props.copybookFileList.map((file, idx) => {
27 | return {
28 | key: file.path,
29 | value: file.path,
30 | text: (idx + 1) + '. ' + file.path
31 | }
32 | });
33 | }
34 |
35 | if (!props.copybookVisible || !props.copybookFileList || !props.copybookFileContent) {
36 | return (
37 |
39 |
40 | Daily Algorithm Copybook
41 |
42 |
43 |
44 |
45 |
46 |
47 | );
48 | }
49 |
50 | return (
51 |
53 |
54 | Daily Algorithm Copybook
55 |
58 |
64 |
65 |
66 | {props.copybookRequesting ? : ''}
67 |
68 | {props.copybookFileContent.content}
69 |
70 |
71 |
72 |
73 | )
74 | }
75 |
--------------------------------------------------------------------------------
/src/components/Donate.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import * as Tools from '../utils/Tools';
3 |
4 | const cnText = Tools.randomList([
5 | '颈椎病晚期',
6 | '买不起奶粉',
7 | '快交不起房租',
8 | '全年996',
9 | '有可能会猝死',
10 | '快要失业',
11 | '头发越来越少',
12 | '还没从 ICU 出来',
13 | '天天写需求',
14 | '又被降薪',
15 | '昨晚熬夜修 BUG '
16 | ], 1)[0];
17 | export default function Donate(props) {
18 | let text = ;
19 | if (props.isZH) {
20 | text = ;
21 | }
22 | return (
23 |
24 |
{text}
25 |
26 |

27 |

28 |
34 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/src/components/Doodle.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'css-doodle';
3 |
4 | export default function Doodle(props) {
5 | const { text } = props;
6 | let doodle = null;
7 | if (/鱼|fish/i.test(text)) {
8 | doodle = 'fish';
9 | } else if (/糖|甜|candy|圣诞|Christmas|xmas|春节/i.test(text)) {
10 | doodle = 'candy'
11 | }
12 |
13 | if (!doodle) { return null; }
14 |
15 | return (
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default function Loading() {
4 | return (
5 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/SearchBar.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useRef, useState } from 'react';
2 | import { Dropdown, Icon, Input } from 'semantic-ui-react';
3 |
4 | // http://githut.info/
5 | const topProgramLan = [
6 | { id: '22,106', language: 'JavaScript, CoffeeScript' },
7 | { id: '133,135', language: 'CSS' },
8 | { id: '3,39', language: 'HTML' },
9 | { id: 137, language: 'Swift' },
10 | { id: 35, language: 'Objective-C' },
11 | { id: 23, language: 'Java' },
12 | { id: 19, language: 'Python' },
13 | { id: 24, language: 'PHP' },
14 | { id: 32, language: 'Ruby' },
15 | { id: 28, language: 'C' },
16 | { id: 16, language: 'C++' },
17 | { id: 6, language: 'C#' },
18 | { id: 55, language: 'Go' },
19 | { id: 51, language: 'Perl' },
20 | { id: '104,109', language: 'Clojure, ClojureScript' },
21 | { id: 40, language: 'Haskell' },
22 | { id: 54, language: 'Lua' },
23 | { id: 20, language: 'Matlab' },
24 | { id: 144, language: 'R' },
25 | { id: 47, language: 'Scala' },
26 | { id: '69,78,146', language: 'Shell' },
27 | { id: 29, language: 'Lisp' },
28 | { id: 42, language: 'ActionScript' }
29 | ];
30 |
31 | export default function SearchBar(props) {
32 | const inputEl = useRef(null);
33 | const inputSize = useInputSize('huge');
34 | const [state, setState] = useState({
35 | lang: props.searchLang || [],
36 | valChanged: false
37 | });
38 |
39 | function updateState(vals) {
40 | setState(prevState => {
41 | return { ...prevState, ...vals };
42 | });
43 | }
44 |
45 | function handleSearch() {
46 | props.onSearch(inputEl.current.inputRef.current.value, state.lang);
47 | inputEl.current.inputRef.current.blur();
48 | updateState({ valChanged: false });
49 | }
50 |
51 | function handleRestLang() {
52 | updateState({ lang: [], valChanged: true });
53 | }
54 |
55 | function handleSelectLang(id) {
56 | updateState({ lang: state.lang.concat(id).sort(), valChanged: true });
57 | }
58 |
59 | function handleDeselectLang(id) {
60 | let lang = state.lang;
61 | lang.splice(state.lang.indexOf(id), 1);
62 | updateState({ lang: lang.sort(), valChanged: true });
63 | }
64 |
65 | function handleToggleSelectLang(id) {
66 | state.lang.indexOf(id) === -1 ? handleSelectLang(id) : handleDeselectLang(id);
67 | }
68 |
69 | const langItems = topProgramLan.map(key => {
70 | const active = state.lang.indexOf(key.id) !== -1;
71 | return handleToggleSelectLang(key.id)}>
74 | {key.language}
75 | ;
76 | });
77 |
78 | return (
79 |
80 |
81 | Search over GitHub, Bitbucket, GitLab to find real-world usage variable names
82 |
83 |
108 |
121 |
122 | )
123 | }
124 |
125 | function useInputSize(val) {
126 | const [size, setSize] = useState(val);
127 |
128 | useEffect(() => {
129 | resizeInput();
130 | window.addEventListener('resize', resizeInput, false);
131 | return () => window.removeEventListener('resize', resizeInput, false);
132 | }, []);// run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([])
133 |
134 | function resizeInput() {
135 | setSize(document.body.offsetWidth < 800 ? '' : val);
136 | }
137 |
138 | return size;
139 | }
140 |
--------------------------------------------------------------------------------
/src/components/SearchError.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Label } from 'semantic-ui-react';
3 |
4 | export default function SearchError() {
5 | return (
6 |
7 |
Nothing found, please try or come back later :)
8 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/SourceCode.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Modal, Button, Dropdown, Label } from 'semantic-ui-react';
3 | import * as Tools from '../utils/Tools';
4 | import Loading from "./Loading";
5 | import useCodeHighlighting from './hooks/useCodeHighlighting';
6 |
7 | export default function SourceCode(props) {
8 | const codeEl = useCodeHighlighting([props.sourceCode, props.sourceCodeVisible], props.sourceCodeVariable ?.keyword);
9 |
10 | function handleClose() {
11 | props.onCloseSourceCode();
12 | }
13 |
14 | if (!props.sourceCodeVariable || !props.sourceCodeRepo) { return null; }
15 | const sourceCodeVariable = props.sourceCodeVariable;
16 | const dropText = (
17 | All Codes
20 | );
21 | const dropdownItems = props.sourceCodeVariable && props.sourceCodeVariable.repoList.map(repo => {
22 | return (
23 |
24 |
25 |
26 |
27 |
28 | )
29 | });
30 | return (
31 |
33 |
34 |
36 |
37 |
38 | {dropdownItems}
39 |
40 |
41 |
42 |
43 |
44 |
45 | {props.sourceCodeRequesting ? : ''}
46 | {props.sourceCode}
47 |
48 |
49 | )
50 | }
51 |
--------------------------------------------------------------------------------
/src/components/Suggestion.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Label } from 'semantic-ui-react';
3 |
4 | export default function Suggestion(props) {
5 | if (!props.suggestion || !props.suggestion.length) { return null; }
6 | const list = props.suggestion.map((item, i) => {
7 | return
8 | });
9 | return (
10 |
11 | {list}
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/TitleLogo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default function TitleLogo() {
4 | return (
5 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/VariableItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button, Label, Popup } from 'semantic-ui-react';
3 | import * as Tools from '../utils/Tools';
4 |
5 | export default function VariableItem(props) {
6 | const clipboardId = `clipboardId-${Tools.uuid()}`;
7 | const variable = props.variable;
8 | let clipboard = null;
9 |
10 | function handlePopOnMount() {
11 | clipboard = new ClipboardJS(`#${clipboardId}`);
12 | }
13 |
14 | function handlePopUnmount() {
15 | clipboard && clipboard.destroy();
16 | }
17 |
18 | return (
19 |
23 | {variable.keyword}
24 | }
25 | onMount={handlePopOnMount}
26 | onUnmount={handlePopUnmount}
27 | hoverable={true}>
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/VariableList.js:
--------------------------------------------------------------------------------
1 | import React, { useMemo, useRef } from 'react';
2 | import * as Tools from '../utils/Tools';
3 | import VariableItem from './VariableItem';
4 |
5 | const notFound = val => val && /59ce9297fba93aeb9d693a2f61922fb6|bfd876277827a33f49d363e8857977a0/g.test(Tools.MD5(val));
6 | const notFoundImg = '//user-images.githubusercontent.com/799578/50722775-1a9a1d00-110f-11e9-9bcc-efe5465a4ad5.jpg';
7 | const animationName = Math.random() > 0.5 ? 'zoomInDown' : 'zoomInUp';
8 |
9 | export default function VariableList(props) {
10 | const lastPageLen = useRef();
11 | const list = useMemo(() => { // same as "shouldComponentUpdate", only compute when "variableList" has changed
12 | const variableList = props.variableList;
13 | const pageLen = variableList.length;
14 | let pages = [];
15 | if (notFound(props.searchValue)) {
16 | pages.push(
);
17 | }
18 | variableList.forEach((list, i) => {
19 | const isLast = i === pageLen - 1 && lastPageLen.current != pageLen;
20 | const variables = list.map((variable, j) => {
21 | let style = {}, className = '', duration = (list.length - j) / list.length;
22 | if (isLast) {
23 | className = 'animated';
24 | style = {
25 | animationName: animationName,
26 | animationDelay: duration + 's',
27 | animationDuration: Math.min(duration, 0.8) + Math.random() + 's'
28 | };
29 | }
30 | return
32 | });
33 | if (variables && variables.length) {
34 | if (pages.length) {
35 | pages.unshift(
);
36 | }
37 | Array.prototype.unshift.apply(pages, variables)
38 | }
39 | });
40 | lastPageLen.current = pageLen;
41 | return pages;
42 | }, [props.variableList]);
43 |
44 | return {list}
;
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/hooks/useCodeHighlighting.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | export default function useCodeHighlighting(watchedProps, keyword) {
4 | const container = useRef(null);
5 | const mark = useRef(null);
6 | useEffect(() => {
7 | renderPrettyPrint();
8 | }, [...watchedProps]);
9 |
10 | function renderPrettyPrint() {
11 | setTimeout(() => {
12 | if (container.current) {
13 | container.current.classList.remove('prettyprinted');
14 | setTimeout(() => PR.prettyPrint(
15 | () => setTimeout(() => renderHighLight(), 1000)
16 | ), 100);
17 | }
18 | }, container.current ? 0 : 1000);
19 | }
20 |
21 | function renderHighLight() {
22 | if (!keyword) {
23 | return;
24 | }
25 | if (mark.current) {
26 | mark.current.unmark()
27 | }
28 | mark.current = new Mark(container.current);
29 | let idx = 0;
30 | mark.current.mark(keyword, {
31 | each: el => {
32 | el.setAttribute('tabindex', idx++);
33 | }
34 | });
35 | }
36 |
37 | return container;
38 | }
39 |
--------------------------------------------------------------------------------
/src/constants/Configs.js:
--------------------------------------------------------------------------------
1 | import * as Tools from '../utils/Tools';
2 |
3 | const APP_NANE = 'codelf';
4 | const PAGE_URL = Tools.thisPage;
5 | const PAGE_PATH = Tools.thisPath;
6 |
7 | export { APP_NANE, PAGE_PATH, PAGE_URL }
8 |
--------------------------------------------------------------------------------
/src/containers/CopybookContainer.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useReducer } from 'react';
2 | import AppModel from '../models/AppModel';
3 | import CopybookModel from '../models/CopybookModel';
4 | import Copybook from '../components/Copybook';
5 |
6 | const actionTypes = {
7 | UPDATE: 'update',
8 | };
9 |
10 | const initState = {
11 | copybookRequesting: false,
12 | copybookVisible: CopybookModel.visible,
13 | copybookFileList: CopybookModel.fileList,
14 | copybookSelectedFile: CopybookModel.selectedFile,
15 | copybookFileContent: CopybookModel.fileContent,
16 | };
17 |
18 | function reducer(state, action) {
19 | switch (action.type) {
20 | case actionTypes.UPDATE:
21 | return {
22 | ...state,
23 | ...action.payload
24 | };
25 | default:
26 | return state;
27 | }
28 | }
29 |
30 | export default function CopybookContainer(props) {
31 | const [state, dispatch] = useReducer(reducer, initState);
32 |
33 | useEffect(() => {
34 | CopybookModel.onUpdated(handleCopybookModelUpdate);
35 | return () => CopybookModel.offUpdated(handleCopybookModelUpdate);
36 | });
37 |
38 | function setState(payload) {
39 | dispatch({ type: actionTypes.UPDATE, payload: payload });
40 | }
41 |
42 | function handleCopybookModelUpdate(curr, prev, mutation) {
43 | if (mutation.fileList) {
44 | setState({
45 | copybookFileList: CopybookModel.fileList
46 | });
47 | }
48 | if (mutation.fileContent) {
49 | setState({
50 | copybookRequesting: false,
51 | copybookSelectedFile: CopybookModel.selectedFile,
52 | copybookFileContent: CopybookModel.fileContent,
53 | });
54 | }
55 | if (mutation.visible) {
56 | setState({
57 | copybookVisible: CopybookModel.visible,
58 | });
59 | if (CopybookModel.visible) {
60 | AppModel.analytics('copybook&q=read');
61 | }
62 | }
63 | }
64 |
65 | function handleCloseCopybook() {
66 | CopybookModel.update({ visible: false });
67 | }
68 |
69 | function handleRequestCopybookFile(file) {
70 | setState({ copybookRequesting: true });
71 | CopybookModel.requestRepoFile(file);
72 | AppModel.analytics('copybook&q=read');
73 | }
74 |
75 | return ;
79 | }
80 |
--------------------------------------------------------------------------------
/src/containers/MainContainer.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useReducer, useCallback } from 'react';
2 | import { Container } from 'semantic-ui-react';
3 | import SearchBar from '../components/SearchBar';
4 | import TitleLogo from '../components/TitleLogo';
5 | import SearchCodeModel from '../models/SearchCodeModel';
6 | import HashHandler from '../utils/HashHandler';
7 | import VariableList from '../components/VariableList';
8 | import SearchError from '../components/SearchError';
9 | import Loading from '../components/Loading';
10 | import Donate from '../components/Donate';
11 | import Suggestion from '../components/Suggestion';
12 | import SourceCode from '../components/SourceCode';
13 | import AppModel from '../models/AppModel';
14 | import DDMSModel from '../models/DDMSModel';
15 | import Doodle from '../components/Doodle';
16 |
17 | const actionTypes = {
18 | UPDATE: 'update',
19 | };
20 |
21 | const initState = {
22 | isZH: false,
23 | isError: false,
24 | variableRequesting: false,
25 | searchValue: SearchCodeModel.searchValue,
26 | searchLang: SearchCodeModel.searchLang,
27 | page: SearchCodeModel.page,
28 | variableList: SearchCodeModel.variableList,
29 | suggestion: SearchCodeModel.suggestion,
30 | luckyKeyWords: DDMSModel.luckyKeyWords,
31 | sourceCodeRequesting: false,
32 | sourceCodeVisible: false,
33 | sourceCodeVariable: null,
34 | sourceCodeRepo: null,
35 | };
36 |
37 | function reducer(state, action) {
38 | switch (action.type) {
39 | case actionTypes.UPDATE:
40 | return {
41 | ...state,
42 | ...action.payload
43 | };
44 | default:
45 | return state;
46 | }
47 | }
48 |
49 |
50 | export default function MainContainer(props) {
51 | const [state, dispatch] = useReducer(reducer, initState);
52 |
53 | useEffect(() => {
54 | AppModel.analytics();
55 | setTimeout(handleLocationHashChanged, 100);
56 | window.addEventListener('hashchange', handleLocationHashChanged, false);
57 | return () => window.removeEventListener('hashchange', handleLocationHashChanged);
58 | }, []);
59 |
60 | useEffect(() => {
61 | state.variableList.length && document.body.classList.add('dark');
62 | }, [state.variableList]);
63 |
64 | useEffect(() => {
65 | SearchCodeModel.onUpdated(handleSearchCodeModelUpdate);
66 | return () => SearchCodeModel.offUpdated(handleSearchCodeModelUpdate);
67 | });
68 |
69 | useEffect(() => {
70 | function handleDDMSModelUpdate(curr, prev, mutation) {
71 | if (mutation.luckyKeyWords) {
72 | setState({ luckyKeyWords: curr.luckyKeyWords });
73 | }
74 | }
75 | DDMSModel.onUpdated(handleDDMSModelUpdate);
76 | return () => DDMSModel.offUpdated(handleDDMSModelUpdate);
77 | }, []);
78 |
79 | const handleSearch = useCallback((val, lang) => {
80 | if (val === null || val === undefined || state.variableRequesting) {
81 | return;
82 | }
83 | val = val.trim().replace(/\s+/ig, ' '); // filter spaces
84 | if (val.length < 1) {
85 | return;
86 | }
87 | if (val == state.searchValue) {
88 | requestVariable(val, lang);
89 | } else {
90 | setState({ searchLang: lang });
91 | setTimeout(() => HashHandler.set(val)); // update window.location.hash
92 | }
93 | }, [state.searchValue, state.variableRequesting]);
94 |
95 | const handleOpenSourceCode = useCallback((variable) => {
96 | setState({ sourceCodeVariable: variable });
97 | setTimeout(() => requestSourceCode(variable.repoList[0]), 0);
98 | }, []);
99 |
100 | function handleCloseSourceCode() {
101 | setState({ sourceCodeVisible: false });
102 | }
103 |
104 | function handleRequestSourceCode(repo) {
105 | requestSourceCode(repo);
106 | }
107 |
108 | function renderSloganImage() {
109 | if (state.page > 0 || state.variableList.length) {
110 | return '';
111 | }
112 | return ;
113 | }
114 |
115 | function renderDoodle() {
116 | if (state.variableList.length == 0) { return null; }
117 | return
118 | }
119 |
120 | function setState(payload) {
121 | dispatch({ type: actionTypes.UPDATE, payload: payload });
122 | }
123 |
124 | function checkError(data) {
125 | if (state.variableRequesting) {
126 | // no search result
127 | if (data.variableList.length < 1 || data.variableList[data.variableList.length - 1].length < 1) {
128 | return true;
129 | }
130 | }
131 | return false;
132 | }
133 |
134 | function requestVariable(val, lang) {
135 | const langChanged = lang ? (lang.join(',') != state.searchLang.join(',')) : !!state.searchLang;
136 | val = decodeURIComponent(val);
137 | let page = state.page;
138 | if (val == state.searchValue && !langChanged) {
139 | page += 1;
140 | } else {
141 | page = 0;
142 | }
143 | setState({ searchValue: val, variableRequesting: true });
144 | SearchCodeModel.requestVariable(val, page, lang || state.searchLang);
145 | AppModel.analytics('q=' + val);
146 | DDMSModel.postKeyWords(val);
147 | updateDocTitle(val);
148 | }
149 |
150 | function requestSourceCode(repo) {
151 | setState({
152 | sourceCodeVisible: true,
153 | sourceCodeRequesting: true,
154 | sourceCodeRepo: repo
155 | });
156 | SearchCodeModel.requestSourceCode(repo.id);
157 | AppModel.analytics('sourcecode&q=' + state.sourceCodeVariable.keyword);
158 | }
159 |
160 | function updateDocTitle(title) {
161 | document.title = `${title ? (title + ' - ') : ''}CODELF`;
162 | }
163 |
164 | function handleLocationHashChanged(e) {
165 | e && e.preventDefault();
166 | const hash = HashHandler.get();
167 | hash && requestVariable(hash.replace(/(\?.*)/, ''));
168 | }
169 |
170 | function handleSearchCodeModelUpdate(curr, prev, mutation) {
171 | if (mutation.variableList) {
172 | setState({
173 | isZH: SearchCodeModel.isZH || state.isZH,
174 | isError: checkError(curr),
175 | variableRequesting: !mutation.variableList,
176 | searchValue: SearchCodeModel.searchValue,
177 | searchLang: SearchCodeModel.searchLang,
178 | page: SearchCodeModel.page,
179 | variableList: SearchCodeModel.variableList,
180 | suggestion: SearchCodeModel.suggestion
181 | });
182 | }
183 | if (mutation.sourceCode) {
184 | setState({
185 | sourceCodeRequesting: false,
186 | sourceCode: SearchCodeModel.sourceCode
187 | });
188 | }
189 | }
190 |
191 | return (
192 |
193 |
194 |
195 |
196 | {state.variableRequesting ? : (state.isError ? : '')}
197 | {renderSloganImage()}
198 |
199 | {state.variableList.length ? : ''}
200 |
203 | {renderDoodle()}
204 |
205 | )
206 | }
207 |
--------------------------------------------------------------------------------
/src/containers/NavBarContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Container, Icon, Popup } from 'semantic-ui-react';
3 | // import CopybookModel from '../models/CopybookModel';
4 |
5 | export default function NavBarContainer() {
6 | function handleOpenCopybook() {
7 | // CopybookModel.update({ visible: true });
8 | }
9 |
10 | return (
11 |
12 |
19 | }>
20 | Daily algorithm copybook, learn algorithm easily!
21 |
22 |
26 |
27 |
28 | }>
29 | Sorry, GitHub stars organize tool currently is not available, new version is coming soon :)
30 |
31 | */}
32 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 | )
45 | }
46 |
--------------------------------------------------------------------------------
/src/containers/NoticeContainer.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useRef } from 'react';
2 | import { Icon, Popup } from 'semantic-ui-react';
3 |
4 | export default function NoticeContainer() {
5 | const listEl = useRef(null);
6 | const [activeIndex, setDisable] = useSliderEffect(listEl);
7 |
8 | return (
9 |
56 | }
57 | trigger={
58 | [内推]字节跳动中国/美国/新加坡社招/校招/实习
59 | } />
60 |
61 |
62 | )
63 | }
64 |
65 | function useSliderEffect(el) {
66 | const [disable, setDisable] = useState(false);
67 | const [active, setActive] = useState(1);
68 | useEffect(() => {
69 | let interval = 0;
70 | const delay = setTimeout(() => {
71 | interval = setInterval(() => {
72 | !disable && renderItem(el.current.children);
73 | }, 5000);
74 | }, 15000);
75 |
76 | return () => {
77 | clearTimeout(delay);
78 | clearInterval(interval);
79 | };
80 | }, [disable]);
81 |
82 | function renderItem(list) {
83 | Array.prototype.forEach.call(list, (item, i) => {
84 | if (i === active) {
85 | item.classList.add('show');
86 | } else {
87 | item.classList.remove('show');
88 | }
89 | });
90 | const index = (active + 1) % list.length;
91 | setActive(index);
92 | }
93 | return [active, setDisable];
94 | }
95 |
--------------------------------------------------------------------------------
/src/models/AppModel.js:
--------------------------------------------------------------------------------
1 | import BaseModel from './BaseModel';
2 | import LocalStorage from '../utils/LocalStorage';
3 | import * as Tools from '../utils/Tools';
4 | import * as Configs from '../constants/Configs';
5 | import { searchParams } from '../utils/Param';
6 | import Navigator from '../utils/Navigator';
7 |
8 | const DEVICE_ID_KEY = `${Configs.APP_NANE}_device_id`;
9 |
10 | class AppModel extends BaseModel {
11 | constructor() {
12 | super();
13 | this._data = {
14 | debug: searchParams()['debug'],
15 | appName: Configs.APP_NANE,
16 | deviceId: LocalStorage.getItem(DEVICE_ID_KEY),
17 | isGithub: /github\.io/g.test(window.location.href)
18 | };
19 | if (!this._data.deviceId) {
20 | this._data.deviceId = Tools.uuid();
21 | LocalStorage.setItem(DEVICE_ID_KEY, this._data.deviceId)
22 | }
23 | }
24 |
25 | analytics(param) {
26 | (this.isGithub || this.debug) && setTimeout(function () {
27 | Navigator.getFrame(null).setAttribute('src', '//www.mihtool.com/analytics.html?codelf' + (param ? ('&' + param) : ''));
28 | }, param ? 500 : 1000);
29 | }
30 |
31 | genPersistenceKey(key) {
32 | if (key !== undefined && key !== null) {
33 | return `${this._data.appName}_${key}`;
34 | }
35 | return null;
36 | }
37 |
38 | get debug() {
39 | return this._data.debug;
40 | }
41 |
42 | get isGithub() {
43 | return this._data.isGithub;
44 | }
45 |
46 | get appName() {
47 | return this._data.appName;
48 | }
49 |
50 | get deviceId() {
51 | return this._data.deviceId;
52 | }
53 | }
54 |
55 | export default new AppModel();
56 |
--------------------------------------------------------------------------------
/src/models/BaseModel.js:
--------------------------------------------------------------------------------
1 | import EventEmitter from 'events';
2 |
3 | class Mutation {
4 | constructor(data) {
5 | this._data = data;
6 | this._serialize();
7 | this.has = this.has.bind(this);
8 | }
9 |
10 | _serialize() {
11 | Object.keys(this._data).forEach(key => {
12 | this[key] = true;
13 | });
14 | }
15 |
16 | get() {
17 | return this._data;
18 | }
19 |
20 | has(fields) {
21 | if (/string/i.test(typeof fields)) {
22 | fields = fields.split(',');
23 | }
24 | if (Array.isArray(fields)) {
25 | return fields.every((key) => {
26 | key = key.trim();
27 | return this[key];
28 | });
29 | }
30 | return false;
31 | }
32 | }
33 |
34 | class BaseModel extends EventEmitter {
35 | constructor() {
36 | super();
37 | this.on('error', () => { });
38 | this.setMaxListeners(99);
39 | this._updateEventName = 'update';
40 | this._data = {};
41 | }
42 |
43 | set(data) {
44 | let prevData = Object.assign({}, this._data);
45 | this._data = data || {};
46 | this.notify(prevData, Object.assign({}, prevData, data, { isReset: true }));
47 | }
48 |
49 | get() {
50 | return this._data;
51 | }
52 |
53 | create(data) {
54 | let instance = Object.create(Object.getPrototypeOf(this));
55 | instance._data = data;
56 | return instance;
57 | }
58 |
59 | notify(prevData, mutationData) {
60 | let data = Object.assign({}, this._data);
61 | this.emit(this._updateEventName, data, prevData || data, new Mutation(mutationData));
62 | }
63 |
64 | update(data) {
65 | let prevData = Object.assign({}, this._data);
66 | Object.assign(this._data, data);
67 | this.notify(prevData, data);
68 | }
69 |
70 | onUpdated(listener) {
71 | this.on(this._updateEventName, listener);
72 | }
73 |
74 | offUpdated(listener) {
75 | this.removeListener(this._updateEventName, listener);
76 | }
77 | }
78 |
79 | export default BaseModel;
80 |
--------------------------------------------------------------------------------
/src/models/CopybookModel.js:
--------------------------------------------------------------------------------
1 | import BaseModel from './BaseModel';
2 | import * as Tools from '../utils/Tools';
3 | import GitHubData from './metadata/GitHubData';
4 | import LocalStorage from '../utils/LocalStorage';
5 | import AppModel from './AppModel';
6 |
7 | const REPO_FILE_URL_KEY = AppModel.genPersistenceKey('agor_repo_file_url_key');
8 |
9 | class CopybookModel extends BaseModel {
10 | constructor() {
11 | super();
12 | this._data = {
13 | visible: false,
14 | fileList: [],
15 | selectedFile: null,
16 | fileContent: null,
17 | cachedFileUrl: LocalStorage.getItem(REPO_FILE_URL_KEY),
18 | };
19 | // only cache 24 hours
20 | if (this._data.cachedFileUrl && (new Date() - new Date(this._data.cachedFileUrl.timer)) >= 86400000) {
21 | this._data.cachedFileUrl = null;
22 | }
23 | setTimeout(() => this.requestRepoTrees(), 100);
24 | }
25 |
26 | async requestRepoTrees() {
27 | const clData = await GitHubData.requestCLangAlgorithmsRepoTree();
28 | if (!this._data.cachedFileUrl && clData) {
29 | this._updateFileList(clData);
30 | this.requestRepoFile(this._genCachedFile(this.fileList));
31 | }
32 | const jsData = await GitHubData.requestJavascriptAlgorithmsRepoTree();
33 | this._updateFileList(jsData);
34 | const pyData = await GitHubData.requestPythonAlgorithmsRepoTree();
35 | this._updateFileList(pyData);
36 | const jvData = await GitHubData.requestJavaAlgorithmsRepoTree();
37 | this._updateFileList(jvData);
38 | const swData = await GitHubData.requestSwiftAlgorithmsRepoTree();
39 | this._updateFileList(swData);
40 | if (this.fileList.length) {
41 | this.requestRepoFile(this._genCachedFile(this.fileList));
42 | }
43 | }
44 |
45 | async requestRepoFile(file) {
46 | if (!file) { return; }
47 | const data = await GitHubData.requestRepoFile(file.url);
48 | if (data) {
49 | const cachedFileUrl = {
50 | timer: (new Date()).toISOString().substr(0, 10),
51 | url: file.url
52 | };
53 | this.update({
54 | selectedFile: file,
55 | fileContent: data,
56 | cachedFileUrl: cachedFileUrl
57 | });
58 | LocalStorage.setItem(REPO_FILE_URL_KEY, cachedFileUrl);
59 | }
60 | }
61 |
62 | _updateFileList(data) {
63 | data && this.update({
64 | fileList: [...this.fileList, ...data]
65 | });
66 | }
67 |
68 | _genCachedFile(data) {
69 | let file;
70 | if (this._data.cachedFileUrl) {
71 | file = data.find(f => f.url === this._data.cachedFileUrl.url);
72 | }
73 | return file || Tools.randomList(data, 1)[0];
74 | }
75 |
76 | get fileList() {
77 | return this._data.fileList;
78 | }
79 |
80 | get selectedFile() {
81 | return this._data.selectedFile;
82 | }
83 |
84 | get fileContent() {
85 | return this._data.fileContent;
86 | }
87 |
88 | get visible() {
89 | return this._data.visible;
90 | }
91 | }
92 |
93 | export default new CopybookModel();
94 |
--------------------------------------------------------------------------------
/src/models/DDMSModel.js:
--------------------------------------------------------------------------------
1 | import BaseModel from './BaseModel';
2 | import FormHandler from '../utils/FormHandler';
3 | import LocalStorage from '../utils/LocalStorage';
4 | import AppModel from './AppModel';
5 | import * as Tools from '../utils/Tools';
6 | import JSONP from '../utils/JSONP';
7 |
8 | const formAction = '//ddms.mihtool.com/apis/v1/formdata/';
9 | const formDataAction = '//ddms.mihtool.com/apis/v1/formdata_detail/';
10 | const persistKeyWordsName = AppModel.genPersistenceKey('ddms_keywords');
11 | const persistOrganizerName = AppModel.genPersistenceKey('ddms_group_sync_id');
12 | const persistKeyWordsTimerName = persistKeyWordsName + '_timer';
13 | let cacheKeyWords = (LocalStorage.getItem(persistKeyWordsName) || '').split(',');
14 | const ot = new Date(LocalStorage.getItem(persistKeyWordsTimerName) || 0);
15 | const nt = Date.now();
16 |
17 | if ((nt - ot) > 1000 * 60 * 60 * 24) {
18 | cacheKeyWords = [];
19 | LocalStorage.setItem(persistKeyWordsTimerName, nt);
20 | }
21 |
22 | class DDMSModel extends BaseModel {
23 | constructor() {
24 | super();
25 | this._data = {
26 | organizerSyncId: LocalStorage.getItem(persistOrganizerName),
27 | luckyKeyWords: []
28 | };
29 | this.getLuckyKeyWords();
30 | }
31 |
32 | getLuckyKeyWords() {
33 | JSONP(`${formAction}?callback=?&formid=56e58775ade3a8e84dbacadf`).then(res => {
34 | if (res && res.code == 1) {
35 | this.update({
36 | luckyKeyWords: Tools.randomList([...new Set(res.data.reduce((cal, cur) => {
37 | if (cur.data.keyword.length > 1) {
38 | cal.push(cur.data.keyword);
39 | }
40 | return cal;
41 | }, []))], 6)
42 | });
43 | }
44 | });
45 | }
46 |
47 | postKeyWords(val) {
48 | if (!(AppModel.isGithub || AppModel.debug)) { return; }
49 | if (val && cacheKeyWords.indexOf(val) == -1) {
50 | FormHandler.asyncSubmit(formAction, {
51 | formid: '56e58775ade3a8e84dbacadf',
52 | keyword: val
53 | });
54 | this._saveKeyWords(val);
55 | }
56 | }
57 |
58 | postBookmarkUser(val) {
59 | if (val) {
60 | FormHandler.asyncSubmit(formAction, {
61 | formid: '56e587a9ade3a8e84dbacae1',
62 | account: val
63 | });
64 | }
65 | }
66 |
67 | postBookmarkGroup(repoid, repourl, groupname, lang, stars) {
68 | if (repoid) {
69 | FormHandler.asyncSubmit(formAction, {
70 | formid: '56e587ecade3a8e84dbacae3',
71 | repoid: repoid,
72 | repourl: repourl,
73 | groupname: groupname,
74 | lang: lang,
75 | stars: stars
76 | });
77 | }
78 | }
79 |
80 | postBookmarkOrganizer(data, callback) {
81 | if (data) {
82 | window.afterPostBookmarkOrganizer = callback;
83 | FormHandler.asyncSubmit(formAction, {
84 | formid: '56fb7d9dade3a8e84dbacaf0',
85 | success_url: Tools.thisPath + 'ddms_frame_callback.html?frame_callback=afterPostBookmarkOrganizer',
86 | data: data
87 | });
88 | }
89 | }
90 |
91 | postUpdateBookmarkOrganizer(id, data, callback) {
92 | if (id && data) {
93 | window.afterPostUpdateBookmarkOrganizer = callback;
94 | FormHandler.asyncSubmit(formDataAction, {
95 | id: id,
96 | success_url: Tools.thisPath + 'ddms_frame_callback.html?frame_callback=afterPostUpdateBookmarkOrganizer',
97 | data: data
98 | });
99 | }
100 | }
101 |
102 | getBookmarkOrganizer(id, callback) {
103 | JSONP(`${formDataAction}?callback=?&id=${id}`).then(data => {
104 | if (data) {
105 | callback && callback(data);
106 | }
107 | });
108 | }
109 |
110 | _saveKeyWords(val) {
111 | if (cacheKeyWords.indexOf(val) == -1) {
112 | cacheKeyWords.push(val);
113 | LocalStorage.setItem(persistKeyWordsName, cacheKeyWords.join(',').replace(/^,*/g, '').replace(/,*&/g, ''));
114 | }
115 | }
116 |
117 | set organizerSyncId(val) {
118 | this._data.organizerSyncId = val;
119 | LocalStorage.setItem(persistOrganizerName, val);
120 | }
121 |
122 | get organizerSyncId() {
123 | return this._data.organizerSyncId || LocalStorage.getItem(persistOrganizerName);
124 | }
125 |
126 | get luckyKeyWords() {
127 | return this._data.luckyKeyWords;
128 | }
129 | }
130 |
131 | export default new DDMSModel();
132 |
--------------------------------------------------------------------------------
/src/models/ErrorModel.js:
--------------------------------------------------------------------------------
1 | import BaseModel from './BaseModel';
2 |
3 | class ErrorModel extends BaseModel {
4 | constructor() {
5 | super();
6 | this._data = {
7 | visible: false,
8 | message: '',
9 | error: null
10 | };
11 | }
12 |
13 | get message() {
14 | return this._data.message;
15 | }
16 |
17 | get error() {
18 | return this._data.error;
19 | }
20 |
21 | set error(error) {
22 | this.update({
23 | visible: true,
24 | message: error.message,
25 | error: error
26 | });
27 | }
28 | }
29 |
30 | export default new ErrorModel();
31 |
--------------------------------------------------------------------------------
/src/models/Store.js:
--------------------------------------------------------------------------------
1 | import LocalStorage, { SessionStorage } from '../utils/LocalStorage';
2 | import * as Tools from '../utils/Tools';
3 | /**
4 | * Store data in memory cache.
5 | */
6 | export default class Store {
7 | /**
8 | * Create a memory cache.
9 | *
10 | * @param expire expire time in seconds for each record, Infinity value will never expire. default (60 * 60 * 1000)s.
11 | */
12 | constructor(expire, options) {
13 | this._expire = expire || (60 * 60 * 1000);
14 | this._cache = {};
15 | this._options = options || {};
16 | if (this._options.persistence === 'local') {
17 | this._local = LocalStorage;
18 | }
19 | if (this._options.persistence === 'session') {
20 | this._local = SessionStorage;
21 | }
22 | if (this._local && this._options.persistenceKey) {
23 | this._cache = this._local.getItem(this._options.persistenceKey) || {};
24 | }
25 | }
26 |
27 | /**
28 | * Returns cached record data with id.
29 | * Returns null if the record is expired.
30 | *
31 | * @param id unique id.
32 | * @return {*} cache data.
33 | */
34 | get(id) {
35 | if (id !== undefined || id != null) {
36 | id = Tools.MD5(id.toString());
37 | let record = this._cache[id];
38 | if (record) {
39 | // delete record when it is expired
40 | if (Date.now() - record.created > this._expire) {
41 | delete this._cache[id];
42 | return null;
43 | }
44 | return record.data;
45 | }
46 | return null;
47 | }
48 | return null;
49 | }
50 |
51 | /**
52 | * Save a record data to memory.
53 | * Saving different record with same id will always overwrite the old record.
54 | *
55 | * @param id unique id.
56 | * @param data cache record data.
57 | */
58 | save(id, data) {
59 | if (id !== undefined || id != null) {
60 | id = Tools.MD5(id.toString());
61 | this._cache[id] = {
62 | id: id,
63 | data: data,
64 | created: Date.now()
65 | };
66 | this._persist();
67 | }
68 | }
69 |
70 | /**
71 | * Clear all cached records.
72 | */
73 | clear() {
74 | this._cache = {};
75 | this._persist();
76 | }
77 |
78 | _persist() {
79 | if (this._local && this._options.persistenceKey) {
80 | this._local.setItem(this._options.persistenceKey, this._cache)
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/models/metadata/BaiduTranslateData.js:
--------------------------------------------------------------------------------
1 | import Store from '../Store';
2 | import * as Tools from '../../utils/Tools';
3 | import JSONP from '../../utils/JSONP';
4 | import { formatSuggestionStr, formatTranslationArr } from '../../utils/TranslateHandler';
5 | import AppModel from '../AppModel';
6 |
7 | /**
8 | * 特别重要,必读!
9 | * CODELF 用的是 Baidu 翻译 API 的免费套餐,一个月仅有200万字符请求限制!
10 | * 所以,如果你想二次开发,请单独申请自己的 Baidu 翻译 API 的 KEY,否则会直接影响 CODELF 的用户。
11 | * Baidu 翻译 API 申请参看: https://api.fanyi.baidu.com/api/trans/product/apidoc
12 | */
13 | const translateAppId = '20191206000363640';
14 | const translateKey = '4hJrdEmxB3M42OYwhAPA';
15 | const translateSalt = Date.now();
16 | const translateEndpoint = `//fanyi-api.baidu.com/api/trans/vip/translate?callback=?&from=auto&to=en&appid=${translateAppId}&salt=${translateSalt}`;
17 |
18 | // https://fanyi-api.baidu.com/api/trans/vip/translate?callback=baiduFanyiRequestCallback&from=auto&to=en&appid=20191206000363640&salt=1575646376369&q=%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD&sign=4e7d639cd17477acf5b13bd5ba6bab76
19 | function genUrl(val) {
20 | const sign = Tools.MD5(`${translateAppId}${val}${translateSalt}${translateKey}`); // appid+q+salt+密钥 的MD5值
21 | return `${translateEndpoint}&q=${encodeURIComponent(val)}&sign=${sign}`;
22 | }
23 |
24 | class BaiduTranslateData {
25 | constructor() {
26 | this._store = new Store(Infinity, {
27 | persistence: 'session',
28 | persistenceKey: AppModel.genPersistenceKey('baidu_translate_key')
29 | });
30 | }
31 |
32 | async request(val) {
33 | const cache = this._store.get(val);
34 | if (cache) {
35 | return cache;
36 | }
37 |
38 | try {
39 | const url = genUrl(val);
40 | let res = await JSONP(url, { callbackName: 'baiduFanyiRequestCallback' });
41 | if (res && res.trans_result) {
42 | let translation = res.trans_result.map(key => key.dst);
43 | let suggestion = formatSuggestionStr(translation.join(' '));
44 | translation = formatTranslationArr(translation);
45 | let response = { suggestion, translation };
46 | this._store.save(val, response);
47 | return response;
48 | } else {
49 | throw new Error(`Request Baidu translate failed`);
50 | }
51 | } catch (err) {
52 | return null;
53 | }
54 | }
55 | }
56 |
57 | export default new BaiduTranslateData();
58 |
--------------------------------------------------------------------------------
/src/models/metadata/BingTranslateData.js:
--------------------------------------------------------------------------------
1 | import Store from '../Store';
2 | import { formatSuggestionStr, formatTranslationArr } from '../../utils/TranslateHandler';
3 | import AppModel from '../AppModel';
4 |
5 | /**
6 | * 特别重要,必读!
7 | * CODELF 用的是 Bing 翻译 API 的免费套餐,一个月仅有200万字符请求限制!
8 | * 所以,如果你想二次开发,请单独申请自己的 Bing 翻译 API 的 KEY,否则会直接影响 CODELF 的用户。
9 | * Bing 翻译 API 申请参看: https://docs.microsoft.com/en-us/azure/cognitive-services/translator/
10 | * https://docs.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-translate
11 | */
12 | // curl -X POST "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=en" -H "Ocp-Apim-Subscription-Key: 445fd33be8764339add46f0770ac617d" -H "Content-Type: application/json; charset=UTF-8" -d "[{'Text':'咸鱼'}]"
13 | const translateEndpoint = 'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=en';
14 | const translateKey = '445fd33be8764339add46f0770ac617d';
15 |
16 | class BingTranslateData {
17 | constructor() {
18 | this._store = new Store(Infinity, {
19 | persistence: 'session',
20 | persistenceKey: AppModel.genPersistenceKey('bing_translate_key')
21 | });
22 | }
23 |
24 | async request(val) {
25 | const cache = this._store.get(val);
26 | if (cache) {
27 | return cache;
28 | }
29 |
30 | try {
31 | let res = await fetch(translateEndpoint, {
32 | method: 'POST',
33 | headers: {
34 | 'Ocp-Apim-Subscription-Key': translateKey,
35 | 'Content-Type': 'application/json; charset=UTF-8'
36 | },
37 | body: JSON.stringify(val.split(' ').map(text => { return { Text: text } }))
38 | });
39 | res = await res.json();
40 | if (res) {
41 | let suggestionStr = '';
42 | let suggestion = null;
43 | let translation = [];
44 |
45 | res.forEach(key => {
46 | const trans = key.translations.map(t => t.text);
47 | suggestionStr += ' ' + trans.join(' ');
48 | Array.prototype.push.apply(translation, trans);
49 | });
50 |
51 | suggestion = formatSuggestionStr(suggestionStr);
52 | if (translation) {
53 | translation = formatTranslationArr(translation);
54 | }
55 | let response = { suggestion, translation };
56 | this._store.save(val, response);
57 | return response;
58 | } else {
59 | throw new Error(`Request Bing translate failed`);
60 | }
61 | } catch (err) {
62 | return null;
63 | }
64 | }
65 | }
66 |
67 | export default new BingTranslateData();
68 |
--------------------------------------------------------------------------------
/src/models/metadata/GitHubData.js:
--------------------------------------------------------------------------------
1 | import Store from '../Store';
2 | import ErrorModel from '../ErrorModel';
3 |
4 | const CLANG = {
5 | name: 'TheAlgorithms/C',
6 | gitHub: 'https://github.com/TheAlgorithms/C/tree/master',
7 | postfix: '.c',
8 | included: [
9 | 'conversions',
10 | 'data_structures',
11 | 'hash',
12 | 'misc',
13 | 'searching',
14 | 'sorting'
15 | ],
16 | excluded: [
17 | ]
18 | };
19 |
20 | const JS = {
21 | name: 'trekhleb/javascript-algorithms',
22 | gitHub: 'https://github.com/trekhleb/javascript-algorithms/tree/master',
23 | postfix: '.js',
24 | included: [
25 | 'src/algorithms/',
26 | 'src/data-structures/'
27 | ],
28 | excluded: [
29 | '__test__'
30 | ]
31 | };
32 |
33 | const PY = {
34 | name: 'TheAlgorithms/Python',
35 | gitHub: 'https://github.com/TheAlgorithms/Python/tree/master',
36 | postfix: '.py',
37 | included: [
38 | 'Maths',
39 | 'binary_tree',
40 | 'data_structures',
41 | 'dynamic_programming',
42 | 'graphs',
43 | 'hashes',
44 | 'maths',
45 | 'other',
46 | 'searches',
47 | 'strings',
48 | 'sorts'
49 | ],
50 | excluded: [
51 | '__init__.py'
52 | ]
53 | };
54 |
55 | const JAVA = {
56 | name: 'TheAlgorithms/Java',
57 | gitHub: 'https://github.com/TheAlgorithms/Java/tree/master',
58 | postfix: '.java',
59 | included: [
60 | 'Conversions',
61 | 'DataStructures',
62 | 'Misc',
63 | 'Others',
64 | 'Searches',
65 | 'Sorts'
66 | ],
67 | excluded: [
68 | ]
69 | };
70 |
71 | const SWIFT = {
72 | name: 'raywenderlich/swift-algorithm-club',
73 | gitHub: 'https://github.com/raywenderlich/swift-algorithm-club/tree/master',
74 | postfix: '.swift',
75 | included: [
76 | ],
77 | excluded: [
78 | '/Tests/',
79 | '.playground'
80 | ]
81 | }
82 |
83 | class GitHubData {
84 | constructor() {
85 | this._repoStore = new Store(Infinity);
86 | }
87 |
88 | async requestRepoLatestCommit(repo) {
89 | const cacheId = 'requestRepoLatestCommit' + repo;
90 | const cache = this._repoStore.get(cacheId);
91 | if (cache) {
92 | return cache;
93 | }
94 | try {
95 | const url = `https://api.github.com/repos/${repo}/commits?`;
96 | let res = await fetch(url + (new Date()).toISOString().substr(0, 7));
97 | res = await res.json();
98 | if (res) {
99 | const data = res[0];
100 | this._repoStore.save(cacheId, data);
101 | return data;
102 | } else {
103 | throw new Error(`Request Repo latest Commit failed`);
104 | }
105 | } catch (err) {
106 | ErrorModel.error = err;
107 | }
108 | }
109 |
110 | async requestRepoTree(repo) {
111 | const cacheId = 'requestRepoTree' + repo.name;
112 | const cache = this._repoStore.get(cacheId);
113 | if (cache) {
114 | return cache;
115 | }
116 | try {
117 | const latestCommit = await this.requestRepoLatestCommit(repo.name);
118 | const url = `${latestCommit.commit.tree.url}?recursive=1`;
119 | let res = await fetch(url);
120 | res = await res.json();
121 | if (res) {
122 | const data = Array.prototype.filter.call(res.tree, n => {
123 | const path = n.path;
124 | n.link = `${repo.gitHub}/${path}`;
125 | return (this._isIncludedFile(path, repo.included) || !repo.included.length)
126 | && path.endsWith(repo.postfix)
127 | && !this._isIncludedFile(path, repo.excluded);
128 | });
129 | this._repoStore.save(cacheId, data);
130 | return data;
131 | } else {
132 | throw new Error(`Request Repo Tree failed`);
133 | }
134 | } catch (err) {
135 | ErrorModel.error = err;
136 | }
137 | }
138 |
139 | async requestJavascriptAlgorithmsRepoTree() {
140 | return this.requestRepoTree(JS);
141 | }
142 |
143 | async requestPythonAlgorithmsRepoTree() {
144 | return this.requestRepoTree(PY);
145 | }
146 |
147 | async requestJavaAlgorithmsRepoTree() {
148 | return this.requestRepoTree(JAVA);
149 | }
150 |
151 | async requestCLangAlgorithmsRepoTree() {
152 | return this.requestRepoTree(CLANG);
153 | }
154 |
155 | async requestSwiftAlgorithmsRepoTree() {
156 | return this.requestRepoTree(SWIFT);
157 | }
158 |
159 | async requestRepoFile(url) {
160 | const cache = this._repoStore.get(url);
161 | if (cache) {
162 | return cache;
163 | }
164 | try {
165 | let res = await fetch(url);
166 | res = await res.json();
167 | if (res) {
168 | res.content = window.atob(res.content);
169 | this._repoStore.save(url, res);
170 | return res;
171 | } else {
172 | throw new Error(`Request Repo File failed`);
173 | }
174 | } catch (err) {
175 | ErrorModel.error = err;
176 | }
177 | }
178 |
179 | _isIncludedFile(path, list) {
180 | return list.find(p => {
181 | return path.includes(p);
182 | });
183 | }
184 | }
185 |
186 | export default new GitHubData();
187 |
--------------------------------------------------------------------------------
/src/models/metadata/YoudaoTranslateData.js:
--------------------------------------------------------------------------------
1 | import Store from '../Store';
2 | import JSONP from '../../utils/JSONP';
3 | import { formatSuggestionStr, formatTranslationArr } from '../../utils/TranslateHandler';
4 | import AppModel from '../AppModel';
5 |
6 | /**
7 | * 特别重要,必读!
8 | * CODELF 用的是有道翻译 API 的免费套餐,1小时仅有1K的请求次数限制!
9 | * 所以,如果你想二次开发,请单独申请自己的有道翻译 API 的 KEY,否则会直接影响 CODELF 的用户。
10 | * 有道翻译 API 申请参看: http://fanyi.youdao.com/openapi?path=data-mode
11 | */
12 | const translateEndpoint = '//fanyi.youdao.com/openapi.do?callback=?&keyfrom=Codelf&key=2023743559&type=data&doctype=jsonp&version=1.1';
13 |
14 | class YoudaoTranslateData {
15 | constructor() {
16 | this._store = new Store(Infinity, {
17 | persistence: 'session',
18 | persistenceKey: AppModel.genPersistenceKey('youdao_translate_key')
19 | });
20 | }
21 |
22 | async request(val) {
23 | const cache = this._store.get(val);
24 | if (cache) {
25 | return cache;
26 | }
27 | const url = `${translateEndpoint}&q=${val}`;
28 | const data = await JSONP(url, { callbackName: 'youdaoFanyiRequestCallback' });
29 | try {
30 | let suggestionStr = '';
31 | let suggestion;
32 | let translation;
33 | //basic translate
34 | if (data.basic && data.basic.explains) {
35 | suggestionStr += data.basic.explains.join(' ');
36 | translation = suggestionStr;
37 | }
38 | //web translate
39 | if (data.web && data.web) {
40 | data.web.forEach(function (key) {
41 | suggestionStr += ' ' + key.value.join(' ');
42 | });
43 | }
44 | suggestion = formatSuggestionStr(suggestionStr);
45 | if (data && data.translation) {
46 | translation = formatTranslationArr(data.translation);
47 | }
48 | let response = { suggestion, translation };
49 | this._store.save(val, response);
50 | return response;
51 | } catch (e) {
52 | return null;
53 | }
54 | }
55 | }
56 |
57 | export default new YoudaoTranslateData();
58 |
--------------------------------------------------------------------------------
/src/utils/FormHandler.js:
--------------------------------------------------------------------------------
1 | import Navigator from './Navigator';
2 |
3 | const FormHandler = new function () {
4 | function getForm(method) {
5 | let _form = document.createElement('form');
6 | _form.setAttribute("style", "display:none;width:0;height:0;position: absolute;top:0;left:0;border:0;");
7 | _form.setAttribute("method", method || 'POST');
8 | document.body.appendChild(_form);
9 | return _form;
10 | }
11 |
12 | this.asyncSubmit = function (action, data) {
13 | this.submit(action, data, true);
14 | }
15 |
16 | this.submit = function (action, data, async) {
17 | let target,
18 | frame,
19 | form = getForm(),
20 | inputs = [],
21 | itpl = '';
22 |
23 | if (async) {
24 | target = '__formhandler_' + new Date().getTime();
25 | frame = Navigator.getFrame(null, target);
26 | form.setAttribute('target', target);
27 | setTimeout(function () {
28 | Navigator.removeFrame(frame);
29 | }, 120000);
30 | }
31 |
32 | form.setAttribute('action', action);
33 | data = data || {};
34 | for (let key in data) {
35 | inputs.push(itpl.replace('{N}', key).replace('{V}', data[key]));
36 | }
37 | form.innerHTML = inputs.join('');
38 | action && setTimeout(function () {
39 | form.submit();
40 | }, 100);
41 | }
42 | };
43 | export default FormHandler;
44 |
--------------------------------------------------------------------------------
/src/utils/HashHandler.js:
--------------------------------------------------------------------------------
1 | const HashHandler = (function () {
2 | let lc = window.location;
3 | function getByURL(url) {
4 | let hash;
5 | url && decodeURIComponent(url).replace(new RegExp('#(.*)', 'g'), function ($1, $2) {
6 | hash = $2;
7 | });
8 | return hash && decodeURIComponent(hash);
9 | }
10 |
11 | function get() {
12 | return getByURL(lc.hash);
13 | }
14 |
15 | function set(hash) {
16 | if (hash) {
17 | lc.hash = encodeURIComponent(hash);
18 | }
19 | }
20 |
21 | return {
22 | get: get,
23 | set: set,
24 | getByURL: getByURL
25 | }
26 | })();
27 |
28 | export default HashHandler;
29 |
--------------------------------------------------------------------------------
/src/utils/JSONP.js:
--------------------------------------------------------------------------------
1 | const JSONP = (url, options) => {
2 | options = options || {};
3 | url = options.url || url;
4 | return new Promise((resolve, reject) => {
5 | let timer = 0;
6 | let script = document.createElement('script');
7 | const callbackName = options.callbackName || `__jsonp_${Date.now()}_callback`;
8 | url = url.replace('=?', `=${callbackName}${options.nocache ? ('&_=' + Date.now()) : ''}`);
9 | const done = () => {
10 | window.clearTimeout(timer);
11 | try { document.head.removeChild(script); } catch (e) { }
12 | window[callbackName] = null;
13 | };
14 | const onerror = () => {
15 | window.removeEventListener('error', onerror);
16 | done();
17 | reject();
18 | };
19 | window[callbackName] = (...args) => {
20 | done();
21 | resolve(...args);
22 | };
23 | timer = setTimeout(onerror, 5 * 60 * 1000); // timeout in 5 min
24 | window.addEventListener('error', onerror);
25 | script.onerror = onerror;
26 | script.src = url;
27 | document.head.appendChild(script);
28 | });
29 | }
30 | export default JSONP;
31 |
--------------------------------------------------------------------------------
/src/utils/LocalStorage.js:
--------------------------------------------------------------------------------
1 | class BasicStorage {
2 | constructor() {
3 | this._store = {};
4 | }
5 |
6 | getItem(key) {
7 | return this._store[key];
8 | }
9 |
10 | setItem(key, value) {
11 | return this._store[key] = value;
12 | }
13 | }
14 |
15 | class Storage {
16 | constructor(store) {
17 | this._store = store;
18 | if (!store) {
19 | return new BasicStorage();
20 | }
21 | }
22 |
23 | getItem(key, defaultValue) {
24 | let rawValue = this._store.getItem(key);
25 | if (rawValue == null) {
26 | return defaultValue;
27 | }
28 | try {
29 | return JSON.parse(rawValue);
30 | } catch (e) {
31 | return null;
32 | }
33 | }
34 |
35 | setItem(key, value) {
36 | try {
37 | this._store.setItem(key, JSON.stringify(value));
38 | } catch (e) {
39 | // todo
40 | }
41 | }
42 | }
43 |
44 | const LocalStorage = new Storage(window.localStorage);
45 | const SessionStorage = new Storage(window.sessionStorage);
46 |
47 | export { SessionStorage };
48 | export default LocalStorage;
49 |
--------------------------------------------------------------------------------
/src/utils/Navigator.js:
--------------------------------------------------------------------------------
1 | const Navigator = (function () {
2 | let frame,
3 | androidReg = /Android/gi,
4 | isAndroid = androidReg.test(navigator.platform) || androidReg.test(navigator.userAgent);
5 | frame = null;
6 |
7 | function appendFrame(frame) {
8 | frame && document.body.appendChild(frame);
9 | }
10 |
11 | function removeFrame(frame) {
12 | frame && frame.parentNode.removeChild(frame);
13 | }
14 |
15 | function getFrame(src, name) {
16 | let _frame = document.createElement('iframe');
17 | _frame.setAttribute('style', 'display:none;width:0;height:0;position: absolute;top:0;left:0;border:0;');
18 | _frame.setAttribute('height', '0px');
19 | _frame.setAttribute('width', '0px');
20 | _frame.setAttribute('frameborder', '0');
21 | name && _frame.setAttribute('name', name);
22 | if (src) {
23 | _frame.setAttribute('src', src);
24 | } else {
25 | appendFrame(_frame);
26 | }
27 | return _frame;
28 | }
29 |
30 | function protocol(command, single, noframe) {
31 | let _frame, timer;
32 | if (noframe) {
33 | window.location.href = command;
34 | return;
35 | }
36 | if (single) {
37 | if (isAndroid) {
38 | _frame = getFrame();
39 | _frame.setAttribute('src', command);
40 | } else {
41 | _frame = getFrame(command);
42 | appendFrame(_frame);
43 | }
44 | timer = setTimeout(function () {
45 | _frame && removeFrame(_frame);
46 | }, 30000);
47 | _frame.onload = _frame.onreadystatechange = function () {
48 | timer && clearTimeout(timer);
49 | _frame && removeFrame(_frame);
50 | }
51 | } else {
52 | frame = frame || getFrame();
53 | frame.setAttribute('src', command);
54 | }
55 | }
56 |
57 | return {
58 | protocol: protocol,
59 | getFrame: getFrame,
60 | appendFrame: appendFrame,
61 | removeFrame: removeFrame
62 | }
63 | })();
64 |
65 | export default Navigator;
66 |
--------------------------------------------------------------------------------
/src/utils/Param.js:
--------------------------------------------------------------------------------
1 |
2 | function fn(str, reg) {
3 | if (str) {
4 | let data = {};
5 | str.replace(reg, function ($0, $1, $2, $3) {
6 | data[$1] = $3;
7 | });
8 | return data;
9 | }
10 | }
11 |
12 | export function searchParams(search) {
13 | search = search || window.location.search;
14 | return fn(search, new RegExp("([^?=&]+)(=([^&]*))?", "g")) || {};
15 | }
16 |
17 | export function hashParams(hash) {
18 | hash = hash || window.location.hash;
19 | return fn(hash, new RegExp("([^#=&]+)(=([^&]*))?", "g")) || {};
20 | }
21 |
22 | export function params(search, hash) {
23 | return {
24 | search: searchParams(search),
25 | hash: hashParams(hash)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/utils/Tools.js:
--------------------------------------------------------------------------------
1 | const ua = navigator.userAgent;
2 | const android = ua.match(/(Android);?[\s/]+([\d.]+)?/);
3 | const ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
4 | const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
5 | const iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
6 | let os = {};
7 |
8 | if (android) os.android = true, os.version = android[2];
9 | if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');
10 | if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');
11 | if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
12 |
13 | const thisPage = window.location.href.replace(window.location.hash, '');
14 | const thisPath = thisPage.substring(0, thisPage.lastIndexOf('/') + 1);
15 |
16 | const randomColor = () => {
17 | const letters = '0123456789ABCDEF'.split('');
18 | let color = '#';
19 | for (let i = 0; i < 6; i++) {
20 | color += letters[Math.floor(Math.random() * 16)];
21 | }
22 | return color;
23 | }
24 |
25 | const randomList = (list, len, verify, ratio) => {
26 | let rs = [], _list = list.slice(0);
27 | len = len || _list.length;
28 | ratio = ratio ? ratio : 0;
29 |
30 | function rd(_array) {
31 | _array.sort(function () {
32 | return (0.5 - Math.random());
33 | });
34 | }
35 |
36 | while (ratio) {
37 | rd(_list);
38 | ratio--;
39 | }
40 | if (_list.length <= len) {
41 | rs = _list;
42 | } else {
43 | while (rs.length < len) {
44 | let index = Math.floor(Math.random() * _list.length),
45 | item = _list[index];
46 | if ((verify && verify.call(this, item, _list)) || !verify) {
47 | rs.push(item);
48 | _list.splice(index, 1);
49 | }
50 | }
51 | }
52 | return rs;
53 | }
54 |
55 | const InlineWebWorker = {
56 | ready: window.Blob && window.Worker && window.URL,
57 | create: function create(selector) {
58 | return new Worker(window.URL.createObjectURL(new Blob([document.querySelector(selector).textContent])));
59 | }
60 | }
61 |
62 | const uuid = len => {
63 | let res = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {
64 | let num = Math.random() * 16 | 0, v = c === 'x' ? num : (num & 0x3 | 0x8);
65 | return v.toString(16);
66 | });
67 | return len ? res.substr(0, len) : res;
68 | }
69 |
70 | const randomLabelColor = () => {
71 | const colors = [
72 | 'red',
73 | 'orange',
74 | 'yellow',
75 | 'olive',
76 | 'green',
77 | 'teal',
78 | 'blue',
79 | 'violet',
80 | 'purple',
81 | 'pink',
82 | 'brown',
83 | ];
84 | return randomList(colors, 1)[0];
85 | };
86 |
87 | import SparkMD5 from 'spark-md5';
88 | const MD5 = SparkMD5.hash;
89 |
90 | export { os, thisPage, thisPath, randomList, randomColor, InlineWebWorker, uuid, randomLabelColor, MD5 }
91 |
--------------------------------------------------------------------------------
/src/utils/TranslateHandler.js:
--------------------------------------------------------------------------------
1 |
2 | export function formatSuggestionStr(str) {
3 | if (!str) { return []; }
4 | let tmp = [];
5 | return str.replace(/[`~!@#$^&*()=|{}':;',\[\].<>\/?~!@#¥……&*()——|\\{\\}【】‘;:”“’。,、?]/g, ' ')
6 | .replace(/\s+/ig, '+').split('+')
7 | .filter((key, idx, inputArray) => {
8 | const checked = key.length > 1
9 | && inputArray.indexOf(key) == idx
10 | && !/[^\x00-\xff]/gi.test(key)
11 | && !tmp.find(ikey => {
12 | return new RegExp('^' + key + '$', 'ig').test(ikey);
13 | });
14 | if (checked) {
15 | tmp.push(key);
16 | }
17 | return checked;
18 | });
19 | }
20 |
21 | export function formatTranslationArr(arr) {
22 | if (!arr) { return null; }
23 | return arr.join(' ')
24 | .replace(/[!$%^&*()_+|~=`{}\[\]:";'<>?,.\/]/g, '')
25 | .split(' ').filter(function (key, idx, inputArray) {
26 | return inputArray.indexOf(key) == idx && !/^(a|an|the)$/ig.test(key);
27 | }).join(' ');
28 | }
29 |
--------------------------------------------------------------------------------
/src/vendors/prettify.css:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Copyright (C) 2015 Google Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /* Pretty printing styles. Used with prettify.js. */
19 |
20 |
21 | /* SPAN elements with the classes below are added by prettyprint. */
22 | .pln { color: #000 } /* plain text */
23 |
24 | @media screen {
25 | .str { color: #080 } /* string content */
26 | .kwd { color: #008 } /* a keyword */
27 | .com { color: #800 } /* a comment */
28 | .typ { color: #606 } /* a type name */
29 | .lit { color: #066 } /* a literal value */
30 | /* punctuation, lisp open bracket, lisp close bracket */
31 | .pun, .opn, .clo { color: #660 }
32 | .tag { color: #008 } /* a markup tag name */
33 | .atn { color: #606 } /* a markup attribute name */
34 | .atv { color: #080 } /* a markup attribute value */
35 | .dec, .var { color: #606 } /* a declaration; a variable name */
36 | .fun { color: red } /* a function name */
37 | }
38 |
39 | /* Use higher contrast and text-weight for printable form. */
40 | @media print, projection {
41 | .str { color: #060 }
42 | .kwd { color: #006; font-weight: bold }
43 | .com { color: #600; font-style: italic }
44 | .typ { color: #404; font-weight: bold }
45 | .lit { color: #044 }
46 | .pun, .opn, .clo { color: #440 }
47 | .tag { color: #006; font-weight: bold }
48 | .atn { color: #404 }
49 | .atv { color: #060 }
50 | }
51 |
52 | /* Put a border around prettyprinted code snippets. */
53 | pre.prettyprint { padding: 2px; border: 1px solid #888 }
54 |
55 | /* Specify class=linenums on a pre to get line numbering */
56 | ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
57 | li.L0,
58 | li.L1,
59 | li.L2,
60 | li.L3,
61 | li.L5,
62 | li.L6,
63 | li.L7,
64 | li.L8 { list-style-type: none }
65 | /* Alternate shading for lines */
66 | li.L1,
67 | li.L3,
68 | li.L5,
69 | li.L7,
70 | li.L9 { background: #eee }
71 |
--------------------------------------------------------------------------------
/styles/_animation.scss:
--------------------------------------------------------------------------------
1 | %animate {
2 | animation-duration: $anim-default-time;
3 | animation-iteration-count: 1;
4 | animation-fill-mode: both;
5 | animation-timing-function: $anim-cubic-bezier;
6 | }
7 | /*https://github.com/tobiasahlin/SpinKit*/
8 | .spinner {
9 | animation: sk-rotateplane 1.2s infinite $anim-cubic-bezier;
10 | }
11 |
12 | @-webkit-keyframes sk-rotateplane {
13 | 0% {
14 | -webkit-transform: perspective(120px);
15 | }
16 |
17 | 50% {
18 | -webkit-transform: perspective(120px) rotateY(180deg);
19 | }
20 |
21 | 100% {
22 | -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg);
23 | }
24 | }
25 |
26 |
27 | @keyframes sk-rotateplane {
28 | 0% {
29 | transform: perspective(120px) rotateX(0deg) rotateY(0deg);
30 | -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
31 | }
32 |
33 | 50% {
34 | transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
35 | -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
36 | }
37 |
38 | 100% {
39 | transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
40 | -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/styles/_common.scss:
--------------------------------------------------------------------------------
1 | *,
2 | :after,
3 | :before {
4 | -webkit-box-sizing: border-box; /*size not include padding and margin*/
5 | }
6 |
7 | html, body {
8 | width: 100%;
9 | font-size: 1rem;
10 | line-height: 1.5;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | }
14 |
15 | body {
16 | background: #fff;
17 | color: #373a3c;
18 | transition: all 350ms $anim-cubic-bezier;
19 | &.dark {
20 | background: $dark;
21 | color: #fff;
22 | }
23 | }
24 |
25 | /*
26 | http://www.fontspace.com/538fonts/dressedless
27 | https://everythingfonts.com/ttf-to-svg
28 | */
29 | @font-face {
30 | font-family: 'Dressedless Three';
31 | src: url('../fonts/Dressedless_Three.ttf') format("truetype"), url('../fonts/Dressedless_Three.svg') format("svg");
32 | /* Legacy iOS */
33 | }
34 |
35 | /* latin-ext */
36 | @font-face {
37 | font-family: 'Lato';
38 | font-style: italic;
39 | font-weight: 400;
40 | src: local('Lato Italic'), local('Lato-Italic'), url('../fonts/LatoLatin-Italic.woff2') format('woff2');
41 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
42 | }
43 |
44 | /* latin */
45 | @font-face {
46 | font-family: 'Lato';
47 | font-style: italic;
48 | font-weight: 400;
49 | src: local('Lato Italic'), local('Lato-Italic'), url('../fonts/LatoLatin-Italic.woff2') format('woff2');
50 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
51 | }
52 |
53 | /* latin-ext */
54 | @font-face {
55 | font-family: 'Lato';
56 | font-style: italic;
57 | font-weight: 700;
58 | src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url('../fonts/LatoLatin-BoldItalic.woff2') format('woff2');
59 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
60 | }
61 |
62 | /* latin */
63 | @font-face {
64 | font-family: 'Lato';
65 | font-style: italic;
66 | font-weight: 700;
67 | src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url('../fonts/LatoLatin-BoldItalic.woff2') format('woff2');
68 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
69 | }
70 |
71 | /* latin-ext */
72 | @font-face {
73 | font-family: 'Lato';
74 | font-style: normal;
75 | font-weight: 400;
76 | src: local('Lato Regular'), local('Lato-Regular'), url('../fonts/LatoLatin-Regular.woff2') format('woff2');
77 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
78 | }
79 |
80 | /* latin */
81 | @font-face {
82 | font-family: 'Lato';
83 | font-style: normal;
84 | font-weight: 400;
85 | src: local('Lato Regular'), local('Lato-Regular'), url('../fonts/LatoLatin-Regular.woff2') format('woff2');
86 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
87 | }
88 |
89 | /* latin-ext */
90 | @font-face {
91 | font-family: 'Lato';
92 | font-style: normal;
93 | font-weight: 700;
94 | src: local('Lato Bold'), local('Lato-Bold'), url('../fonts/LatoLatin-Bold.woff2') format('woff2');
95 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
96 | }
97 |
98 | /* latin */
99 | @font-face {
100 | font-family: 'Lato';
101 | font-style: normal;
102 | font-weight: 700;
103 | src: local('Lato Bold'), local('Lato-Bold'), url('../fonts/LatoLatin-Bold.woff2') format('woff2');
104 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
105 | }
106 |
--------------------------------------------------------------------------------
/styles/_components.scss:
--------------------------------------------------------------------------------
1 | @import "logo";
2 | @import "donate";
3 | @import "nav-bar-container";
4 | @import "source-code";
5 | @import "doodle";
6 |
--------------------------------------------------------------------------------
/styles/_constants.scss:
--------------------------------------------------------------------------------
1 | /* animation */
2 | $anim-cubic-bezier: cubic-bezier(0.4, 0, 0.2, 1);
3 | $anim-default-time: 0.6s;
4 |
5 | /* color */
6 | $box-shadow: rgb(187,187,187) 0px 2px 8px !important;
7 | $dark: #272b38;
8 |
9 | /* dimensions */
10 |
--------------------------------------------------------------------------------
/styles/_containers.scss:
--------------------------------------------------------------------------------
1 | @import "main-container";
2 | @import "copybook-container";
3 | @import "notice-container";
4 |
--------------------------------------------------------------------------------
/styles/_copybook-container.scss:
--------------------------------------------------------------------------------
1 | @at-root {
2 | .copybook-container {
3 | {&}> .header {
4 | padding: 0.8rem 1rem;
5 | }
6 | > .content {
7 | position: relative;
8 | &:after {
9 | content: "";
10 | position: absolute;
11 | top: 0;
12 | left: 0;
13 | right: 0;
14 | bottom: 0;
15 | z-index: 1;
16 | transition: background $anim-default-time $anim-cubic-bezier;
17 | }
18 | &:hover, &:focus {
19 | &:after {
20 | background: rgba(255, 255, 255, 0.76);
21 | }
22 | }
23 | pre {
24 | position: relative;
25 | display: inline-block;
26 | margin: 0;
27 | padding: 0;
28 | min-width: 98%;
29 | }
30 | code {
31 | display: inline-block;
32 | color: #000;
33 | }
34 | }
35 | .ui.search.selection.dropdown {
36 | font-size: .8rem;
37 | min-width: 30rem;
38 | .menu>.item {
39 | font-size: .8rem;
40 | }
41 | }
42 | .title {
43 | text-align: center;
44 | font-size: 1rem;
45 | margin-bottom: -0.2rem;
46 | margin-top: -1rem;
47 | }
48 | .editor {
49 | position: absolute;
50 | top: 0;
51 | left: 0;
52 | right: 0;
53 | bottom: 0;
54 | z-index: 4;
55 | color: #000;
56 | -webkit-tap-highlight-color: rgba(255,255,255,0);
57 | outline: none;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/styles/_donate.scss:
--------------------------------------------------------------------------------
1 | .donate {
2 | padding: 2rem 0;
3 | text-align: center;
4 |
5 | form {
6 | display: inline-block;
7 | }
8 |
9 | .hd {
10 | padding-bottom: .8rem;
11 | text-align: center;
12 | }
13 |
14 | .bd {
15 | display: flex;
16 | flex-direction: row;
17 | align-items: center;
18 | }
19 |
20 | .zhifubao,
21 | .wechatpay,
22 | .paypal {
23 | margin: 0 0.5rem;
24 | width: 5rem;
25 | background: #fff;
26 | border-radius: 0.1rem;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/styles/_doodle.scss:
--------------------------------------------------------------------------------
1 | @at-root {
2 | css-doodle {
3 | position: fixed;
4 | z-index: -1;
5 | // fish
6 | &.fish {
7 | --color: @p(#FDFFFC, #2EC4B6, #E71D36, #FF9F1C);
8 | --color-fade: var(--color)@repeat2(@p([0-9a-b]));
9 | --noise: @svg-filter(
10 |
16 | );
17 |
18 | --rule: (
19 | :doodle {
20 | @grid: 12x1 / 100vw 100vh;
21 | background-position: 50%;
22 | filter: var(--noise);
23 | }
24 |
25 | @size: 100% 50%;
26 | position: absolute; top: 25%;
27 | transform: rotate(calc((@i() - 1) * 360deg / @size()));
28 |
29 | :after {
30 | --c: var(--color);
31 | --s: @r(5);
32 | content: '';
33 | position: absolute;
34 | @size: @r(40vmin, 61vmin) @r(12vmin, 17vmin);
35 | border-left: @r(3px) solid @var(--c);
36 | border-radius: 50vmin;
37 | background:
38 | radial-gradient(@var(--c) 50%, transparent 0%) 1vmin 42% / 3px 6px no-repeat,
39 | radial-gradient(@var(--c) 50%, transparent 0%) 1vmin 58% / 3px 6px no-repeat,
40 | @m20(linear-gradient(to right, @var(--c), transparent @r(50%, 80%)) 0 @r(100%) / @r(20%) 1px no-repeat),
41 | linear-gradient(to right, @var(--c), transparent @r(50%, 80%)) 0 50% / @r(40%, 60%) 1px no-repeat,
42 | linear-gradient(to right, rgba(255, 255, 255, .015), transparent);
43 | transform: rotateY(0) scaleX(@var(--s)) translateZ(50vmin);
44 | transform-origin: 0 50%;
45 | will-change: transform;
46 | animation: r @r(10s, 20s) linear infinite;
47 | animation-delay: -@r(50s);
48 | }
49 |
50 | @keyframes r {
51 | to { transform: rotateY(-1turn) scaleX(@var(--s)) translateZ(50vmin) }
52 | }
53 | );
54 | }
55 |
56 | // candy
57 | &.candy {
58 | --rule: ( :doodle {
59 | position: absolute;
60 | width: 100%;
61 | @grid: 10 / 101% 100vh;
62 | overflow: hidden;
63 | }
64 | animation: bounce linear @r(7s, 15s) @r(-1s, -5s) infinite;
65 | opacity: @r(0.3, 1);
66 | @place-cell: @r(100%) @r(100%);
67 | @random(.3) {
68 | :after {
69 | content: '🍭';
70 | position: absolute;
71 | font-size: @r(25px, 35px);
72 | transform: rotate(@r(360deg));
73 | }
74 | }
75 | @random(.2) {
76 | :after {
77 | content: '🍫';
78 | position: absolute;
79 | @place-cell: @r(100%) @r(100%);
80 | font-size: @r(15px, 25px);
81 | z-index: @p(1, 2);
82 | transform: rotate(@r(360deg));
83 | }
84 | }
85 | @random(.2) {
86 | :before {
87 | content: '🧁';
88 | position: absolute;
89 | @place-cell: @r(100%) @r(100%);
90 | font-size: @r(15px, 25px);
91 | z-index: @p(1, 2);
92 | transform: rotate(@r(360deg));
93 | }
94 | }
95 | @random(.2) {
96 | :before {
97 | content: '🍪';
98 | position: absolute;
99 | @place-cell: @r(100%) @r(100%);
100 | font-size: @r(15px, 25px);
101 | z-index: @p(1, 2);
102 | transform: rotate(@r(360deg));
103 | }
104 | }
105 |
106 | @keyframes bounce {
107 | 0% {
108 | transform: translateY(@r(-101vh, -110vh));
109 | }
110 | 100% {
111 | transform: translateY(@r(101vh, 110vh));
112 | }
113 | }
114 | );
115 | }
116 |
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/styles/_logo.scss:
--------------------------------------------------------------------------------
1 | @at-root {
2 | .logo {
3 | margin: 1rem auto;
4 | width: 3rem;
5 | height: 3rem;
6 |
7 | img {
8 | display: inherit;
9 | width: 100%;
10 | height: 100%;
11 | border-radius: 20%;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/styles/_main-container.scss:
--------------------------------------------------------------------------------
1 | .main-container {
2 | $dark-theme: 'body.dark &';
3 | position: relative;
4 | display: flex;
5 | align-items: center;
6 | flex-direction: column;
7 | padding-bottom: 3rem;
8 | .title {
9 | text-align: center;
10 | margin-top: 5rem;
11 | margin-bottom: 2rem;
12 | transition: margin 0.35s $anim-cubic-bezier;
13 | @media screen and (min-width: 50rem) {
14 | margin-top: 8rem;
15 | }
16 |
17 | a {
18 | color: inherit;
19 | text-decoration: none;
20 |
21 | &:visited, &:link, &:active, &:hover {
22 | color: inherit;
23 | text-decoration: none;
24 | }
25 | }
26 |
27 | span {
28 | font-family: "Dressedless Three", Lato, Roboto, 'Helvetica Neue', Arial, Helvetica, sans-serif;
29 | text-transform: uppercase;
30 | font-size: 3.5rem;
31 | font-weight: 100;
32 | @media screen and (min-width: 50rem) {
33 | font-size: 5rem;
34 | }
35 | }
36 |
37 | &.animated span {
38 | @extend %animate;
39 | animation-name: fadeIn;
40 | animation-duration: 250ms;
41 | animation-delay: 100ms;
42 | /*C*/
43 | &:nth-child(1) {
44 | color: #4285F4;
45 | }
46 |
47 | /*O*/
48 | &:nth-child(2) {
49 | color: #DB4437;
50 | }
51 |
52 | /*D*/
53 | &:nth-child(3) {
54 | color: #F4B400;
55 | }
56 |
57 | /*E*/
58 | &:nth-child(4) {
59 | color: #4285F4;
60 | }
61 |
62 | /*L*/
63 | &:nth-child(5) {
64 | color: #0F9D58;
65 | }
66 |
67 | /*F*/
68 | &:nth-child(6) {
69 | color: #DB4437;
70 | }
71 | }
72 | }
73 |
74 | #{$dark-theme} {
75 | .title {
76 | margin-top: 3rem;
77 | margin-bottom: 0;
78 | @media screen and (min-width: 50rem) {
79 | margin-top: 5rem;
80 | margin-bottom: 1rem;
81 | }
82 | }
83 | }
84 |
85 | .search-bar {
86 | padding: 1rem 0;
87 | width: 100%;
88 | @media screen and (min-width: 50rem) {
89 | width: 45rem;
90 | }
91 |
92 | form {
93 | padding: 0;
94 | margin: 0;
95 | border: 0;
96 | }
97 |
98 | &__desc {
99 | opacity: 0.5;
100 | padding-left: 0.8rem;
101 | font-size: 0.8rem;
102 | line-height: 1;
103 | margin-bottom: 0.2rem;
104 | @media screen and (min-width: 50rem) {
105 | padding-left: 1.4rem;
106 | font-size: 1rem;
107 | line-height: 1.5;
108 | margin-bottom: 0;
109 | }
110 | }
111 |
112 | &__input {
113 | background: #F1F3F4;
114 | border-radius: 5rem;
115 | transition: box-shadow 350ms $anim-cubic-bezier;
116 |
117 | &:focus, &:active, &:hover {
118 | box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.08);
119 | }
120 |
121 | input {
122 | background: #F1F3F4;
123 | border-radius: 5rem;
124 | border: 0 !important;
125 | }
126 | }
127 |
128 | &__dropdown {
129 | display: flex;
130 | justify-content: center;
131 | align-items: center;
132 | margin-top: -0.4rem;
133 | margin-left: 1rem;
134 |
135 | i {
136 | opacity: 0.5;
137 | font-size: 1rem;
138 | &:hover {
139 | opacity: 1;
140 | }
141 | @media screen and (min-width: 50rem) {
142 | font-size: 1.2rem;
143 | }
144 | }
145 | }
146 |
147 | &__plugins {
148 | padding-left: 0.8rem;
149 | color: inherit;
150 | opacity: 0.5;
151 | font-size: 0.8rem;
152 | a, a:hover, a:link, a:active, a:focus, a:visited {
153 | color: inherit;
154 | }
155 | a:hover {
156 | text-decoration: underline;
157 | }
158 | @media screen and (min-width: 50rem) {
159 | padding-left: 1.4rem;
160 | font-size: 1rem;
161 | }
162 | }
163 | }
164 |
165 | #{$dark-theme} {
166 | .search-bar {
167 | &__input {
168 | &:focus, &:active, &:hover {
169 | box-shadow: $box-shadow;
170 | }
171 | }
172 | }
173 | }
174 |
175 | .suggestion {
176 | padding-bottom: 2rem;
177 | max-width: 100%;
178 | @media screen and (min-width: 50rem) {
179 | min-width: 43rem;
180 | }
181 | a {
182 | &:hover {
183 | text-decoration: underline;
184 | }
185 | }
186 | }
187 |
188 | .variable-list {
189 | width: 100%;
190 | text-align: center;
191 |
192 | .label {
193 | @extend .pointer-link;
194 | margin: 0.4rem 0.4rem 0 0;
195 | &:hover {
196 | box-shadow: $box-shadow;
197 | }
198 | &.animated {
199 | transform: translateZ(0);
200 | will-change: transform;
201 | }
202 | }
203 |
204 | hr {
205 | width: 70%;
206 | border-color: rgba(0, 0, 0, .16);
207 | margin-top: 1rem;
208 | }
209 | }
210 |
211 | .search-error {
212 | margin: 1rem 0;
213 | }
214 |
215 | .slogan-image {
216 | padding: 2rem 1rem;
217 | @media screen and (min-width: 50rem) {
218 | padding: 4rem 1rem;
219 | }
220 |
221 | img {
222 | max-width: 100%;
223 | height: auto;
224 | }
225 | }
226 | }
227 |
228 |
--------------------------------------------------------------------------------
/styles/_nav-bar-container.scss:
--------------------------------------------------------------------------------
1 | .nav-bar-container {
2 | position: relative;
3 | top: 0;
4 | z-index: 10;
5 | .bd {
6 | top: -0.25rem;
7 | right: 0;
8 | position: absolute;
9 | display: inline-block;
10 | transition: all 1s;
11 | >*{
12 | float: left;
13 | display: inline-block;
14 | cursor: pointer;
15 | margin-right: 0.4rem;
16 | }
17 | &:last-child{
18 | margin-right: 0;
19 | }
20 | i{
21 | width: auto;
22 | height: auto;
23 | margin: 0 !important;
24 | font-size: 2rem;
25 | color: #70B7FD;
26 | &:hover,&:active{
27 | color: #59AAF9;
28 | }
29 | }
30 | .github-corner {
31 | margin-top: -0.2rem;
32 | i {
33 | font-size: 2.3rem;
34 | }
35 | }
36 | .copybook-btn {
37 | display: none;
38 | }
39 | $anim-delay: 150ms;
40 | $anim-duration: 500ms;
41 | @for $i from 1 through 5 {
42 | >*:nth-child(#{$i}) {
43 | animation-duration: $anim-duration;
44 | animation-delay: 500 + $anim-delay*($i - 1);
45 | }
46 | }
47 | }
48 | @media screen and (min-width: 50rem) {
49 | top: -0.25rem;
50 | .bd {
51 | i{
52 | width: auto;
53 | height: 3.4rem;
54 | font-size: 3rem;
55 | }
56 | .copybook-btn.copybook-btn.copybook-btn {
57 | display: inline-block;
58 | }
59 | .github-corner {
60 | margin-top: -0.2rem;
61 | i {
62 | font-size: 3.3rem;
63 | }
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/styles/_notice-container.scss:
--------------------------------------------------------------------------------
1 | .notice-container {
2 | $dark-theme: 'body.dark &';
3 | position: fixed;
4 | bottom: 0;
5 | left: 0;
6 | width: 100%;
7 | padding-bottom: 1rem;
8 | padding-top: 0.5rem;
9 | text-align: center;
10 | background-color: #fff;
11 | transition: background-color 150ms ease-in-out;
12 | @at-root {
13 | #{$dark-theme} {
14 | background-color: $dark;
15 | }
16 | }
17 | a {
18 | display: none;
19 | color: #70B7FD;
20 | &.show {
21 | display: block;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/styles/_source-code.scss:
--------------------------------------------------------------------------------
1 | @at-root {
2 | .source-code {
3 | {&}> .header {
4 | padding: 0.8rem 1rem;
5 | }
6 | > .content {
7 | pre {
8 | display: inline-block;
9 | margin: 0;
10 | padding: 0;
11 | }
12 | code {
13 | display: inline-block;
14 | color: #000;
15 | }
16 | }
17 | {&} .ui.dropdown .menu>.item {
18 | padding: 0.4rem 0 0 0.4rem !important;
19 | &:last-child {
20 | padding-bottom: 0.4rem !important;
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/styles/_utils.scss:
--------------------------------------------------------------------------------
1 | @mixin clearfix() {
2 | & {
3 | &::before,
4 | &::after {
5 | content: "";
6 | display: table;
7 | }
8 | &::after {
9 | clear: both;
10 | }
11 | }
12 | }
13 |
14 | %ellipsis {
15 | white-space: nowrap;
16 | overflow: hidden;
17 | text-overflow: ellipsis;
18 | }
19 |
20 | .up-first {
21 | &::first-letter {
22 | text-transform: uppercase
23 | }
24 | }
25 |
26 | .pointer-link {
27 | cursor: pointer;
28 | }
29 |
30 | .hidden-link {
31 | {&} {
32 | color: #000;
33 | }
34 | {&}:hover {
35 | color: #1e70bf;
36 | }
37 | }
38 |
39 | .fix-break-word, p {
40 | word-break: break-all;
41 | word-break: break-word;
42 | -webkit-hyphens: auto;
43 | hyphens: auto;
44 | }
45 |
46 | .fix-modal.fix-modal.fix-modal.fix-modal {
47 | height: 97%;
48 | margin: 0 auto;
49 | overflow: hidden;
50 | transform: translate3d(0, 0, 0);
51 | {&} > .content {
52 | padding: 0.4rem 1rem;
53 | margin: 0;
54 | height: 91%;
55 | overflow: scroll;
56 | -webkit-overflow-scrolling: touch;
57 | }
58 | }
59 | @media (min-width: 50rem) {
60 | .fix-modal.fix-modal.fix-modal.fix-modal {
61 | height: auto;
62 | overflow: visible;
63 | .close.icon {
64 | top: 0.5rem;
65 | right: 0.5rem;
66 | color: rgba(0,0,0,.87);
67 | }
68 | {&} > .content {
69 | height: auto;
70 | overflow-y: visible;
71 | }
72 | }
73 | }
74 |
75 | .fix-dropdown-menu {
76 | -webkit-overflow-scrolling: touch;
77 | }
78 |
--------------------------------------------------------------------------------
/styles/app.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | @import 'constants';
3 | @import 'common';
4 | @import 'utils';
5 | @import "animation";
6 | .app {
7 | position: relative;
8 | @import 'components';
9 | @import 'containers';
10 | }
11 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const path = require('path');
4 | const merge = require('webpack-merge');
5 |
6 | const common = {
7 | entry: ['@babel/polyfill', './src/App.js'],
8 | output: {
9 | filename: 'app.js',
10 | path: path.resolve(__dirname, 'app/js'),
11 | publicPath: '/app/js'
12 | },
13 | externals: {
14 | 'react': 'React',
15 | 'react-dom': 'ReactDOM'
16 | },
17 | module: {
18 | rules: [
19 | {
20 | test: /\.jsx?$/,
21 | include: [
22 | path.resolve(__dirname, 'src'),
23 | path.resolve(__dirname, 'node_modules')
24 | ],
25 | loader: 'babel-loader'
26 | }
27 | ]
28 | }
29 | };
30 |
31 | exports.dev = merge(common, {
32 | mode: 'development',
33 | devtool: 'source-map'
34 | });
35 |
36 | exports.prod = merge(common, {
37 | mode: 'production'
38 | });
39 |
--------------------------------------------------------------------------------