Skip to content

Commit bad6ae6

Browse files
committed
调整自定义网站配置功能
1 parent 0825b9e commit bad6ae6

File tree

6 files changed

+114
-90
lines changed

6 files changed

+114
-90
lines changed

README.md

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,31 @@ markdownDownload(websiteConfigs.juejin, {
5454

5555
## 自定义网站配置
5656
如果某网站没有被支持, 可以自定义网站配置.
57-
在控制台选中插件环境, 或者在插件的选项页/背景页, 将示例代码修改为对应网站配置, 并执行
58-
自定义的网站配置的优先级, 要比默认的网站配置更高
57+
在文章页面打开控制台, 选中`插件环境`, 或者在插件的`选项页``背景页`打开控制台, 将示例代码修改为对应网站配置, 并执行
5958
``` js
60-
// 注意: 网站域名 和 文章内容选择器为必填项
59+
// 注释前面带*号的为必填项
6160
setWebsite(
62-
'juejin',
63-
{
64-
// * 网站域名, 默认配置支持正则, 这里暂不支持
65-
hosts: ['juejin.cn'],
66-
link: true,
67-
br: false,
68-
code: false,
69-
selectors: {
70-
// 标题选择器
71-
title: '.article-title',
72-
// * 文章内容选择器
73-
body: '.markdown-body',
74-
// 文章作者用户名选择器
75-
userName: '.username .name',
76-
// 文章作者链接选择器
77-
userLink: '.username',
78-
// 无效内容的选择器
79-
invalid: 'style',
80-
// 文章标签选择器
81-
tag: '.article-end .tag-list .tag-item'
82-
}
61+
'juejin',
62+
{
63+
// * 匹配域名 插件会将 文章页面的域名 与 数组的每一项元素 依次匹配, 匹配成功则该配置生效
64+
hosts: ['juejin.cn'],
65+
link: true,
66+
br: false,
67+
code: false,
68+
selectors: {
69+
// 标题选择器
70+
title: '.article-title',
71+
// * 文章内容选择器
72+
body: '.markdown-body',
73+
// 文章作者用户名选择器
74+
userName: '.username .name',
75+
// 文章作者链接选择器
76+
userLink: '.username',
77+
// 无效内容选择器, 文章内容在转换为markdown前会移除这些元素
78+
invalid: 'style',
79+
// 文章标签选择器
80+
tag: '.article-end .tag-list .tag-item'
8381
}
82+
}
8483
)
8584
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "markdown-downloader",
3-
"version": "2.0.2",
3+
"version": "2.0.3",
44
"description": "markdown文章下载",
55
"main": "dist/index.js",
66
"scripts": {

src/background.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,29 @@ chrome.action.onClicked.addListener(async (tab) => {
4747
const { host } = new URL(tab.url)
4848
const localWebsites = await getLocal('websites')
4949
const localConfigs = localWebsites instanceof Object ? Object.keys(localWebsites).reduce((acc, curr) => {
50-
return localWebsites[curr] instanceof Object ? acc.concat({
50+
const item = localWebsites[curr]
51+
return item instanceof Object ? acc.concat({
5152
website: curr,
52-
hosts: localWebsites[curr].hosts
53+
hosts: Array.isArray(item.hosts) ? item.hosts.map(item => /^\/(.*?)\/$/.test(item) ? new RegExp(item.slice(1, -1)) : item) : [],
54+
item
5355
}) : acc
54-
}, []) : []
55-
const matched = localConfigs.concat(configs).some(({ website, hosts }) => {
56+
}, []).sort((a, b) => b.item.timestamp - a.item.timestamp) : []
57+
const matched = localConfigs.concat(configs).some(({ website, hosts, item }) => {
5658
if (
5759
website && Array.isArray(hosts) && hosts.some(item => item instanceof RegExp ? item.test(host) : item === host)
5860
) {
5961
sendMessage({
6062
type: 'download',
61-
website
63+
website,
64+
from: item ? 'custom' : 'default'
6265
})
6366
return true
6467
}
6568
})
66-
!matched && chrome.notifications.create(Date.now() + String(tab.id), {
67-
type : 'basic',
68-
title : '下载提示',
69-
message : '当前页面不支持下载',
70-
iconUrl : '/icon.png'
69+
!matched && chrome.notifications.create(Date.now() + String(tab.id), {
70+
type: 'basic',
71+
title: '下载提示',
72+
message: '当前页面不支持下载',
73+
iconUrl: '/icon.png'
7174
})
7275
})

src/index.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { websites, hooks } from './websites'
2-
import {
2+
import {
33
isExtension,
44
sendMessage,
55
getLocal,
@@ -9,16 +9,16 @@ import downloadZip from './download'
99
import { downloadMarkdown } from './markdown'
1010
import { getLocalOptions } from './options'
1111

12-
const extract = async (options, customOptions = {}, hook = {}) => {
12+
const extract = async (options, customOptions = {}, hooks = {}) => {
1313
const localOptions = await getLocalOptions()
1414
const data = await downloadMarkdown(options, Object.assign(customOptions, {
1515
localOptions
16-
}), hook)
16+
}), hooks)
1717
if (data) {
1818
if (data.type === 'download') {
1919
const { fileName, files, options = {} } = data
2020
downloadZip(fileName, files, options)
21-
} else {
21+
} else {
2222
sendMessage(data)
2323
}
2424
}
@@ -30,21 +30,23 @@ if (isExtension) {
3030
const localWebsites = await getLocal('websites')
3131
if (message instanceof Object) {
3232
if (message.type === 'download') {
33-
if (typeof websites[message.website] === 'function') {
34-
await websites[message.website](extract)
35-
} else {
36-
const localWebsite = localWebsites[message.website]
37-
if (localWebsite instanceof Object) {
38-
await extract(
39-
localWebsite,
40-
localWebsite.customOptions instanceof Object ? localWebsite.customOptions : {},
41-
Object.assign({},
42-
hooks[message.website] instanceof Object ? hooks[message.website] : {},
43-
localWebsite.hooks instanceof Object ? localWebsite.hooks : {}
44-
)
45-
)
33+
const localWebsite = localWebsites[message.website]
34+
if (message.from === 'custom' && localWebsite instanceof Object) {
35+
const hookName = message.website || localWebsite.website || localWebsite.origin
36+
const customOptions = localWebsite.customOptions instanceof Object ? localWebsite.customOptions : {}
37+
const customHooks = Object.assign({},
38+
hooks[hookName] instanceof Object ? hooks[hookName] : {},
39+
localWebsite.hooks instanceof Object ? localWebsite.hooks : {}
40+
)
41+
await extract(
42+
localWebsite,
43+
customOptions,
44+
customHooks
45+
)
46+
} else
47+
if (typeof websites[message.website] === 'function') {
48+
await websites[message.website](extract)
4649
}
47-
}
4850
}
4951
}
5052
sendResponse('')

src/option.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,32 @@ const getLocal = (key) =>
33
chrome.storage.local.get(key, (data) => {
44
resolve(data[key])
55
})
6-
})
6+
})
77
const setWebsite = async (website, options) => {
88
const localWebsites = await getLocal('websites')
99
const websites = Object.assign(
1010
{},
1111
localWebsites instanceof Object ? localWebsites : {}
1212
)
13-
const valid = website
14-
&&
15-
options instanceof Object
16-
&&
17-
Array.isArray(options.hosts)
18-
&&
19-
options.hosts.length
20-
&&
21-
(options.selectors || {}).body
22-
if (valid) {
13+
const rules = [
14+
[
15+
website && typeof website === 'string',
16+
'第一个参数应该是字符串类型, 并且不能为空'
17+
],
18+
[
19+
Array.isArray(options.hosts) && options.hosts.length,
20+
'options.hosts应该是数组,并且长度不能为0'
21+
],
22+
[
23+
(options.selectors || {}).body,
24+
'options.selectors.body不能为空'
25+
]
26+
]
27+
const hit = rules.find(item => !item[0])
28+
if (!hit) {
2329
options.origin = website
30+
options.timestamp = Date.now()
31+
options.hosts = options.hosts.map(item => item.toString())
2432
Object.assign(
2533
websites,
2634
{
@@ -35,6 +43,8 @@ const setWebsite = async (website, options) => {
3543
chrome.storage.local.set({
3644
websites
3745
})
46+
} else {
47+
hit[1] && console.warn(hit[1])
3848
}
3949
return websites
4050
}

src/utils.js

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const queryAll = (selector, context = document) => {
2626
return [].slice.apply(context.querySelectorAll(selector))
2727
}
2828
export const noop = (func, defaultFunc) => {
29-
return typeof func === 'function' ? func : typeof defaultFunc === 'function' ? defaultFunc : () => {}
29+
return typeof func === 'function' ? func : typeof defaultFunc === 'function' ? defaultFunc : () => { }
3030
}
3131
export const encodeUrlData = (data) => {
3232
let body = ''
@@ -75,23 +75,23 @@ export const formatDate = (str, t) => {
7575
const obj = {
7676
yyyyyyyy: t.getFullYear(),
7777
yy: t.getFullYear(),
78-
MM: t.getMonth()+1,
78+
MM: t.getMonth() + 1,
7979
dd: t.getDate(),
8080
HH: t.getHours(),
8181
hh: t.getHours() % 12,
8282
mm: t.getMinutes(),
8383
ss: t.getSeconds(),
8484
ww: '日一二三四五六'.split('')[t.getDay()]
85-
};
86-
return str.replace(/([a-z]+)/ig, function ($1){
87-
return (obj[$1+$1] === 0 ? '0' : obj[$1+$1]) || ('0' + obj[$1]).slice(-2);
88-
});
85+
}
86+
return str.replace(/([a-z]+)/ig, function ($1) {
87+
return (obj[$1 + $1] === 0 ? '0' : obj[$1 + $1]) || ('0' + obj[$1]).slice(-2)
88+
})
8989
}
9090
export const insertAfter = (newElement, targetElement) => {
9191
const parent = targetElement.parentNode
92-
if(parent.lastChild === targetElement){
92+
if (parent.lastChild === targetElement) {
9393
parent.appendChild(newElement)
94-
}else{
94+
} else {
9595
parent.insertBefore(newElement, targetElement.nextSibling)
9696
}
9797
}
@@ -106,14 +106,14 @@ export const getUrl = (prefix, link) => {
106106
return prefix + link
107107
}
108108
export const exec = async (...rest) => {
109-
if (!rest.length) return exec.returnValue
110-
exec.returnValue = false
111-
try {
112-
exec.returnValue = typeof rest[0] === 'function' && await rest[0](...rest.slice(1))
113-
} catch (err) {
114-
console.warn(err)
115-
}
116-
return exec.returnValue
109+
if (!rest.length) return exec.returnValue
110+
exec.returnValue = false
111+
try {
112+
exec.returnValue = typeof rest[0] === 'function' && await rest[0](...rest.slice(1))
113+
} catch (err) {
114+
console.warn(err)
115+
}
116+
return exec.returnValue
117117
}
118118
export const getLocal = (key) => {
119119
return new Promise((resolve) => {
@@ -128,17 +128,25 @@ export const setWebsite = async (website, options) => {
128128
{},
129129
localWebsites instanceof Object ? localWebsites : {}
130130
)
131-
const valid = website
132-
&&
133-
options instanceof Object
134-
&&
135-
Array.isArray(options.hosts)
136-
&&
137-
options.hosts.length
138-
&&
139-
(options.selectors || {}).body
140-
if (valid) {
131+
const rules = [
132+
[
133+
website && typeof website === 'string',
134+
'第一个参数应该是字符串类型, 并且不能为空'
135+
],
136+
[
137+
Array.isArray(options.hosts) && options.hosts.length,
138+
'options.hosts应该是数组,并且长度不能为0'
139+
],
140+
[
141+
(options.selectors || {}).body,
142+
'options.selectors.body不能为空'
143+
]
144+
]
145+
const hit = rules.find(item => !item[0])
146+
if (!hit) {
141147
options.origin = website
148+
options.timestamp = Date.now()
149+
options.hosts = options.hosts.map(item => item.toString())
142150
Object.assign(
143151
websites,
144152
{
@@ -153,6 +161,8 @@ export const setWebsite = async (website, options) => {
153161
chrome.storage.local.set({
154162
websites
155163
})
164+
} else {
165+
hit[1] && console.warn(hit[1])
156166
}
157167
return websites
158168
}

0 commit comments

Comments
 (0)