UNPKG

5.15 kBJavaScriptView Raw
1const ydoc = require('./ydoc.js');
2const path = require('path');
3const utils = require('./utils.js');
4const fs = require('fs-extra');
5
6let DEFAULT_PLUGINS = ['execution-time', 'import-asset', 'search'];
7
8const hooks = {}
9
10function addHook(arr){
11 arr.forEach(hookname=> hooks[hookname] = {
12 listener: []
13 })
14}
15
16function addTplHook(arr){
17 arr.forEach(hookname=> hooks[utils.defaultTplHookPrefix + hookname] = {
18 listener: []
19 })
20}
21
22addHook(["init","nav", "finish", "book:before", "book", "page:before", "page"])
23addTplHook(["header","mask"])
24
25
26function 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
34exports.bindHook = bindHook;
35
36/**
37*
38* @param {*} hookname
39* @return promise
40*/
41exports.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* @param {*} hookname
61* @return promise
62*/
63exports.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
80function _importAsset(filepath, type, pluginAssetPath){
81 filepath = path.resolve(pluginAssetPath, filepath);
82 return ydoc.addAsset(filepath, type)
83}
84
85function 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
116function 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
127exports.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