1
1
import md5 from 'md5'
2
- import path from 'path-browserify'
3
2
import html2markdown from 'html-to-md'
4
3
import { websites , hooks } from './websites'
5
4
import merge from 'webpack-merge'
5
+ import 'mathjax/es5/tex-svg'
6
+ import {
7
+ isExtension ,
8
+ getExt ,
9
+ query ,
10
+ getText ,
11
+ getAttribute ,
12
+ queryAll ,
13
+ noop ,
14
+ sendMessage ,
15
+ formatDate ,
16
+ insertAfter ,
17
+ getUrl
18
+ } from './utils'
6
19
7
- const isBroswer = typeof window !== 'undefined' && window instanceof Object
8
- const isExtension = isBroswer && window . chrome instanceof Object && window . chrome . runtime
9
-
10
- const getExt = ( fileName ) => {
11
- return path . parse ( fileName ) . ext . slice ( 1 )
12
- }
13
-
14
- const query = ( selector , context = document ) => {
15
- if ( selector instanceof NodeList || selector instanceof Node ) {
16
- return selector
17
- }
18
- return context . querySelector ( selector )
19
- }
20
-
21
- const getText = ( selector , context = document ) => {
22
- const el = query ( selector , context ) || { }
23
- return el . innerText || ''
24
- }
25
-
26
- const getAttribute = ( val , selector , context = document ) => {
27
- const el = query ( selector , context )
28
- return el ? el . getAttribute ( val ) || '' : ''
29
- }
30
-
31
- const queryAll = ( selector , context = document ) => {
32
- return [ ] . slice . apply ( context . querySelectorAll ( selector ) )
33
- }
34
-
35
- const noop = ( func , defaultFunc ) => {
36
- return typeof func === 'function' ? func : typeof defaultFunc === 'function' ? defaultFunc : ( ) => { }
37
- }
38
-
39
- const encodeUrlData = ( data ) => {
40
- let body = ''
41
- for ( let key in data ) {
42
- body += key + '=' + encodeURIComponent ( data [ key ] ) + '&'
43
- }
44
- return body . slice ( 0 , - 1 )
45
- }
46
-
47
- const encodeOptionsData = ( options ) => {
48
- if ( options . stringify !== false && typeof options . data === 'object' ) {
49
- options . data = encodeUrlData ( options . data )
50
- }
51
- return options
52
- }
53
-
54
- const sendMessage = ( options , onsuccess , onerror , retry ) => {
55
- if ( isExtension ) {
56
- retry = isNaN ( retry ) ? 3 : + retry
57
- encodeOptionsData ( options )
58
- chrome . runtime . sendMessage ( options , ( [ error , response , headers , xhr ] ) => {
59
- if ( ! error ) {
60
- try {
61
- const result = noop ( onsuccess ) ( response , headers , xhr )
62
- if ( result === void 0 ) {
63
- return response
64
- }
65
- // onsuccess返回值不为undefined, 视为调用失败
66
- error = result
67
- } catch ( err ) {
68
- // 执行onsuccess代码出错
69
- error = err
70
- }
71
- }
72
- if ( retry -- > 0 ) {
73
- sendMessage ( options , onsuccess , onerror , retry )
74
- } else {
75
- noop ( onerror ) ( error , headers , xhr )
76
- }
77
- } )
78
- }
79
- }
80
-
81
- const formatDate = ( str , t ) => {
82
- t = typeof t === 'string' || ! isNaN ( t ) ? new Date ( t ) : t
83
- if ( t instanceof Date === false ) {
84
- t = new Date ( )
85
- }
86
- const obj = {
87
- yyyyyyyy : t . getFullYear ( ) ,
88
- yy : t . getFullYear ( ) ,
89
- MM : t . getMonth ( ) + 1 ,
90
- dd : t . getDate ( ) ,
91
- HH : t . getHours ( ) ,
92
- hh : t . getHours ( ) % 12 ,
93
- mm : t . getMinutes ( ) ,
94
- ss : t . getSeconds ( ) ,
95
- ww : '日一二三四五六' . split ( '' ) [ t . getDay ( ) ]
96
- } ;
97
- return str . replace ( / ( [ a - z ] + ) / ig, function ( $1 ) {
98
- return ( obj [ $1 + $1 ] === 0 ? '0' : obj [ $1 + $1 ] ) || ( '0' + obj [ $1 ] ) . slice ( - 2 ) ;
99
- } ) ;
100
- }
101
20
102
21
const setInfo = ( data ) => {
103
22
data = Object . assign ( {
@@ -129,25 +48,6 @@ const getMarkdown = (markdownBody) => {
129
48
// }[s1] || s))
130
49
}
131
50
132
- const insertAfter = ( newElement , targetElement ) => {
133
- const parent = targetElement . parentNode
134
- if ( parent . lastChild === targetElement ) {
135
- parent . appendChild ( newElement )
136
- } else {
137
- parent . insertBefore ( newElement , targetElement . nextSibling )
138
- }
139
- }
140
-
141
- const getUrl = ( prefix , link ) => {
142
- if ( ! link ) return ''
143
- if ( / ^ ( h t t p | h t t p s ) / . test ( link ) ) {
144
- return link
145
- }
146
- if ( / ^ \/ \/ / . test ( link ) ) {
147
- return prefix . split ( '//' ) [ 0 ] + link
148
- }
149
- return prefix + link
150
- }
151
51
const convert = async ( options , customOptions ) => {
152
52
const context = { }
153
53
const defaultOptions = {
@@ -189,6 +89,9 @@ const convert = async (options, customOptions) => {
189
89
return result
190
90
}
191
91
const markdownBody = query ( selectors . body , options . context ) . cloneNode ( true )
92
+ const fileName = ( getText ( selectors . title ) || document . title )
93
+ const realName = fileName . replace ( / [ \\ \/ \? < > : ' \* \| ] / g, '_' )
94
+ noop ( hook . extract ) ( context , { markdownBody, fileName, realName } )
192
95
queryAll ( selectors . copyBtn , markdownBody ) . map ( item => item . parentElement . removeChild ( item ) )
193
96
queryAll ( '[data-id]' , markdownBody ) . map ( item => item . removeAttribute ( 'data-id' ) )
194
97
if ( selectors . invalid ) {
@@ -214,9 +117,17 @@ const convert = async (options, customOptions) => {
214
117
} )
215
118
}
216
119
const urls = [ ]
217
- const fileName = ( getText ( selectors . title ) || document . title )
218
- const realName = fileName . replace ( / [ \\ \/ \? < > : ' \* \| ] / g, '_' )
219
120
const files = queryAll ( 'img' , markdownBody ) . map ( item => {
121
+ const downloadName = item . getAttribute ( 'downloadName' )
122
+ const downloadUrl = item . getAttribute ( 'downloadUrl' )
123
+ if ( downloadName && downloadUrl ) {
124
+ item . src = './' + downloadName
125
+ options . urls !== false && urls . push ( downloadUrl )
126
+ return {
127
+ name : downloadName ,
128
+ downloadUrl
129
+ }
130
+ }
220
131
const src = item . getAttribute ( options . lazyKey ) || item . src
221
132
const url = src . replace ( / \? $ / , '' )
222
133
const ext = getExt ( url )
@@ -235,11 +146,12 @@ const convert = async (options, customOptions) => {
235
146
home : getUrl ( location . origin , getAttribute ( 'href' , selectors . userLink ) ) ,
236
147
description : markdownBody . innerText . replace ( / ^ ( [ \n \s ] + ) / g, '' ) . replace ( / \n / g, ' ' ) . slice ( 0 , 50 ) + '...' ,
237
148
} )
238
- noop ( hook . extract ) ( context )
239
149
const markdwonDoc = html2markdown ( info + getMarkdown ( markdownBody ) , { } )
150
+ const copyright = '> 当前文档由 [markdown文档下载插件](https://github.com/kscript/markdown-download) 下载, 原文链接: [' + fileName + '](' + location . href + ') '
151
+ const content = await noop ( hook . formatContent ) ( context , { markdownBody, markdwonDoc } )
240
152
files . push ( {
241
153
name : realName + '.md' ,
242
- content : markdwonDoc + '\n\n' + '> 当前文档由 [markdown文档下载插件](https://github.com/kscript/markdown-download) 下载, 原文链接: [' + fileName + ']( ' + location . href + ') '
154
+ content : ( content && typeof content === 'string' ? content : markdwonDoc ) + '\n\n ' + copyright
243
155
} )
244
156
files . push ( {
245
157
name : realName + '/urls' ,
@@ -259,19 +171,17 @@ const extract = async (options, customOptions) => {
259
171
return datas
260
172
}
261
173
262
- if ( isBroswer ) {
263
- if ( isExtension ) {
264
- chrome . runtime . onMessage . addListener ( async ( message , sender , sendResponse ) => {
265
- if ( message instanceof Object ) {
266
- if ( message . type === 'download' ) {
267
- if ( typeof websites [ message . website ] === 'function' ) {
268
- await websites [ message . website ] ( extract )
269
- }
174
+ if ( isExtension ) {
175
+ chrome . runtime . onMessage . addListener ( async ( message , sender , sendResponse ) => {
176
+ if ( message instanceof Object ) {
177
+ if ( message . type === 'download' ) {
178
+ if ( typeof websites [ message . website ] === 'function' ) {
179
+ await websites [ message . website ] ( extract )
270
180
}
271
181
}
272
- sendResponse ( '' )
273
- } )
274
- }
182
+ }
183
+ sendResponse ( '' )
184
+ } )
275
185
}
276
186
277
187
export default convert
0 commit comments