├── .gitignore
├── keymaps
└── element-helper.json
├── resources
├── repos.json
├── element
│ ├── fix2.js
│ ├── fix1.js
│ ├── style.css
│ └── index.json
└── style.css
├── styles
└── element-helper.less
├── CHANGELOG.md
├── package.json
├── LICENSE.md
├── lib
├── docset.js
├── search-view.js
├── element-helper.js
├── resource.js
├── library.js
├── document-view.js
└── provider.js
├── snippets
└── element.cson
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 | resources/element-gh-pages
5 | resources/element/versions.json
6 |
--------------------------------------------------------------------------------
/keymaps/element-helper.json:
--------------------------------------------------------------------------------
1 | {
2 | "atom-workspace": {
3 | "ctrl-cmd-z": "element-helper:search-under-cursor"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/resources/repos.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "type": "element",
4 | "name": "Element UI",
5 | "links": {
6 | "home": "http://element.eleme.io",
7 | "source": "https://github.com/ElemeFE/element"
8 | }
9 | }
10 | ]
11 |
--------------------------------------------------------------------------------
/styles/element-helper.less:
--------------------------------------------------------------------------------
1 | // The ui-variables file is provided by base themes provided by Atom.
2 | //
3 | // See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less
4 | // for a full listing of what's available.
5 | @import "ui-variables";
6 |
7 | .element-helper-docs-item-left {
8 | color: white;
9 | }
10 | .element-helper-docs-item-right {
11 | float: right;
12 | }
13 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.3.2
2 | * add loading animation
3 | * fix title change problem
4 | * fetch attrs and tags json files from npm
5 | * update document.gif
6 | * other optimize
7 |
8 | ## 0.3.1 - Modify description
9 |
10 | ## 0.3.0 - Add menu
11 |
12 | ## 0.2.3 - Update Document
13 |
14 | ## 0.2.2 - Change keymap
15 |
16 | ## 0.2.1 - Support el-table-column tag to search
17 |
18 | ## 0.2.0 - Update some examples
19 |
20 | ## 0.1.0 - First Release
21 | * Every feature added
22 | * Every bug fixed
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "element-helper",
3 | "main": "./lib/element-helper",
4 | "version": "0.5.4",
5 | "description": "Element-Helper is a Atom package and support snippets, autocomplete and document.",
6 | "keywords": [],
7 | "repository": "https://github.com/ElemeFE/element-helper",
8 | "license": "MIT",
9 | "engines": {
10 | "atom": ">=1.0.0 <2.0.0"
11 | },
12 | "providedServices": {
13 | "autocomplete.provider": {
14 | "versions": {
15 | "2.0.0": "provide"
16 | }
17 | }
18 | },
19 | "dependencies": {
20 | "atom-space-pen-views": "^2.0.0",
21 | "cheerio": "^1.0.0-rc.1",
22 | "element-gh-pages": "^1.0.13",
23 | "element-helper-json": "^1.0.0",
24 | "follow-redirects": "^1.2.3",
25 | "jquery": "^3.3.1",
26 | "mkdirp": "^0.5.0",
27 | "pretty": "^2.0.0",
28 | "shelljs": "^0.7.8"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 ElemeFE
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lib/docset.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import Path from 'path';
4 | import Resource from './resource';
5 |
6 | class DocSet {
7 | constructor(item) {
8 | this.id_ = item.type;
9 | this.indexPath = this.id_ + '/index.json';
10 | this.index_ = null;
11 | this.language_ = atom.config.get('element-helper.language');
12 |
13 | atom.config.observe('element-helper.' + this.id_, this.setEnabled.bind(this));
14 | }
15 |
16 | setEnabled(enabled) {
17 | if (!enabled) {
18 | this.index_ = null;
19 | return;
20 | }
21 |
22 | Resource.get(Path.join(Resource.RESOURCE_PATH, this.indexPath))
23 | .then(result => {
24 | this.index_ = JSON.parse(result);
25 |
26 | for (var i = 0 ; i < this.index_.entries.length; ++i) {
27 | this.index_.entries[i].id = this.id_;
28 | this.index_.entries[i].url = `elements-docs://${this.id_}/${this.index_.entries[i].path}`;
29 | }
30 | });
31 | }
32 |
33 | getTitle(path) {
34 | for (let i = 0; i < this.index_.entries.length; ++i) {
35 | if (this.index_.entries[i].path == path) {
36 | return this.language_ === 'zh-CN' ? this.index_.entries[i].name : this.index_.entries[i].name.split(' ').shift();
37 | }
38 | }
39 | return '';
40 | }
41 |
42 | queryAll() {
43 | return !this.index_ ? [] : this.index_.entries;
44 | }
45 | }
46 |
47 | export default DocSet;
48 |
--------------------------------------------------------------------------------
/resources/element/fix2.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | $(document.body).css('display', 'none');
4 | $(window).on('load', () => {
5 | const container = $('.page-container.page-component');
6 | container.find('.page-component__content').first().addClass('page-container-right').css('margin-left', '20px');
7 | let menu = container.find('.page-component__nav').first();
8 | menu.addClass('page-container-left').find('.nav-dropdown').remove();
9 | menu.append('
');
10 |
11 | $('.headerWrapper, .footer-nav, .page-component-up, .demo-block-control button').remove();
12 | container.addClass('hide-menu');
13 |
14 | const page = $('.el-scrollbar__view');
15 | page.on('click', '.show-menu .menu-button, .page-container-right', function () {
16 | container.addClass('hide-menu').removeClass('show-menu');
17 | container.find('.menu-button').text('>>');
18 | });
19 | page.on('click', '.hide-menu .menu-button', function () {
20 | container.addClass('show-menu').removeClass('hide-menu');
21 | container.find('.menu-button').text('<<');
22 | });
23 | page.on('click', '.side-nav .nav-item a', function () {
24 | window.parent.postMessage({ title: this.textContent, hash: this.href.split('#').pop() }, '*');
25 | $('.demo-block-control button, .page-component-up').remove();
26 | });
27 | $(document.body).css('display', 'block');
28 | window.parent.postMessage({ loaded: true }, '*');
29 | });
30 |
--------------------------------------------------------------------------------
/resources/element/fix1.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | $(document.body).css('display', 'none');
4 | $(window).on('load', () => {
5 | const container = $('.page-container.page-component');
6 | container.find('.el-row .el-col:nth-child(2)').first().attr('class', "page-container-right").css('margin-left', '20px');
7 | let menu = container.find('.el-row .el-col:nth-child(1)').first();
8 | menu.attr('class', 'page-container-left').find('.nav-dropdown').remove();
9 | menu.append('');
10 |
11 | $('.headerWrapper, .footer, .footer-nav, .page-component-up, .header-anchor, .description button').remove();
12 | container.css({padding: 0, margin: 0}).children().attr('class', 'hide-menu');
13 |
14 | container.on('click', '.show-menu .menu-button, .page-container-right', function () {
15 | container.children().attr('class', 'hide-menu');
16 | container.find('.menu-button').text('>>');
17 | });
18 | container.on('click', '.hide-menu .menu-button', function () {
19 | container.children().attr('class', 'show-menu');
20 | container.find('.menu-button').text('<<');
21 | });
22 | container.on('click', '.side-nav .nav-item a', function () {
23 | window.parent.postMessage({ title: this.textContent, hash: this.href.split('#').pop() }, '*');
24 | $('.description button').remove();
25 | });
26 | $(document.body).css('display', 'block');
27 | window.parent.postMessage({ loaded: true }, '*');
28 | });
29 |
--------------------------------------------------------------------------------
/lib/search-view.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import $ from 'jquery';
4 | import { SelectListView } from 'atom-space-pen-views';
5 |
6 | class SearchView extends SelectListView {
7 |
8 | constructor(word, items) {
9 | super();
10 | this.docView_ = null;
11 | this.confirmed_ = false;
12 | this.setViewPromise_ = null;
13 | this.panel_ = atom.workspace.addModalPanel({item: this});
14 |
15 | this.filterEditorView.setText(word);
16 | this.setMaxItems(50);
17 | this.setItems(items);
18 | this.storeFocusedElement();
19 | this.focusFilterEditor();
20 | }
21 |
22 | viewForItem(item) {
23 | const tag = $('').text(item.tag).html();
24 | const name = $('').text(item.name).html();
25 | return `${tag}${name}`;
26 | }
27 |
28 | confirmed(item) {
29 | this.confirmed_ = true;
30 | this.showViewForItem(item);
31 | this.filterEditorView.blur();
32 | }
33 |
34 | cancelled() {
35 | if (!this.confirmed_ && this.docView_) {
36 | this.docView_.destroy();
37 | }
38 | this.panel_.destroy();
39 | }
40 |
41 | getFilterKey() {
42 | return 'description';
43 | }
44 |
45 | showViewForItem(item) {
46 | if (!this.setViewPromise_) {
47 | this.setViewPromise_ = atom.workspace.open('element-docs://', { split: 'right', activatePane: false})
48 | .then(docView => {
49 | this.docView_ = docView;
50 | this.docView_.setView(item.url);
51 | });
52 | } else {
53 | this.setViewPromise_ = this.setViewPromise_.then(() => {
54 | this.docView_.setView(item.url);
55 | })
56 | }
57 | }
58 | }
59 |
60 | module.exports = SearchView;
61 |
--------------------------------------------------------------------------------
/resources/element/style.css:
--------------------------------------------------------------------------------
1 | .page-container h2 {font-size: 1.5rem;}.page-container h3 {font-size: 1.17rem;}.page-container p {font-size: 12px;}
2 | /* Menu */
3 | .side-nav {
4 | position: fixed;
5 | z-index: 1001;
6 | width: 230px;
7 | height: 100%;
8 | background: #eef1f6;
9 | transform: translate(-230px);
10 | transition: transform 0.4s cubic-bezier(0.7,0,0.3,1);
11 | overflow: auto;
12 | padding: 0 10px;
13 | }
14 | .side-nav ul > li a, .side-nav .nav-group__title {
15 | cursor: pointer;
16 | }
17 | .page-container-right {
18 | transition: 0.4s cubic-bezier(0.7,0,0.3,1);
19 | }
20 | .hide-menu .menu-button{
21 | left: 0;
22 | transition: left 0.4s cubic-bezier(0.7,0,0.3,1);
23 | }
24 | .show-menu .menu-button {
25 | left: 230px;
26 | transition: left 0.4s cubic-bezier(0.7,0,0.3,1);
27 | }
28 | .menu-button {
29 | cursor: pointer;
30 | width: 15px;
31 | height: 30px;
32 | line-height: 30px;
33 | background: #20a0ff;
34 | position: fixed;
35 | top: 50%;
36 | font-size: 12px;
37 | z-index: 10;
38 | color: white;
39 | border-radius: 0 5px 5px 0;
40 | }
41 | /* Shown menu */
42 | .show-menu .side-nav {
43 | transform: translate(0);
44 | transition: transform 0.4s cubic-bezier(0.7,0,0.3,1);
45 | }
46 | .show-menu .page-container-right {
47 | transform: translate(245px);
48 | transition: transform 0.4s cubic-bezier(0.7,0,0.3,1);
49 | }
50 | .show-menu .menu-button {
51 | background-color: #eef1f6;
52 | color: #666;
53 | transition: 0.5s;
54 | }
55 |
56 | .page-component__scroll {
57 | height: calc(100%) !important;
58 | margin-top: 0 !important;
59 | }
60 |
61 | .page-component__nav {
62 | margin-top: 0px !important;
63 | }
64 |
65 | .page-component__content {
66 | padding: 0px !important;
67 | }
68 |
69 | .page-container {
70 | width: 100%;
71 | }
72 |
--------------------------------------------------------------------------------
/snippets/element.cson:
--------------------------------------------------------------------------------
1 | ".source.js":
2 | "message":
3 | "prefix": "msg",
4 | "body": """
5 | this.$message({
6 | message: '${1:text}',
7 | type: '${2:info}'
8 | });
9 | """
10 | "msgbox-alert":
11 | "prefix": "alert",
12 | "body": """
13 | this.$alert('${1:content}', '${2:title}', {
14 | confirmButtonText: '${3:confirm}',
15 | callback: ${4:action} => {
16 |
17 | }
18 | });
19 | """
20 | "msgbox-confirm":
21 | "prefix": "confirm",
22 | "body": """
23 | this.$confirm('${1:content}', '${2:title}', {
24 | confirmButtonText: '${3:confirm}',
25 | cancelButtonText: '${4:cancel}',
26 | type: '${5:warning}'
27 | }).then(() => {
28 |
29 | }).catch(() => {});
30 | """
31 | "msgbox-prompt":
32 | "prefix": "prompt",
33 | "body": """
34 | this.$prompt('${1:content}', '${2:title}', {
35 | confirmButtonText: '${3:confirm}',
36 | cancelButtonText: '${4:cancel}',
37 | inputPattern: /${5:regExp}/,
38 | inputErrorMessage: '${6:errormsg}'
39 | }).then(({ value }) => {
40 |
41 | }).catch(() => {});
42 | """
43 | "msgbox":
44 | "prefix": "msgb",
45 | "body": """
46 | this.$msgbox({
47 | title: '${1:title}',
48 | message: '${2:string|VNode}',
49 | showCancelButton: ${3:true},
50 | confirmButtonText: '${4:confirm}',
51 | cancelButtonText: '${5:cancel}',
52 | beforeClose: (action, instance, done) => {}
53 | }).then(action => {
54 |
55 | });
56 | """
57 | "notification":
58 | "prefix": "notify",
59 | "body": """
60 | this.$notify({
61 | title: '${1:title}',
62 | message: '${2:string|VNode}'
63 | });
64 | """
65 |
--------------------------------------------------------------------------------
/lib/element-helper.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import Url from 'url';
4 | import { CompositeDisposable } from 'atom';
5 | import Library from './library';
6 | import provider from './provider';
7 |
8 | let DocView = null;
9 | let SearchView = null;
10 |
11 | export default {
12 | config: {
13 | 'language': {
14 | title: 'Document Language',
15 | type: 'string',
16 | default: 'zh-CN',
17 | enum: ['zh-CN', 'en-US'],
18 | order: 2,
19 | }
20 | },
21 | activate(state) {
22 | this.subscriptions = new CompositeDisposable();
23 | this.library = new Library();
24 |
25 | this.lazyLoad();
26 | // Register command
27 | this.subscriptions.add(atom.commands.add('atom-workspace', {
28 | 'element-helper:search-under-cursor': this.search.bind(this)
29 | }));
30 |
31 | this.subscriptions.add(atom.workspace.addOpener(this.opener.bind(this)));
32 | },
33 |
34 | deactivate() {
35 | this.subscriptions.dispose();
36 | },
37 |
38 | search() {
39 | if (localStorage.getItem('element-helper.loading')) {
40 | atom.notifications.addInfo('Document is loading, please wait a minute.');
41 | return;
42 | }
43 | if (editor = atom.workspace.getActiveTextEditor()) {
44 | const selectedText = editor.getSelectedText();
45 | const wordUnderCursor = editor.getWordUnderCursor({ includeNonWordCharacters: false });
46 |
47 | const items = this.library.queryAll();
48 | const queryText = selectedText ? selectedText : wordUnderCursor;
49 |
50 | new SearchView(queryText, items);
51 | }
52 | },
53 |
54 | opener(url) {
55 | if (Url.parse(url).protocol == 'element-docs:') {
56 | return new DocView(this.library, url);
57 | }
58 | },
59 |
60 | lazyLoad() {
61 | if (!SearchView) {
62 | SearchView = require('./search-view');
63 | }
64 | if (!DocView) {
65 | DocView = require('./document-view');
66 | }
67 | },
68 |
69 | provide() {
70 | return provider;
71 | }
72 | };
73 |
--------------------------------------------------------------------------------
/resources/style.css:
--------------------------------------------------------------------------------
1 | .element-helper-docs-container {
2 | background-color: white;
3 | overflow: auto;
4 | }
5 | .element-helper-docs-container .docs-version {
6 | color: #50bfff;
7 | }
8 | .element-helper-docs-container .docs-notice {
9 | position: absolute;
10 | right: 10px;
11 | background: #50bfff;
12 | color: white;
13 | padding: 2px 8px;
14 | border-radius: 2px;
15 | }
16 |
17 | .element-helper-docs-container .docs-notice a {
18 | color: inherit;
19 | text-decoration: underline;
20 | }
21 |
22 | .element-helper-loading-mask, .element-helper-move-mask {
23 | position: absolute;
24 | z-index: 10000;
25 | background-color: hsla(0,0%,100%,.9);
26 | margin: 0;
27 | top: 0;
28 | right: 0;
29 | bottom: 0;
30 | left: 0;
31 | transition: opacity .3s
32 | }
33 | .element-helper-move-mask {
34 | display: none;
35 | background-color: hsla(0,0%,100%,0);
36 | }
37 |
38 | .element-helper-loading-mask.is-fullscreen {
39 | position: fixed
40 | }
41 |
42 | .element-helper-loading-mask.is-fullscreen .element-helper-loading-spinner {
43 | margin-top: -25px
44 | }
45 |
46 | .element-helper-loading-mask.is-fullscreen .element-helper-loading-spinner .circular {
47 | width: 50px;
48 | height: 50px
49 | }
50 |
51 | .element-helper-loading-spinner {
52 | top: 50%;
53 | margin-top: -21px;
54 | width: 100%;
55 | text-align: center;
56 | position: absolute
57 | }
58 |
59 | .element-helper-loading-spinner .element-helper-loading-text {
60 | color: #20a0ff;
61 | margin: 3px 0;
62 | font-size: 14px
63 | }
64 |
65 | .element-helper-loading-spinner .circular {
66 | width: 42px;
67 | height: 42px;
68 | animation: loading-rotate 2s linear infinite
69 | }
70 |
71 | .element-helper-loading-spinner .path {
72 | animation: loading-dash 1.5s ease-in-out infinite;
73 | stroke-dasharray: 90,150;
74 | stroke-dashoffset: 0;
75 | stroke-width: 2;
76 | stroke: #20a0ff;
77 | stroke-linecap: round
78 | }
79 |
80 | .element-helper-loading-fade-enter,.element-helper-loading-fade-leave-active {
81 | opacity: 0
82 | }
83 |
84 | @keyframes loading-rotate {
85 | to {
86 | transform: rotate(1turn)
87 | }
88 | }
89 |
90 | @keyframes loading-dash {
91 | 0% {
92 | stroke-dasharray: 1,200;
93 | stroke-dashoffset: 0
94 | }
95 |
96 | 50% {
97 | stroke-dasharray: 90,150;
98 | stroke-dashoffset: -40px
99 | }
100 |
101 | to {
102 | stroke-dasharray: 90,150;
103 | stroke-dashoffset: -120px
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Element-Helper
2 |
3 | > Element-Helper is a Atom package for Element-UI, if you use VSCode editor, please go to [VSCode VERSION](https://marketplace.visualstudio.com/items?itemName=ElemeFE.vscode-element-helper)
4 |
5 | Element-UI is a great library. More and more projects use it. So, For helping developer write by Element-UI more efficient, Element-Helper is born.
6 |
7 | ## Feature
8 |
9 | * Document
10 |
11 | * Autocomplete
12 |
13 | * Snippets
14 |
15 |
16 | ## Document
17 |
18 | ### Usage
19 |
20 | 1 - Move cursor to Element-UI tag or select it
21 |
22 | 2 - Press default hot key `ctrl + cmd + z`
23 |
24 | 3 - Select tag you want to search
25 |
26 | 4 - Enter and trigger document browser
27 |
28 | 
29 |
30 | ### Version and Language Switching
31 |
32 | 1 - Enter `Atom` -> `Preferences`
33 |
34 | 2 - Enter `Packages` and search Element-Helper package
35 |
36 | 3 - Enter `Setting`
37 |
38 | 4 - Switch version and language
39 |
40 | ### Auto Update Mechanism
41 |
42 | Document is off-line and auto synchronize with Element-UI official site.
43 |
44 | ### Keymap
45 |
46 | Default hot key is `ctrl + cmd + z`. If it has conflicted with other software's hot key. You can customize it.
47 |
48 | 1 - Enter `Atom` -> `Keymap`
49 |
50 | 2 - Customize your config. like
51 |
52 | ```
53 | "atom-workspace":
54 | "ctrl-alt-z": "element-helper:search-under-cursor"
55 | ```
56 |
57 |
58 | ## Autocomplete
59 |
60 | 
61 |
62 | * Distinguish and auto complete property and method for every Element-UI tag
63 |
64 | * Prompt value when value is some special type like Boolean or ICON.
65 |
66 |
67 | ## Snippets
68 |
69 | 
70 |
71 | Support snippets list:
72 |
73 | * `msg`
74 |
75 | ```
76 | this.$message({
77 | message: '',
78 | type: ''
79 | })
80 | ```
81 |
82 | * `alert`
83 |
84 | ```
85 | this.$alert('', '', {
86 | confirmButtonText: '',
87 | callback: () => {}
88 | });
89 | ```
90 |
91 | * `confirm`
92 |
93 | ```
94 | this.$confirm('', '', {
95 | confirmButtonText: '',
96 | cancelButtonText: '',
97 | type: ''
98 | }).then(() => {})
99 | .catch(() => {});
100 | ```
101 |
102 | * `prompt`
103 |
104 | ```
105 | this.$prompt('', '', {
106 | confirmButtonText: '',
107 | cancelButtonText: '',
108 | inputPattern: //,
109 | inputErrorMessage: ''
110 | }).then(({ value }) => {})
111 | .catch(() => {});
112 | ```
113 |
114 | * `msgb`
115 |
116 | ```
117 | this.$msgbox({
118 | title: '',
119 | message: '',
120 | showCancelButton: '',
121 | confirmButtonText: '',
122 | cancelButtonText: '',
123 | beforeClose: (action, instance, done) => {}
124 | }).then(action => {});
125 | ```
126 |
127 | * `notify`
128 |
129 | ```
130 | this.$notify({
131 | title: '',
132 | message: ''
133 | });
134 | ```
135 |
136 | ## Contribution
137 |
138 | Your pull request will make Element-Helper better.
139 |
140 | ## LICENSE
141 |
142 | MIT
143 |
--------------------------------------------------------------------------------
/lib/resource.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import { File } from 'atom';
4 | import Path from 'path';
5 | import Mkdirp from 'mkdirp';
6 | import cheerio from "cheerio";
7 | import { http as Http } from "follow-redirects";
8 | import Fs from 'fs';
9 |
10 | class Resource {
11 | // resources local path
12 | static RESOURCE_PATH = Path.join(__dirname, '..', 'resources');
13 | static ELEMENT_PATH = Path.join(__dirname, '..', 'node_modules', 'element-gh-pages');
14 | static URL_REG = /((?:src|href)\s*=\s*)(['"])(\/\/[^'"]*)\2/g;
15 | static ELEMENT_VERSION_URL = 'http://element.eleme.io/versions.json';
16 | static ELEMENT_HOME_URL = 'http://element.eleme.io/';
17 | static RESOURCE_REPO = 'repos.json';
18 |
19 | static get(filename) {
20 |
21 | return new File(filename).read()
22 | .then(result => result ? result : Promise.reject('ReadFail'));
23 | }
24 |
25 | static getFromUrl(url, filename) {
26 | return new Promise((resolve, reject) => {
27 | Http.get(url, response => {
28 | response.on('error', reject);
29 | let buffer = '';
30 | response.on('data', chunk => { buffer += chunk; });
31 | response.on('end', () => { resolve(buffer); });
32 | }).on('error', reject);
33 | }).then(result => {
34 | if (filename) {
35 | Mkdirp(Path.dirname(filename));
36 | new File(filename).write(result);
37 | }
38 | return result;
39 | }).catch(error => console.log(error));
40 | }
41 |
42 | static fixResource(file, vs) {
43 | const htmlPath = Path.join(Resource.ELEMENT_PATH, file);
44 | Resource.get(htmlPath)
45 | .then(content => {
46 | const matched = [];
47 | content = content.replace(Resource.URL_REG, (match, one, two, three)=> {
48 | const name = Path.basename(three);
49 | const url = `http:${three}`;
50 | Resource.getFromUrl(url, Path.join(Path.dirname(htmlPath), name)).catch(error =>{
51 | // one more again
52 | Resource.getFromUrl(url, Path.join(Path.dirname(htmlPath), name));
53 | });
54 | return `${one}${two}${name}${two}`;
55 | });
56 |
57 | let $ = cheerio.load(content);
58 |
59 | const jqScript = $(``);
60 | const fixScript = $(``);
61 | const style = $(``);
62 | $('body').append(jqScript).append(fixScript);
63 | $('head').append(style);
64 |
65 | const indexPath = Path.join(Resource.ELEMENT_PATH, file);
66 | const dir = Path.dirname(indexPath);
67 | new File(Path.join(dir, 'main.html')).write($.html());
68 | return content;
69 | });
70 | }
71 |
72 | static updateResource() {
73 | Fs.readdir(Resource.ELEMENT_PATH, (err, files) => {
74 | if (err) {
75 | return;
76 | }
77 |
78 | for(let i = 0; i < files.length; ++i) {
79 | const status = Fs.lstatSync(Path.join(Resource.ELEMENT_PATH, files[i]));
80 | if (status.isFile() && /index.html$/.test(files[i])) { // index.html entry
81 | Resource.fixResource(files[i], 1);
82 | } else if (status.isDirectory() && /^\d+\./.test(files[i])) { // version directory
83 | Resource.fixResource(Path.join(files[i], 'index.html'), files[i].split('.')[0] || 1);
84 | } else {
85 | continue;
86 | }
87 | }
88 | });
89 | }
90 | }
91 |
92 | export default Resource;
93 |
--------------------------------------------------------------------------------
/lib/library.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import { File } from 'atom';
4 | import Path from 'path';
5 | import DocSet from './docset';
6 | import Resource from './resource';
7 | import { exec, cd } from 'shelljs';
8 | const fs = require('fs');
9 |
10 | class Library {
11 | static REFRESH_PERIOD_MS_ = 6 * 60 * 60 * 1000;
12 | static DEFAULT_DOCSETS = new Set([
13 | 'element'
14 | ]);
15 |
16 | constructor() {
17 | this.catalog = null;
18 | this.fetchRepo();
19 | this.cmd = '';
20 | setInterval(() => { this.fetchAllVersion(this.repos); }, Library.REFRESH_PERIOD_MS_);
21 | }
22 |
23 | // id: type
24 | get(id) {
25 | return this.catalog[id];
26 | }
27 |
28 | queryAll() {
29 | let ret = [];
30 | for (const id in this.catalog) {
31 | ret = ret.concat(this.catalog[id].queryAll());
32 | }
33 | return ret;
34 | }
35 |
36 | fetchRepo() {
37 | return Resource.get(Path.join(Resource.RESOURCE_PATH, Resource.RESOURCE_REPO))
38 | .then(result => {
39 | this.repos = JSON.parse(result)
40 | this.buildCatalog(this.repos);
41 | this.fetchAllVersion(this.repos);
42 | }).catch(error => {
43 | console.log('fetchRepo error: ', error);
44 | });
45 | }
46 |
47 | fetchAllVersion(repos) {
48 | cd(`${Resource.RESOURCE_PATH}/..`);
49 | exec('npm update element-helper-json --save', { async: true });
50 | for (let i = 0; i < repos.length; ++i) {
51 | let repo = repos[i];
52 | this.fetchVersion(repo);
53 | }
54 | }
55 |
56 | setVersionSchema(versions, repo) {
57 | const versionSchema = {
58 | title: `${repo.name} Version`,
59 | description: `Document version of ${repo.name}.`,
60 | type: 'string',
61 | default: versions[versions.length -1],
62 | enum: versions,
63 | order: 1
64 | };
65 | atom.config.setSchema(`element-helper.${repo.type}_version`, versionSchema);
66 | }
67 |
68 | fetchVersion(repo) {
69 | Resource.get(Path.join(Resource.ELEMENT_PATH, 'versions.json')).then(local => {
70 | Resource.getFromUrl(Resource.ELEMENT_VERSION_URL)
71 | .then(online => {
72 | const oldVersions = this.getValues(JSON.parse(local));
73 | const newVersions = this.getValues(JSON.parse(online));
74 | if (!this.isSame(JSON.parse(local), JSON.parse(online))) {
75 | cd(`${Resource.RESOURCE_PATH}/..`);
76 | exec('npm update element-gh-pages --save', (error, stdout, stderr) => {
77 | if (error) {
78 | return;
79 | }
80 | const versionsStr = fs.readFileSync(Path.join(Resource.ELEMENT_PATH, 'versions.json'), 'utf8');
81 | if (!this.isSame(JSON.parse(local), JSON.parse(versionsStr))) {
82 | this.setVersionSchema(newVersions, repo);
83 | atom.notifications.addInfo(`${repo.name} version updated to lasted version`, {
84 | dismissable: true
85 | });
86 | } else {
87 | this.setVersionSchema(oldVersions, repo);
88 | }
89 | Resource.updateResource();
90 | });
91 | } else {
92 | this.setVersionSchema(oldVersions, repo);
93 | if (!fs.existsSync(Path.join(Resource.ELEMENT_PATH, 'main.html'))) {
94 | Resource.updateResource();
95 | }
96 | }
97 | });
98 | });
99 | }
100 |
101 | isSame(local, online) {
102 | for (let key in online) {
103 | if (!local[key]) {
104 | return false;
105 | }
106 | }
107 | return true;
108 | }
109 |
110 | getValues(obj) {
111 | let values = [];
112 | for (let key in obj) {
113 | values.push(obj[key]);
114 | }
115 | return values;
116 | }
117 |
118 | buildCatalog(repos) {
119 | const catalog = {};
120 |
121 | for (let i = 0; i < repos.length; ++i) {
122 | const repo = repos[i];
123 | catalog[repo.type] = new DocSet(repo);
124 | }
125 |
126 | for (let i = 0; i < repos.length; ++i) {
127 | const repo = repos[i];
128 |
129 | let title = repo.name;
130 | if ('version' in repo && repo.version) {
131 | title += ' ' + repo.version;
132 | }
133 |
134 | let schema = {
135 | title: title,
136 | type: 'boolean',
137 | default: Library.DEFAULT_DOCSETS.has(repo.type)
138 | };
139 | atom.config.setSchema(`element-helper.${repo.type}`, schema);
140 | }
141 |
142 | this.catalog = catalog;
143 | }
144 | }
145 |
146 | export default Library;
147 |
--------------------------------------------------------------------------------
/lib/document-view.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import { ScrollView } from 'atom-space-pen-views';
4 | import { Emitter, Disposable } from 'atom';
5 | import $ from 'jquery';
6 | import Url from 'url';
7 | import Resource from './resource';
8 | import Path from 'path';
9 |
10 | class DocView extends ScrollView {
11 | static DOC_STYLE = "";
12 |
13 | static content() {
14 | return this.div({class: 'element-helper-docs-container native-key-bindings', tabindex: -1});
15 | }
16 |
17 | constructor(library, url) {
18 | super();
19 | this.emitter_ = new Emitter();
20 | this.title_ = 'Loading...';
21 | this.library_ = library;
22 | this.url_ = url;
23 | this.pane_ = null;
24 | this.stylePromise = Resource.get(Path.join(Resource.RESOURCE_PATH, 'style.css')).then(result => DocView.DOC_STYLE = result);
25 | this.version_ = atom.config.get('element-helper.element_version');
26 | this.language_ = atom.config.get('element-helper.language');
27 | }
28 |
29 | setView(url) {
30 | this.stylePromise.then(() => {
31 | const parsedUrl = Url.parse(url, true);
32 | const versions = atom.config.getSchema('element-helper.element_version').enum;
33 | const docset = this.library_.get(parsedUrl.hostname);
34 | const path = url.split('/').pop();
35 | const componentPath = `${this.version_}/main.html#/${this.language_}/component/${path}`;
36 | const href = Resource.ELEMENT_HOME_URL + componentPath.replace('main.html', 'index.html');
37 | const iframeSrc = 'file://' + Path.join(Resource.ELEMENT_PATH, componentPath).split(Path.sep).join('/');
38 |
39 | let opts = ['');
46 | const html = opts.join('');
47 |
48 | const notice = ({
49 | 'zh-CN': `版本:${html},在线示例请在浏览器中查看`,
50 | 'en-US': `Version: ${html}, view online examples in browser`
51 | })[this.language_];
52 | $(this.element).html(`${notice}
`);
53 |
54 | let iframe = $('.element-helper-docs-container #docs-frame');
55 | let link = $('.element-helper-docs-container .docs-notice a');
56 | window.addEventListener('message', (e) => {
57 | e.data.loaded && $('.element-helper-loading-mask').css('display', 'none');
58 | if (e.data.title) {
59 | this.title_ = e.data.title;
60 | this.emitter_.emit('did-change-title');
61 | }
62 | if (e.data.hash) {
63 | let pathArr = link.attr('href').split('#');
64 | pathArr.pop();
65 | pathArr.push(e.data.hash);
66 | link.attr('href', pathArr.join('#'));
67 | let srcArr = iframe.attr('src').split('#');
68 | srcArr.pop();
69 | srcArr.push(e.data.hash);
70 | iframe.attr('src', srcArr.join('#'));
71 | }
72 | }, false);
73 | $('.element-helper-docs-container .docs-version').on('change', () => {
74 | var version = $('.element-helper-docs-container .docs-version').val();
75 | var originalSrc = iframe.attr('src');
76 | var arr = originalSrc.split(new RegExp('/?[0-9.]*/main.html'));
77 | if(this.version_ === version) {
78 | iframe.attr('src', arr.join('/main.html'));
79 | link.attr('href', link.attr('href').replace(new RegExp('/?[0-9.]*/index.html'), '/index.html'));
80 | } else {
81 | iframe.attr('src', arr.join('/' + version + '/main.html'));
82 | link.attr('href', link.attr('href').replace(new RegExp('/?[0-9.]*/index.html'), '/' + version + '/index.html'));
83 | }
84 | });
85 | this.title_ = docset.getTitle(path);
86 | this.emitter_.emit('did-change-title');
87 | });
88 | }
89 |
90 | onDidChangeTitle(callback) {
91 | return this.emitter_.on('did-change-title', callback);
92 | }
93 |
94 | onDidChangeModified() {
95 | return new Disposable();
96 | }
97 |
98 | destroy() {
99 | this.pane_.destroyItem(this);
100 | if (this.pane_.getItems().length === 0) {
101 | this.pane_.destroy();
102 | }
103 | }
104 |
105 | attached() {
106 | this.pane_ = atom.workspace.paneForURI(this.getURI());
107 | this.pane_.activateItem(this);
108 | let timer = null;
109 | // resolve block problem
110 | this.pane_.onDidChangeFlexScale(f => {
111 | $('.element-helper-move-mask').css('display', 'block');
112 | clearTimeout(timer);
113 | timer = setTimeout(() => {
114 | $('.element-helper-move-mask').css('display', 'none');
115 | }, 500);
116 | });
117 | }
118 |
119 | getURI() {
120 | return this.url_;
121 | }
122 |
123 | getTitle() {
124 | return this.title_;
125 | }
126 | }
127 |
128 | export default DocView;
129 |
--------------------------------------------------------------------------------
/lib/provider.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 |
3 | import prettyHTML from 'pretty';
4 | import * as TAGS from 'element-helper-json/element-tags.json';
5 | import * as ATTRS from 'element-helper-json/element-attributes.json';
6 |
7 | // https://github.com/atom/autocomplete-plus/wiki/Provider-API
8 | const provider = {
9 | selector: '.text.html',
10 | disableForSelector: '.text.html .comment',
11 | filterSuggestions: true,
12 | attrReg: /\s+[:@]*([a-zA-Z][-a-zA-Z]*)\s*=\s*$/,
13 | tagReg: /<([a-zA-Z][-a-zA-Z]*)(?:\s|$)/,
14 | bindReg: /\s+:$/,
15 | methodReg: /^\s+@$/,
16 |
17 | getSuggestions(request) {
18 | if (this.isAttrValueStart(request)) {
19 | return this.getAttrValueSuggestion(request);
20 | } else if (this.isAttrStart(request)) {
21 | return this.getAttrSuggestion(request);
22 | } else if (this.isTagStart(request)) {
23 | return this.getTagSuggestion(request);
24 | } else {
25 | return [];
26 | }
27 | },
28 | // called when a suggestion from your provider was inserted into the buffer
29 | onDidInsertSuggestion({editor, suggestion}) {
30 | (suggestion.type === 'property') && setTimeout(() => this.triggerAutocomplete(editor), 1);
31 | },
32 |
33 | triggerAutocomplete(editor) {
34 | atom.commands.dispatch(atom.views.getView(editor), 'autocomplete-plus:activate', {activatedManually: false});
35 | },
36 |
37 | isAttrStart({editor, scopeDescriptor, bufferPosition, prefix}) {
38 | const preTwoLetter = editor.getTextInBufferRange([[bufferPosition.row, bufferPosition.column - 2], bufferPosition]);
39 | const scopes = scopeDescriptor.getScopesArray();
40 | if (!this.getPreAttr(editor, bufferPosition) && ((prefix && !prefix.trim())|| this.bindReg.test(preTwoLetter) || this.methodReg.test(preTwoLetter))) {
41 | return this.hasTagScope(scopes);
42 | }
43 |
44 | const preBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)];
45 | const preScopeDescriptor = editor.scopeDescriptorForBufferPosition(preBufferPosition);
46 | const preScopes = preScopeDescriptor.getScopesArray();
47 |
48 | if (preScopes.includes('entity.other.attribute-name.html')) {
49 | return true;
50 | }
51 | if (!this.hasTagScope(scopes) || !prefix) {
52 | return false;
53 | }
54 | return (scopes.includes('punctuation.definition.tag.end.html') &&
55 | !preScopes.includes('punctuation.definition.tag.end.html'));
56 | },
57 |
58 | isAttrValueStart({scopeDescriptor, bufferPosition, editor}) {
59 | const scopes = scopeDescriptor.getScopesArray();
60 |
61 | const preBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)];
62 | const preScopeDescriptor = editor.scopeDescriptorForBufferPosition(preBufferPosition);
63 | const preScopes = preScopeDescriptor.getScopesArray();
64 |
65 | return (this.hasStringScope(scopes) &&
66 | this.hasStringScope(preScopes) &&
67 | !preScopes.includes('punctuation.definition.string.end.html') &&
68 | this.hasTagScope(scopes) &&
69 | this.getPreAttr(editor, bufferPosition)
70 | );
71 | },
72 |
73 | isTagStart({editor, bufferPosition, scopeDescriptor, prefix}) {
74 | if (prefix.trim() && !prefix.includes('<')) {
75 | return this.hasTagScope(scopeDescriptor.getScopesArray());
76 | }
77 | // autocomplete-plus's default prefix setting does not capture <. Manually check for it.
78 | prefix = editor.getTextInBufferRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition]);
79 | const scopes = scopeDescriptor.getScopesArray();
80 |
81 | return (prefix === '<' &&
82 | ((scopes.includes('text.html.basic') && scopes.length === 1) ||
83 | (scopes.includes('text.html.vue') && scopes.includes('invalid.illegal.bad-angle-bracket.html'))));
84 | },
85 |
86 | getPreAttr(editor, bufferPosition) {
87 | let quoteIndex = bufferPosition.column - 1;
88 | let preScopeDescriptor = null;
89 | let scopes = null;
90 | while (quoteIndex) {
91 | preScopeDescriptor = editor.scopeDescriptorForBufferPosition([bufferPosition.row, quoteIndex]);
92 | scopes = preScopeDescriptor.getScopesArray();
93 | if (!this.hasStringScope(scopes) || scopes.includes('punctuation.definition.string.begin.html')) {
94 | break;
95 | }
96 | quoteIndex--;
97 | }
98 | let attr = this.attrReg.exec(editor.getTextInRange([[bufferPosition.row, 0], [bufferPosition.row, quoteIndex]]));
99 | return attr && attr[1];
100 | },
101 |
102 | getPreTag(editor, bufferPosition) {
103 | let row = bufferPosition.row;
104 | let tag = null;
105 | while (row) {
106 | tag = this.tagReg.exec(editor.lineTextForBufferRow(row));
107 | if (tag && tag[1]) {
108 | return tag[1];
109 | }
110 | row--;
111 | }
112 | return;
113 | },
114 |
115 | getAttrValues(tag, attr) {
116 | let attrItem = this.getAttrItem(tag, attr);
117 | let options = attrItem && attrItem.options;
118 | if (!options && attrItem) {
119 | if (attrItem.type === 'boolean') {
120 | options = ['true', 'false'];
121 | } else if (attrItem.type === 'icon') {
122 | options = ATTRS['icons'];
123 | } else if (attrItem.type === 'shortcut-icon') {
124 | options = [];
125 | ATTRS['icons'].forEach(icon => {
126 | options.push(icon.replace(/^el-icon-/, ''));
127 | });
128 | }
129 | }
130 | return options || [];
131 | },
132 |
133 | getTagAttrs(tag) {
134 | return (TAGS[tag] && TAGS[tag].attributes) || [];
135 | },
136 |
137 | getTagSuggestion({editor, bufferPosition, prefix}) {
138 | const preLetter = editor.getTextInBufferRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition]);
139 | const suggestions = [];
140 | for (let tag in TAGS) {
141 | if (preLetter === '<' || this.firstCharsEqual(tag, prefix)) {
142 | suggestions.push(this.buildTagSuggestion(tag, TAGS[tag]));
143 | }
144 | }
145 | return suggestions;
146 | },
147 |
148 | getAttrSuggestion({editor, bufferPosition, prefix}) {
149 | const suggestions = [];
150 | const tag = this.getPreTag(editor, bufferPosition);
151 | const tagAttrs = this.getTagAttrs(tag);
152 | const preText = editor.getTextInBufferRange([[bufferPosition.row, 0], bufferPosition]);
153 |
154 | // method attribute
155 | const method = preText.split(/\s+/).pop()[0] === '@';
156 | // bind attribute
157 | const bind = preText.split(/\s+/).pop()[0] === ':';
158 |
159 | tagAttrs.forEach(attr => {
160 | // autocomplete-plus会忽略@和<符号
161 | // 属性存在 and 为空 or 绑定元素(' :') or 首字母相等
162 | const attrItem = this.getAttrItem(tag, attr);
163 | if (attrItem && (!prefix.trim() || this.bindReg.test(prefix) || this.firstCharsEqual(attr, prefix))) {
164 | const sug = this.buildAttrSuggestion({attr, tag, bind, method}, attrItem);
165 | sug && suggestions.push(sug);
166 | }
167 | });
168 | for (let attr in ATTRS) {
169 | const attrItem = this.getAttrItem(tag, attr);
170 | if (attrItem && attrItem.global && (!prefix.trim() || this.bindReg.test(prefix) || this.firstCharsEqual(attr, prefix))) {
171 | const sug = this.buildAttrSuggestion({attr, bind, method}, attrItem);
172 | sug && suggestions.push(sug);
173 | }
174 | }
175 | return suggestions;
176 | },
177 |
178 | getAttrValueSuggestion({editor, bufferPosition, prefix}) {
179 | const suggestions = [];
180 | const tag = this.getPreTag(editor, bufferPosition);
181 | const attr = this.getPreAttr(editor, bufferPosition);
182 | const values = this.getAttrValues(tag, attr);
183 | values.forEach(value => {
184 | if (this.firstCharsEqual(value, prefix) || !prefix) {
185 | suggestions.push(this.buildAttrValueSuggestion(tag, attr, value));
186 | }
187 | });
188 |
189 | return suggestions;
190 | },
191 |
192 | buildAttrSuggestion({attr, tag, bind, method}, {description, type}) {
193 | const attrItem = this.getAttrItem(tag, attr);
194 | if ((method && attrItem.type === "method") || (bind && attrItem.type !== "method") || (!method && !bind)) {
195 | return {
196 | snippet: (type && (type === 'flag')) ? `${attr} ` : `${attr}=\"$1\"$0`,
197 | displayText: attr,
198 | type: (type && (type === 'method')) ? 'method' : 'property',
199 | description: description,
200 | rightLabel: tag ? `<${tag}>` : 'element-ui'
201 | };
202 | } else { return; }
203 | },
204 |
205 | buildAttrValueSuggestion(tag, attr, value) {;
206 | const attrItem = this.getAttrItem(tag, attr)
207 | return {
208 | text: value,
209 | type: 'value',
210 | description: attrItem.description,
211 | rightLabel: attrItem.global ? 'element-ui' : `<${tag}>`
212 | };
213 | },
214 |
215 | buildTagSuggestion(tag, tagVal) {
216 | const snippets = [];
217 | let index = 0;
218 | function build(tag, {subtags, defaults}, snippets) {
219 | let attrs = '';
220 | defaults && defaults.forEach((item,i) => {
221 | attrs +=` ${item}="$${index + i + 1}"`;
222 | });
223 | snippets.push(`${index > 0 ? '<':''}${tag}${attrs}>`);
224 | index++;
225 | subtags && subtags.forEach(item => build(item, TAGS[item], snippets));
226 | snippets.push(`${tag}>`);
227 | };
228 | build(tag, tagVal, snippets);
229 |
230 | return {
231 | displayText: tag,
232 | snippet: prettyHTML('<' + snippets.join('')).substr(1),
233 | type: 'tag',
234 | rightLabel: 'element-ui',
235 | description: tagVal.description
236 | };
237 | },
238 |
239 | //two types: double and single quote
240 | hasStringScope(scopes) {
241 | return (scopes.includes('string.quoted.double.html') ||
242 | scopes.includes('string.quoted.single.html'));
243 | },
244 |
245 | hasTagScope(scopes) {
246 | return (scopes.includes('meta.tag.any.html') ||
247 | scopes.includes('meta.tag.other.html') ||
248 | scopes.includes('meta.tag.block.any.html') ||
249 | scopes.includes('meta.tag.inline.any.html') ||
250 | scopes.includes('meta.tag.structure.any.html'));
251 | },
252 |
253 | firstCharsEqual(str1, str2) {
254 | if (str2 && str1) {
255 | return str1[0].toLowerCase() === str2[0].toLowerCase();
256 | }
257 | return false;
258 | },
259 |
260 | getAttrItem(tag, attr) {
261 | return ATTRS[`${tag}/${attr}`] || ATTRS[attr];
262 | }
263 |
264 | };
265 |
266 | export default provider;
267 |
--------------------------------------------------------------------------------
/resources/element/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "entries": [
3 | {
4 | "type": "basic",
5 | "name": "Layout 布局",
6 | "path": "layout",
7 | "tag": "el-row",
8 | "description": "el-row,Layout 布局"
9 | },
10 | {
11 | "type": "basic",
12 | "name": "Layout 布局",
13 | "path": "layout",
14 | "tag": "el-col",
15 | "description": "el-col,Layout 布局"
16 | },
17 | {
18 | "type": "basic",
19 | "name": "Color 色彩",
20 | "path": "color",
21 | "tag": "color",
22 | "description": "color,Color 色彩"
23 | },
24 | {
25 | "type": "basic",
26 | "name": "Typography 字体",
27 | "path": "typography",
28 | "tag": "typography",
29 | "description": "typography,Typography 字体"
30 | },
31 | {
32 | "type": "basic",
33 | "name": "Icon 图标",
34 | "path": "icon",
35 | "tag": "icon",
36 | "description": "icon,Icon 图标"
37 | },
38 | {
39 | "type": "basic",
40 | "name": "Button 按钮",
41 | "path": "button",
42 | "tag": "el-button",
43 | "description": "el-button,Button 按钮"
44 | },
45 | {
46 | "type": "form",
47 | "name": "Radio 单选框组",
48 | "path": "radio",
49 | "tag": "el-radio",
50 | "description": "el-radio,Radio 单选框"
51 | },
52 | {
53 | "type": "form",
54 | "name": "Radio 单选框组",
55 | "path": "radio",
56 | "tag": "el-radio-group",
57 | "description": "el-radio-group,Radio 单选框组"
58 | },
59 | {
60 | "type": "form",
61 | "name": "Checkbox 多选框",
62 | "path": "checkbox",
63 | "tag": "el-checkbox",
64 | "description": "el-checkbox,Checkbox 多选框"
65 | },
66 | {
67 | "type": "form",
68 | "name": "Checkbox 多选框",
69 | "path": "checkbox",
70 | "tag": "el-checkbox-group",
71 | "description": "el-checkbox-group,Checkbox 多选框"
72 | },
73 | {
74 | "type": "form",
75 | "name": "Input 输入框",
76 | "path": "input",
77 | "tag": "el-input",
78 | "description": "el-input,Input 输入框"
79 | },
80 | {
81 | "type": "form",
82 | "name": "Input 输入框",
83 | "path": "input",
84 | "tag": "el-autocomplete",
85 | "description": "el-autocomplete,Input 输入框"
86 | },
87 | {
88 | "type": "form",
89 | "name": "InputNumber 计数器",
90 | "path": "input-number",
91 | "tag": "el-input-number",
92 | "description": "el-input-number,InputNumber 计数器"
93 | },
94 | {
95 | "type": "form",
96 | "name": "Select 选择器",
97 | "path": "select",
98 | "tag": "el-select",
99 | "description": "el-select,Select 选择器"
100 | },
101 | {
102 | "type": "form",
103 | "name": "Select 选择器",
104 | "path": "select",
105 | "tag": "el-option",
106 | "description": "el-option,Select 选择器"
107 | },
108 | {
109 | "type": "form",
110 | "name": "Select 选择器",
111 | "path": "select",
112 | "tag": "el-option-group",
113 | "description": "el-option-group,Select 选择器"
114 | },
115 | {
116 | "type": "form",
117 | "name": "Cascader 级联选择器",
118 | "path": "cascader",
119 | "tag": "el-cascader",
120 | "description": "el-cascader,Cascader 级联选择器"
121 | },
122 | {
123 | "type": "form",
124 | "name": "Switch 开关",
125 | "path": "switch",
126 | "tag": "el-switch",
127 | "description": "el-switch,Switch 开关"
128 | },
129 | {
130 | "type": "form",
131 | "name": "Slider 滑块",
132 | "path": "slider",
133 | "tag": "el-slider",
134 | "description": "el-slider,Slider 滑块"
135 | },
136 | {
137 | "type": "form",
138 | "name": "TimerPicker 时间选择器",
139 | "path": "time-picker",
140 | "tag": "el-time-picker",
141 | "description": "el-time-picker,TimerPicker 时间选择器"
142 | },
143 | {
144 | "type": "form",
145 | "name": "TimerPicker 时间选择器",
146 | "path": "time-picker",
147 | "tag": "el-time-select",
148 | "description": "el-time-select,TimerPicker 时间选择器"
149 | },
150 | {
151 | "type": "form",
152 | "name": "DatePicker 日期选择器",
153 | "path": "date-picker",
154 | "tag": "el-date-picker",
155 | "description": "el-date-picker,DatePicker 日期选择器"
156 | },
157 | {
158 | "type": "form",
159 | "name": "DateTimePicker 日期时间选择器",
160 | "path": "datetime-picker",
161 | "tag": "el-datetime-picker",
162 | "description": "el-datetime-picker,DateTimePicker 日期时间选择器"
163 | },
164 | {
165 | "type": "form",
166 | "name": "Upload 上传",
167 | "path": "upload",
168 | "tag": "el-upload",
169 | "description": "el-upload,Upload 上传"
170 | },
171 | {
172 | "type": "form",
173 | "name": "Rate 评分",
174 | "path": "rate",
175 | "tag": "el-rate",
176 | "description": "el-rate,Rate 评分"
177 | },
178 | {
179 | "type": "form",
180 | "name": "ColorPicker 颜色选择器",
181 | "path": "color-picker",
182 | "tag": "el-color-picker",
183 | "description": "el-color-picker,ColorPicker 颜色选择器"
184 | },
185 | {
186 | "type": "form",
187 | "name": "ransfer 穿梭框",
188 | "path": "transfer",
189 | "tag": "el-transfer",
190 | "description": "el-transfer,ransfer 穿梭框"
191 | },
192 | {
193 | "type": "form",
194 | "name": "Form 表单",
195 | "path": "form",
196 | "tag": "el-form",
197 | "description": "el-form,Form 表单"
198 | },
199 | {
200 | "type": "form",
201 | "name": "Form 表单",
202 | "path": "form",
203 | "tag": "el-form-item",
204 | "description": "el-form-item,Form 表单"
205 | },
206 | {
207 | "type": "data",
208 | "name": "Table 表格",
209 | "path": "table",
210 | "tag": "el-table",
211 | "description": "el-table,Table 表格"
212 | },
213 | {
214 | "type": "data",
215 | "name": "Table 表格",
216 | "path": "table",
217 | "tag": "el-table-column",
218 | "description": "el-table-column,Table 表格"
219 | },
220 | {
221 | "type": "data",
222 | "name": "Tag 标签",
223 | "path": "tag",
224 | "tag": "el-tag",
225 | "description": "el-tag,Tag 标签"
226 | },
227 | {
228 | "type": "data",
229 | "name": "Progress 进度条",
230 | "path": "progress",
231 | "tag": "el-progress",
232 | "description": "el-progress,Progress 进度条"
233 | },
234 | {
235 | "type": "data",
236 | "name": "Tree 树形控件",
237 | "path": "tree",
238 | "tag": "el-tree",
239 | "description": "el-tree,Tree 树形控件"
240 | },
241 | {
242 | "type": "data",
243 | "name": "Pagination 分页",
244 | "path": "pagination",
245 | "tag": "el-pagination",
246 | "description": "el-pagination,Pagination 分页"
247 | },
248 | {
249 | "type": "data",
250 | "name": "Badge 标记",
251 | "path": "badge",
252 | "tag": "el-badge",
253 | "description": "el-badge,Badge 标记"
254 | },
255 | {
256 | "type": "notice",
257 | "name": "Alert 警告",
258 | "path": "alert",
259 | "tag": "el-alert",
260 | "description": "el-alert,Alert 警告"
261 | },
262 | {
263 | "type": "notice",
264 | "name": "Loading 加载",
265 | "path": "loading",
266 | "tag": "v-loading",
267 | "description": "v-loading,Loading 加载"
268 | },
269 | {
270 | "type": "notice",
271 | "name": "Message 消息提示",
272 | "path": "message",
273 | "tag": "$message",
274 | "description": "$message,Message 消息提示"
275 | },
276 | {
277 | "type": "notice",
278 | "name": "MessageBox 弹框",
279 | "path": "message-box",
280 | "tag": "$alert",
281 | "description": "$alert,MessageBox 弹框"
282 | },
283 | {
284 | "type": "notice",
285 | "name": "MessageBox 弹框",
286 | "path": "message-box",
287 | "tag": "$prompt",
288 | "description": "$prompt,MessageBox 弹框"
289 | },
290 | {
291 | "type": "notice",
292 | "name": "MessageBox 弹框",
293 | "path": "message-box",
294 | "tag": "$msgbox",
295 | "description": "$msgbox,MessageBox 弹框"
296 | },
297 | {
298 | "type": "notice",
299 | "name": "Notification 通知",
300 | "path": "notification",
301 | "tag": "$notify",
302 | "description": "$notify,Notification 通知"
303 | },
304 | {
305 | "type": "navigation",
306 | "name": "NavMenu 导航菜单",
307 | "path": "menu",
308 | "tag": "el-menu",
309 | "description": "el-menu,NavMenu 导航菜单"
310 | },
311 | {
312 | "type": "navigation",
313 | "name": "NavMenu 导航菜单",
314 | "path": "menu",
315 | "tag": "el-submenu",
316 | "description": "el-submenu,NavMenu 导航菜单"
317 | },
318 | {
319 | "type": "navigation",
320 | "name": "NavMenu 导航菜单",
321 | "path": "menu",
322 | "tag": "el-menu-item",
323 | "description": "el-menu-item,NavMenu 导航菜单"
324 | },
325 | {
326 | "type": "navigation",
327 | "name": "Tabs 标签页",
328 | "path": "tabs",
329 | "tag": "el-tabs",
330 | "description": "el-tabs,Tabs 标签页"
331 | },
332 | {
333 | "type": "navigation",
334 | "name": "Tabs 标签页",
335 | "path": "tabs",
336 | "tag": "el-tab-pane",
337 | "description": "el-tab-pane,Tabs 标签页"
338 | },
339 | {
340 | "type": "navigation",
341 | "name": "Breadcrumb 面包屑",
342 | "path": "breadcrumb",
343 | "tag": "el-breadcrumb",
344 | "description": "el-breadcrumb,Breadcrumb 面包屑"
345 | },
346 | {
347 | "type": "navigation",
348 | "name": "Dropdown 下拉菜单",
349 | "path": "dropdown",
350 | "tag": "el-dropdown",
351 | "description": "el-dropdown,Dropdown 下拉菜单"
352 | },
353 | {
354 | "type": "navigation",
355 | "name": "Dropdown 下拉菜单",
356 | "path": "dropdown",
357 | "tag": "el-dropdown-menu",
358 | "description": "el-dropdown-menu,Dropdown 下拉菜单"
359 | },
360 | {
361 | "type": "navigation",
362 | "name": "Dropdown 下拉菜单",
363 | "path": "dropdown",
364 | "tag": "el-dropdown-item",
365 | "description": "el-dropdown-item,Dropdown 下拉菜单"
366 | },
367 | {
368 | "type": "navigation",
369 | "name": "Steps 步骤条",
370 | "path": "steps",
371 | "tag": "el-steps",
372 | "description": "el-steps,Steps 步骤条"
373 | },
374 | {
375 | "type": "others",
376 | "name": "Dialog 对话框",
377 | "path": "dialog",
378 | "tag": "el-dialog",
379 | "description": "el-dialog,Dialog 对话框"
380 | },
381 | {
382 | "type": "others",
383 | "name": "Tooltip 文字提示",
384 | "path": "tooltip",
385 | "tag": "el-tooltip",
386 | "description": "el-tooltip,Tooltip 文字提示"
387 | },
388 | {
389 | "type": "others",
390 | "name": "Popover 弹出框",
391 | "path": "popover",
392 | "tag": "el-popover",
393 | "description": "el-popover,Popover 弹出框"
394 | },
395 | {
396 | "type": "others",
397 | "name": "Card 卡片",
398 | "path": "card",
399 | "tag": "el-card",
400 | "description": "el-card,Card 卡片"
401 | },
402 | {
403 | "type": "others",
404 | "name": "Carousel 走马灯",
405 | "path": "carousel",
406 | "tag": "el-carousel",
407 | "description": "el-carousel,Carousel 走马灯"
408 | },
409 | {
410 | "type": "others",
411 | "name": "Carousel 走马灯",
412 | "path": "carousel",
413 | "tag": "el-carousel-item",
414 | "description": "el-carousel-item,Carousel 走马灯"
415 | },
416 | {
417 | "type": "others",
418 | "name": "Collapse 折叠面板",
419 | "path": "collapse",
420 | "tag": "el-collapse",
421 | "description": "el-collapse,Collapse 折叠面板"
422 | },
423 | {
424 | "type": "others",
425 | "name": "Collapse 折叠面板",
426 | "path": "collapse",
427 | "tag": "el-collapse-item",
428 | "description": "el-collapse-item,Collapse 折叠面板"
429 | }
430 | ],
431 | "types": [
432 | {"name": "basic"},
433 | {"name": "form"},
434 | {"name": "data"},
435 | {"name": "notice"},
436 | {"name": "navigation"},
437 | {"name": "others"}
438 | ]
439 | }
440 |
--------------------------------------------------------------------------------