1 | const ydoc = require('./ydoc.js');
|
2 | const path = require('path');
|
3 | const utils = require('./utils.js');
|
4 | const fs = require('fs-extra');
|
5 |
|
6 | let DEFAULT_PLUGINS = ['execution-time', 'import-asset', 'search'];
|
7 |
|
8 | const hooks = {}
|
9 |
|
10 | function addHook(arr){
|
11 | arr.forEach(hookname=> hooks[hookname] = {
|
12 | listener: []
|
13 | })
|
14 | }
|
15 |
|
16 | function addTplHook(arr){
|
17 | arr.forEach(hookname=> hooks[utils.defaultTplHookPrefix + hookname] = {
|
18 | listener: []
|
19 | })
|
20 | }
|
21 |
|
22 | addHook(["init","nav", "finish", "book:before", "book", "page:before", "page"])
|
23 | addTplHook(["header","mask"])
|
24 |
|
25 |
|
26 | function bindHook(name, listener) {
|
27 | if (!name) throw new Error(`Hookname ${name} is undefined.`);
|
28 | if (name in hooks === false) {
|
29 | throw new Error(`It is't exist hookname ${name}.`);
|
30 | }
|
31 | hooks[name].listener.push(listener);
|
32 | }
|
33 |
|
34 | exports.bindHook = bindHook;
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | exports.emitHook = function emitHook(name) {
|
42 | if (hooks[name] && typeof hooks[name] === 'object') {
|
43 | let args = Array.prototype.slice.call(arguments, 1);
|
44 | let promiseAll = [];
|
45 |
|
46 | if (Array.isArray(hooks[name].listener)) {
|
47 | let listenerList = hooks[name].listener;
|
48 | for (let i = 0, l = listenerList.length; i < l; i++) {
|
49 | let context = utils.extend({}, ydoc);
|
50 | context.options = listenerList[i].options;
|
51 | promiseAll.push(Promise.resolve(listenerList[i].fn.apply(context, args)));
|
52 | }
|
53 | }
|
54 | return Promise.all(promiseAll);
|
55 | }
|
56 | }
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | exports.emitTplHook = function emitHook(name) {
|
64 | let all = [];
|
65 | if (hooks[name] && typeof hooks[name] === 'object') {
|
66 | let args = Array.prototype.slice.call(arguments, 1);
|
67 |
|
68 | if (Array.isArray(hooks[name].listener)) {
|
69 | let listenerList = hooks[name].listener;
|
70 | for (let i = 0, l = listenerList.length; i < l; i++) {
|
71 | let context = utils.extend({}, ydoc);
|
72 | context.options = listenerList[i].options;
|
73 | all.push(listenerList[i].fn.apply(context, args));
|
74 | }
|
75 | }
|
76 | }
|
77 | return all;
|
78 | }
|
79 |
|
80 | function _importAsset(filepath, type, pluginAssetPath){
|
81 | filepath = path.resolve(pluginAssetPath, filepath);
|
82 | return ydoc.addAsset(filepath, type)
|
83 | }
|
84 |
|
85 | function handleAssets(config, dir, pluginName){
|
86 | let pluginAssetPath;
|
87 | if(config && typeof config === 'object'){
|
88 | if(config.dir){
|
89 | let pluginPath = path.resolve(dir, config.dir);
|
90 | pluginAssetPath = path.resolve(ydoc.config.dist, 'ydoc/ydoc-plugin-' + pluginName) ;
|
91 | fs.ensureDirSync(pluginAssetPath);
|
92 | fs.copySync(pluginPath, pluginAssetPath);
|
93 | if(config.js){
|
94 | importAsset(config.js, 'js');
|
95 | }
|
96 | if(config.css){
|
97 | importAsset(config.css, 'css');
|
98 | }
|
99 | }
|
100 |
|
101 | }
|
102 |
|
103 | function getType(p){
|
104 | return path.extname(filepath).substr(1)
|
105 | }
|
106 |
|
107 | function importAsset(filepath, type){
|
108 | if(typeof filepath === 'string'){
|
109 | _importAsset(filepath, type, pluginAssetPath);
|
110 | }else if(Array.isArray(filepath)){
|
111 | filepath.forEach(item=> _importAsset(item, type, pluginAssetPath))
|
112 | }
|
113 | }
|
114 | }
|
115 |
|
116 | function bindHooks(pluginModule, options){
|
117 | for (let key in pluginModule) {
|
118 | if (hooks[key]) {
|
119 | bindHook(key, {
|
120 | fn: pluginModule[key],
|
121 | options: options
|
122 | })
|
123 | }
|
124 | }
|
125 | }
|
126 |
|
127 | exports.loadPlugins = function loadPlugins() {
|
128 | const ydocConfig = ydoc.config;
|
129 | let modules = path.resolve(process.cwd(), 'node_modules');
|
130 | if(Array.isArray(ydocConfig.plugins) && ydocConfig.plugins.length > 0 ){
|
131 | ydocConfig.plugins.forEach(item=>{
|
132 | if(item[0] === '-'){
|
133 | let name = item.substr(1)
|
134 | DEFAULT_PLUGINS = DEFAULT_PLUGINS.filter(item=>{
|
135 | return item !== name
|
136 | })
|
137 | }
|
138 | })
|
139 | ydocConfig.plugins = ydocConfig.plugins.filter(item=> item[0] !== '-')
|
140 | }
|
141 |
|
142 | let plugins = [].concat(DEFAULT_PLUGINS);
|
143 | if (ydocConfig.plugins && Array.isArray(ydocConfig.plugins)) {
|
144 | plugins = plugins.concat(ydocConfig.plugins)
|
145 | }
|
146 | for (let i = 0, l = plugins.length; i < l; i++) {
|
147 | let pluginName = plugins[i];
|
148 |
|
149 | try {
|
150 | let pluginModule, pluginModuleDir;
|
151 | if(pluginName && typeof pluginName === 'object' && pluginName.name && pluginName.module){
|
152 | pluginModule = pluginName.module;
|
153 | pluginName = pluginName.name;
|
154 | pluginModuleDir = process.cwd();
|
155 | }else{
|
156 | try{
|
157 | pluginModuleDir = path.resolve(modules, './ydoc-plugin-' + pluginName)
|
158 | pluginModule = require(pluginModuleDir);
|
159 | }catch(err){
|
160 | pluginModuleDir = path.dirname(require.resolve('ydoc-plugin-' + pluginName))
|
161 | pluginModule = require(pluginModuleDir);
|
162 | }
|
163 | utils.log.info(`Load plugin "${pluginName}" success.`)
|
164 | }
|
165 | let options = typeof ydocConfig.pluginsConfig === 'object' && ydocConfig.pluginsConfig ? ydocConfig.pluginsConfig[pluginName] : null;
|
166 |
|
167 | bindHooks(pluginModule, options)
|
168 | if(pluginModule.assets){
|
169 | handleAssets(pluginModule.assets, pluginModuleDir, pluginName)
|
170 | }
|
171 | } catch (err) {
|
172 | err.message = 'Load ' + path.resolve(modules, './ydoc-plugin-' + pluginName) + ' plugin failed, ' + err.message;
|
173 | throw err;
|
174 | }
|
175 |
|
176 | }
|
177 | } |
\ | No newline at end of file |