diff --git a/.vscode/settings.json b/.vscode/settings.json index 3170cb29..d3aeedc1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -54,5 +54,5 @@ "**/dist": true }, "editor.detectIndentation": false, // 不自动检测缩进 - "editor.tabSize": 4, + "editor.tabSize": 4 } \ No newline at end of file diff --git a/README.md b/README.md index b344748a..bca1776b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -


Wereader

+

icon
Wereader

一个 Chrome / Firefox 扩展:主要用于微信读书做笔记,对常使用 Markdown 做笔记的读者比较有帮助。

@@ -53,3 +53,12 @@ | [chrome-plugin-demo](https://github.com/sxei/chrome-plugin-demo) | Chrome 扩展开发教程 | | [Extensions - Chrome Developers](https://developer.chrome.com/docs/extensions/) | Chrome 扩展官方文档 | +## 其他 + + + + + +
+
wx-code
加微信进交流群(备注:wereader 交流群)
+
diff --git a/res/README/wx-code.png b/res/README/wx-code.png new file mode 100644 index 00000000..28e2d4ec Binary files /dev/null and b/res/README/wx-code.png differ diff --git a/src/common/utils.ts b/src/common/utils.ts index cbbf15cc..a9431205 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -65,3 +65,21 @@ export function commandCopy(text: string, selector: string) { textEl.select() document.execCommand('copy') } + +/** + * 时间戳转时间字符串 + * @param timestamp 时间戳(秒为单位) + * @returns 格式化时间字符串 + */ +export function formatTimestamp(timestamp: number) { + // 乘 1000 转为毫秒单位 + const date = new Date(timestamp * 1000) + const year = date.getFullYear() + const month = String(date.getMonth() + 1).padStart(2, '0') + const day = String(date.getDate()).padStart(2, '0') + const hours = String(date.getHours()).padStart(2, '0') + const minutes = String(date.getMinutes()).padStart(2, '0') + const seconds = String(date.getSeconds()).padStart(2, '0') + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` +} diff --git a/src/content.ts b/src/content.ts index 87c130c9..b52cd357 100644 --- a/src/content.ts +++ b/src/content.ts @@ -19,6 +19,8 @@ import { initTheme } from './content/modules/content-theme' import { initThoughtEdit } from './content/modules/content-thought-edit' import { initFancyBox } from './content/modules/fancybox' import './content/modules/content-copy' +import './content/static/css/content-theme-switch.css' +import './content/static/css/common.css' initAlert() initDeleteMarksNotification() diff --git a/src/content/modules/content-theme.ts b/src/content/modules/content-theme.ts index b9352ddf..8110d151 100644 --- a/src/content/modules/content-theme.ts +++ b/src/content/modules/content-theme.ts @@ -90,8 +90,6 @@ function changeTheme(currentFlag: number, event?: JQuery.ClickEvent) { * 添加主题切换按钮并绑定点击事件 */ function addThemeBtn() { - // 主题切换顺序 - const themeOrder = [-1, 0, 1, 2] // 创建主题切换按钮 const themeBtn = $('') themeBtn.append($('主题')) @@ -99,10 +97,11 @@ function addThemeBtn() { // 隐藏原主题切换按钮图标 $('.readerControls_item.white > .icon,.readerControls_item.dark > .icon').css('display', 'none').before(themeBtn) // 主题切换按钮点击事件 - themeBtn.on('click', (event) => { + themeBtn.on('click', function onClick(event) { try { - curFlag = themeOrder[(themeOrder.indexOf(curFlag) + 1) % themeOrder.length] - changeTheme(curFlag, event) + $('.readerControls_item.theme').css('display', 'none') + $('.theme_switcher').css('display', 'flex') + event.stopPropagation() } catch (error) { Swal.fire({ title: 'Oops...', text: '似乎出了点问题,刷新一下试试吧~', icon: 'error', confirmButtonText: 'OK' @@ -111,6 +110,39 @@ function addThemeBtn() { }) } +/** + * 添加主题切换 + */ +function addThemeSwitcher() { + $('.readerControls_item.white > .icon,.readerControls_item.dark > .icon').before($(``)) + // 不同主题按钮 + const itemClass = 'theme-switch-item' + $('.theme-switch-container span').addClass([itemClass, 'cursor-pointer']) + .on('click', function onClick(e) { + const themeIndex = $(this).data('themeIndex') + changeTheme(themeIndex, e) + }) + // 点击父元素时关闭冒泡 + $('.theme-switch-container,.theme-switch-left').on('click', function handleClick(e) { + if (!$(e.target).is(`.${itemClass}`)) e.stopPropagation() + }) + // 隐藏面板 + $(document).add('.theme-switch-left').on('click', function handleHideSwitcher(e) { + // 不是点击切换选项时关闭切换面板 + if (!$(e.target).is(`.${itemClass}`)) { + $('.theme_switcher').css('display', 'none') + $('.readerControls_item.theme').css('display', 'inline-block') + } + }) +} + function initTheme() { console.log(tag, 'initTheme') // 主题初始化(记住上次设置的背景主题) @@ -141,6 +173,7 @@ function initTheme() { }) observer.observe(themeSwitch, { attributes: true }) addThemeBtn() + addThemeSwitcher() } }) } diff --git a/src/content/static/css/common.css b/src/content/static/css/common.css new file mode 100644 index 00000000..867b1633 --- /dev/null +++ b/src/content/static/css/common.css @@ -0,0 +1,6 @@ +.cursor-pointer { + cursor: pointer; +} +.cursor-default { + cursor: default; +} diff --git a/src/content/static/css/content-theme-switch.css b/src/content/static/css/content-theme-switch.css new file mode 100644 index 00000000..989638f7 --- /dev/null +++ b/src/content/static/css/content-theme-switch.css @@ -0,0 +1,7 @@ +/* 主题面板项 */ +.theme-switch-container span{ + border: 2px solid grey; + border-radius: 3px; + padding: 6px; + margin: 3px; +} diff --git a/src/content/static/css/theme/dark.css b/src/content/static/css/theme/dark.css index 1a25aa89..c8a63f10 100644 --- a/src/content/static/css/theme/dark.css +++ b/src/content/static/css/theme/dark.css @@ -8,6 +8,6 @@ } /* 主题按钮、进度按钮 */ -.readerControls_item.theme, #progressText { +.readerControls_item.theme, .theme-switch-left, #progressText { color: rgb(190,190,190) !important; -} \ No newline at end of file +} diff --git a/src/content/static/css/theme/white.css b/src/content/static/css/theme/white.css index 98d2f1b0..f6279f98 100644 --- a/src/content/static/css/theme/white.css +++ b/src/content/static/css/theme/white.css @@ -8,6 +8,6 @@ } /* 主题按钮、进度按钮 */ -.readerControls_item.theme, #progressText { +.readerControls_item.theme, .theme-switch-left, #progressText { color: rgb(0,0,0) !important; -} \ No newline at end of file +} diff --git a/src/options/options-help.ts b/src/options/options-help.ts index 29174cc1..2fdcd70c 100644 --- a/src/options/options-help.ts +++ b/src/options/options-help.ts @@ -34,7 +34,7 @@ const helpContent: {[key: string]: any} = { }, thouSuf: { title: '想法后缀', - help: `

想法也就是你平时阅读时在书中发表的想法。当你将前后缀设置为两个星号(**)时,导出的想法在 Markdown 中将会被加粗。

` + help: `

想法也就是你平时阅读时在书中发表的想法。当你将前后缀设置为两个星号(**)时,导出的想法在 Markdown 中将会被加粗。可使用{createTime}作为占位符导出想法创建时间。

` }, metaTemplate: { title: '书本信息导出模板', @@ -50,7 +50,7 @@ const helpContent: {[key: string]: any} = { }, thouMarkSuf: { title: '想法标注后缀', - help: `

想法标注即想法所对应的书本内容。当你将想法标注前后缀设置为两个星号(**)时,导出的想法标注在 Markdown 中将会被加粗。

` + help: `

想法标注即想法所对应的书本内容。当你将想法标注前后缀设置为两个星号(**)时,导出的想法标注在 Markdown 中将会被加粗。可使用{createTime}作为占位符导出想法创建时间。

` }, codeSuf: { title: '代码块后缀', @@ -190,4 +190,4 @@ function initHelpContent() { }); } -export { initHelpContent }; \ No newline at end of file +export { initHelpContent }; diff --git a/src/worker/types/ThoughtsInAChap.ts b/src/worker/types/ThoughtsInAChap.ts index bc301465..2e068750 100644 --- a/src/worker/types/ThoughtsInAChap.ts +++ b/src/worker/types/ThoughtsInAChap.ts @@ -4,4 +4,5 @@ export interface ThoughtsInAChap { range: string; abstract: string; content: string; + createTime: number } diff --git a/src/worker/worker-popup-process.ts b/src/worker/worker-popup-process.ts index e28b5e79..57341efe 100644 --- a/src/worker/worker-popup-process.ts +++ b/src/worker/worker-popup-process.ts @@ -21,7 +21,9 @@ import { } from './worker-vars' import { Wereader } from './types/Wereader' import { ThoughtsInAChap } from './types/ThoughtsInAChap' -import { getLocalStorage, getSyncStorage, sortByKey } from '../common/utils' +import { + formatTimestamp, getLocalStorage, getSyncStorage, sortByKey +} from '../common/utils' import { notify } from './worker-notification' // 给标题添加前后缀 @@ -77,7 +79,12 @@ export async function getMyThought() { } else { range = range.replace(/(\d*)-\d*/, '$1') } - thoughtsInAChap.push({ abstract: abstract, content: content, range: range }) + thoughtsInAChap.push({ + abstract, + content, + range, + createTime: item.review.createTime + }) } } thoughtsMap.set(chapterUid, sortByKey(thoughtsInAChap, 'range') as ThoughtsInAChap[]) @@ -369,6 +376,27 @@ function addMarkPreAndSuf(markText: string, style: number, config: ConfigType) { return pre + markText + suf } +/** + * 替换想法前后缀配置中的占位符 + * @param mark 想法标注 + * @param config 配置信息 + * @returns 替换后的各前后缀 + */ +export function getReplacedThoughtConfig(mark: ThoughtsInAChap, config: ConfigType) { + const re = /\{createTime}/g + const time = formatTimestamp(mark.createTime) + const thouPre = config.thouPre.replace(re, time) + const thouSuf = config.thouSuf.replace(re, time) + const thouMarkPre = config.thouMarkPre.replace(re, time) + const thouMarkSuf = config.thouMarkSuf.replace(re, time) + return { + thouPre, + thouSuf, + thouMarkPre, + thouMarkSuf + } +} + // 处理章内标注 export function traverseMarks( marks: (Updated | ThoughtsInAChap)[], @@ -395,11 +423,17 @@ export function traverseMarks( footnoteContent = data[1] } if (isThought(mark)) { // 如果为想法 + const { + thouPre, + thouSuf, + thouMarkPre, + thouMarkSuf + } = getReplacedThoughtConfig(mark, config) // 想法 - const thouContent = `${config.thouPre}${mark.content}${config.thouSuf}\n\n` + const thouContent = `${thouPre}${mark.content}${thouSuf}\n\n` // 想法所标注的内容 const abstract = mark.abstract - let thouAbstract = `${config.thouMarkPre}${abstract}${config.thouMarkSuf}\n\n` + let thouAbstract = `${thouMarkPre}${abstract}${thouMarkSuf}\n\n` // 想法所对应文本与上一条标注相同时 if (abstract === prevMarkText) { if (prevMarkType === '0') { diff --git a/src/worker/worker-popup.ts b/src/worker/worker-popup.ts index 2e1ee867..33715212 100644 --- a/src/worker/worker-popup.ts +++ b/src/worker/worker-popup.ts @@ -14,7 +14,7 @@ import { getBestBookMarks, getBookMarks, getChapters, - getMyThought, + getMyThought, getReplacedThoughtConfig, getTitleAddedPreAndSuf, traverseMarks } from './worker-popup-process' @@ -224,10 +224,16 @@ export async function copyThought(isAll?: boolean) { let tempRes = `${getTitleAddedPreAndSuf(contents.get(chapUid)!.title, contents.get(chapUid)!.level, config)}\n\n` let prevAbstract = '' // 保存上一条想法对应标注文本 thoughtsInAChap.forEach((thou) => { + const { + thouPre, + thouSuf, + thouMarkPre, + thouMarkSuf + } = getReplacedThoughtConfig(thou, config) // 想法 - const thouContent = `${config.thouPre}${thou.content}${config.thouSuf}\n\n` + const thouContent = `${thouPre}${thou.content}${thouSuf}\n\n` // 想法所标注的内容 - let thouAbstract = `${config.thouMarkPre}${thou.abstract}${config.thouMarkSuf}\n\n` + let thouAbstract = `${thouMarkPre}${thou.abstract}${thouMarkSuf}\n\n` // 当前标注文本和前一条标注文本内容相同、且配置去重时,不导出当前的标注 if (thou.abstract === prevAbstract && config.distinctThouMarks) { thouAbstract = '' diff --git a/src/worker/worker-vars.ts b/src/worker/worker-vars.ts index 27bb96ed..532e9e2f 100644 --- a/src/worker/worker-vars.ts +++ b/src/worker/worker-vars.ts @@ -40,7 +40,7 @@ const defaultConfig: ConfigType = { lev2Suf: '', lev3Pre: '#### ', lev3Suf: '', - thouPre: '==', + thouPre: '> {createTime}\n\n==', thouSuf: '==', /* eslint-disable */ metaTemplate: '__metaTemplate__', diff --git a/wereader.zip b/wereader.zip index 411b3b55..663e46f0 100644 Binary files a/wereader.zip and b/wereader.zip differ