diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
new file mode 100644
index 000000000..ad6203270
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -0,0 +1,53 @@
+name: 🛠æäº¤ Bug
+description: 请æäº¤ä½ çš„ Bug
+body:
+ - type: markdown
+ attributes:
+ value: |
+ 谢谢帮忙æäº¤ Bug 这会让简悦å˜å¾—更好。
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: æè¿°è¿™ä¸ªé”™è¯¯
+ description: 请尽é‡è¯¦ç»†æè¿°ä½ 的错误
+ validations:
+ required: true
+ - type: textarea
+ id: repro-steps
+ attributes:
+ label: å¤çްæ¥éª¤
+ description: 请尽é‡ç”¨æ¸…æ™°çš„æ¥éª¤ï¼ˆå“ªæ€•比较多)的æè¿°ä½ 的问题,最好å¯ä»¥çš„è¯ï¼Œè¯·æˆªå›¾æˆ–者视频说明。
+ placeholder: |
+ 1. æ¥éª¤1
+ 2. æ¥éª¤2
+ 3. æ¥éª¤3
+ validations:
+ required: true
+ - type: textarea
+ id: others
+ attributes:
+ label: 其他相关说明
+ description: 如果有需è¦ï¼Œå¯ä»¥åœ¨è¿™é‡Œç»§ç»è¯´æ˜Ž
+ validations:
+ required: false
+ - type: input
+ id: os
+ attributes:
+ label: æ“作系统
+ placeholder: macOS
+ validations:
+ required: true
+ - type: input
+ id: browser
+ attributes:
+ label: æµè§ˆå™¨
+ placeholder: 请说明æµè§ˆå™¨ä»¥åŠå°½é‡è¯´æ˜Žæµè§ˆå™¨ç‰ˆæœ¬
+ validations:
+ required: true
+ - type: input
+ id: website
+ attributes:
+ label: å‘生问题的网å€
+ placeholder: 如果任æ„网站å‡å¯çš„è¯ï¼Œè¯·éšä¾¿ç•™ä¸‹ä¸€ä¸ªä½ é‡åˆ°é—®é¢˜çš„地å€
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..62f9bcd32
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,68 @@
+blank_issues_enabled: false
+contact_links:
+ - name: 🆘 当å‡çº§ Chrome åŽæ— 法使用简悦的解决方案
+ url: https://www.yuque.com/kenshin/simpread/fxszlhpp1iht441s
+ about: |
+ 当 Chrome 应用商店æç¤ºã€æ¤æ‰©å±•ç¨‹åºæœªéµå¾ª Chrome 扩展程åºçš„æœ€ä½³å®žè·µï¼Œå› æ¤å·²æ— 法å†ä½¿ç”¨ã€‘的解决方案
+ - name: 📮 订阅ä¸å¿ƒ
+ url: https://simpread.pro/subscribe
+ about: |
+ 我æ¯å‘¨éƒ½ä¼šæŽ¨ 3 ~ 4 篇关于简悦的新功能ã€è”动ç‰å†…容,建议简悦用户(尤其是ç»å¸¸ä½¿ç”¨ç®€æ‚¦é«˜çº§åŠŸèƒ½çš„ç”¨æˆ·ï¼‰è®¢é˜…ã€å‘布汇总】。
+ - name: 📚 简悦手册
+ url: https://www.yuque.com/kenshin/simpread/
+ about: |
+ 简悦的阅读模å¼ç›¸å…³åŠŸèƒ½æ˜¯ä¸éœ€è¦è®¾ç½®çš„。
+ å¦‚æžœä½ ä½¿ç”¨äº†æ›´é«˜çº§çš„åŠŸèƒ½ï¼Œå¦‚ï¼šåŒæ¥åŠ©æ‰‹ï¼Œæˆ–è€…ä½ æ˜¯ Obsidian / Logseq ç‰åŒé“¾ç¬”è®°ç”¨æˆ·ï¼Œæˆ–è€…ä½ æœ¬åœ°å¿«ç…§ç‰åŠŸèƒ½çš„è¯ï¼Œåˆ™éœ€è¦é…置。
+ 简悦官方已ç»å‡†å¤‡å¥½äº†ç›¸å…³çš„æ•™ç¨‹ã€‚
+ - name: 📦 é…置库(强烈建议åŒé“¾ç¬”è®°ç”¨æˆ·ä½¿ç”¨æ¤æ–¹å¼ï¼‰
+ url: https://www.yuque.com/kenshin/simpread/ds8zk0
+ about: |
+ 这是简悦官方推出的å…é…置包方案,包括:Notion / Obsidian / Logseq ç‰ç”¨æ³•。
+ - name: 📗 Notion é…置库
+ url: https://www.yuque.com/kenshin/simpread/mwda8s
+ about: |
+ 通过简悦导入到 Notion 的内容包括:Notion 图床ã€é¢˜å›¾ã€Faviconã€æ ‡ç¾ç‰è¯¸å¤šåŠŸèƒ½ã€‚
+ - name: 📘 Obsidian é…置库
+ url: https://www.yuque.com/kenshin/simpread/psugef
+ about: |
+ 简悦与 Obsidian çš„è”动å¯ä»¥å°†ç®€æ‚¦çš„æ ‡æ³¨ç³»ç»Ÿå†…置到 Obsidian ä¸ã€‚
+ - name: 🖥 如何é…ç½®åŒæ¥åŠ©æ‰‹
+ url: https://www.yuque.com/kenshin/simpread/pwpnsx
+ about: |
+ åŒæ¥åŠ©æ‰‹ç›¸å½“äºŽä¸€ä¸ªåŸºäºŽç”¨æˆ·ç³»ç»Ÿçš„æœåŠ¡å™¨ï¼Œå¯ä»¥å®žçŽ°è¯¸å¤šé«˜çº§åŠŸèƒ½ï¼ˆå¦‚æžœä½ åªæ˜¯é˜…读模å¼ç”¨æˆ·ï¼Œä¸éœ€è¦è¿™äº›ï¼‰
+ - name: 💾 如何é…置本地快照系统
+ url: https://www.yuque.com/kenshin/simpread/wkswh7
+ about: |
+ ç®€æ‚¦æœ€å¤§çš„ä¼˜åŠ¿åœ¨äºŽï¼šç”¨æˆ·æ‹¥æœ‰å…¨éƒ¨çš„æ•°æ®æ‰€æœ‰æƒï¼Œåªéœ€è¦ç®€å•çš„å‡ æ¥å°±èƒ½å®žçŽ°ä¸€ä¸ªåŸºäºŽæœ¬åœ°çš„å¿«ç…§ç³»ç»Ÿã€‚
+ - name: 📓 ä¸€ç«™å¼æ•™ç¨‹
+ url: https://www.yuque.com/kenshin/simpread/pn4bbg
+ about: |
+ 如果ä¸éœ€è¦é…置库方案的è¯ï¼Œä¹Ÿå¯ä»¥ç›´æŽ¥æŸ¥çœ‹ Notion / Obsidian / Logseq çš„ä¸€ç«™å¼æ•™ç¨‹ï¼Œé€‚åˆå–œæ¬¢æ›´çµæ´»æ–¹æ¡ˆçš„用户。
+ - name: 👤 高级账户相关功能
+ url: https://www.yuque.com/kenshin/simpread/xs0gp0
+ about: |
+ 这是简悦的高级账户相关æ“ä½œï¼ŒåŸºæœ¬ä¸Šä½ å‡ºçŽ°çš„é—®é¢˜å¤§éƒ¨åˆ†éƒ½å¯ä»¥é€šè¿‡æ¤æ–¹å¼è§£å†³ã€‚
+ - name: 🔒 首次绑定高级账户ä»å‡ºçŽ°å¸¦ðŸ”’çš„é—®é¢˜
+ url: https://www.yuque.com/kenshin/simpread/xs0gp0
+ about: |
+ 首次å‡çº§ä¸ºé«˜çº§è´¦æˆ·åŽï¼Œè¯·é‡å¯æµè§ˆå™¨ï¼Œå¦‚果没有é‡å¯çš„è¯ï¼Œè¯·ä½¿ç”¨æ¤é“¾æŽ¥è§£å†³ã€‚
+ - name: 1ï¸âƒ£ 如何找回丢失的 UID ï¼ˆé«˜çº§è´¦æˆ·èµ„æ ¼ï¼‰
+ url: https://www.yuque.com/kenshin/simpread/bvcunx
+ about: |
+ 如果ä¸å°å¿ƒä¸¢å¤±äº† UID è¯·é€šè¿‡æ¤æ•™ç¨‹æ‰¾å›žã€‚
+ - name: 2ï¸âƒ£ 找回 UID åŽå¦‚何æ¢å¤é«˜çº§è´¦æˆ·èµ„æ ¼
+ url: https://www.yuque.com/kenshin/simpread/pkq3d1
+ about: |
+ 找回 UID åŽå¯ä½¿ç”¨æ¤æ•™ç¨‹æ¢å¤ä½ çš„é«˜çº§è´¦æˆ·èµ„æ ¼ã€‚
+ - name: 3ï¸âƒ£ 在哪里å¯ä»¥é‡æ–°æ‰¾åˆ° License(兑æ¢ç )
+ url: https://www.yuque.com/kenshin/simpread/hgvw56
+ about: |
+ 找回 UID å‰éœ€è¦çŸ¥é“ä½ çš„ License,一般æ¥è¯´å½“å‡çº§é«˜çº§è´¦æˆ·åŽä¼šè‡ªåŠ¨ä¸‹è½½å«æœ‰é«˜çº§è´¦æˆ· UID 与 License 到本地。
+ - name: 📗 Notion 相关问题
+ url: https://www.yuque.com/kenshin/simpread/wwk65u
+ about: |
+ å¦‚ï¼šæ— æ³•æŽˆæƒåˆ° Notion,使用导入到 Notion 辅助增强æ’件失败ç‰å¸¸è§„性问题。
+ - name: 🆘 æ— æ³•æ‰“å¼€ç®€æ‚¦çš„é€‰é¡¹é¡µæˆ–ç¨åŽè¯»
+ url: https://www.yuque.com/kenshin/simpread/lwuterg3u83sq0b2
+ about: |
+ 如:一般æ¥è¯´åªæœ‰ä½¿ç”¨äº†åŒæ¥åŠ©æ‰‹åŽæ‰ä¼šé‡åˆ°æ¤ç±»é—®é¢˜ï¼Œå¯é€šè¿‡æ¤é“¾æŽ¥è§£å†³ã€‚
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000..0b9f04e6e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,19 @@
+name: ✨ 功能建议或改善
+description: ä½ çš„å»ºè®®ä¼šè®©ç®€æ‚¦å˜å¾—更好
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ä½ çš„æ¯ä¸ªæƒ³æ³•都是对简悦最大的支æŒï¼Œç®€æ‚¦ 60% 的功能都æ¥è‡ªç”¨æˆ·çš„简悦。
+ - type: textarea
+ id: feature
+ attributes:
+ label: 请æè¿°ä½ 的建议或任何内容
+ description: 如有å¯èƒ½è¯·è¯¦ç»†è¯´æ˜Žå®ƒ
+ validations:
+ required: true
+ - type: textarea
+ id: context
+ attributes:
+ label: 补充说明
+ description: 如有å¯èƒ½è¯·è¯´æ˜Žä¸‹è¿™ä¸ªå»ºè®®å…·ä½“使用场景(或如果有这个功能åŽï¼Œä¼šæ”¹å–„ä½ çš„ä»€ä¹ˆæµç¨‹ï¼Ÿ
diff --git a/.github/ISSUE_TEMPLATE/new_site.yml b/.github/ISSUE_TEMPLATE/new_site.yml
new file mode 100644
index 000000000..700ab7bc4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/new_site.yml
@@ -0,0 +1,22 @@
+name: 🔗 新站适é…
+description: æäº¤éœ€è¦é€‚é…的站点
+labels: ["new site"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ 大部分网页都å¯ä»¥æ£å¸¸ä½¿ç”¨ç®€æ‚¦çš„阅读模å¼ï¼Œç®€æ‚¦å®˜æ–¹æ”¶å½•的新站具有大众类型的网站。
+ - type: textarea
+ id: website
+ attributes:
+ label: 需è¦é€‚é…的新站
+ placeholder: 请输入这个站点的 URL,如果这个站的规则比较多,请多帮忙æä¾›ä¸€äº› URL 作为å‚考
+ validations:
+ required: true
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: 有需è¦è¯·æè¿°è¿™ä¸ªç«™çš„æ€§è´¨
+ description: 尤其是英文类型的网站,我需è¦åˆ¤æ–这个站是å¦å…·æœ‰é€‚é…的必è¦ã€‚
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/yinxiang_code.yml b/.github/ISSUE_TEMPLATE/yinxiang_code.yml
new file mode 100644
index 000000000..7aa5ec668
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/yinxiang_code.yml
@@ -0,0 +1,22 @@
+name: 🚑 å°è±¡ç¬”记或代ç 高亮问题
+description: 关于å°è±¡ç¬”记或代ç 高亮的集ä¸åé¦ˆæ¸ é“
+body:
+ - type: markdown
+ attributes:
+ value: |
+ 谢谢帮忙æäº¤ Bug 这会让简悦å˜å¾—更好。
+ - type: dropdown
+ id: browsers
+ attributes:
+ label: 请选择
+ multiple: false
+ options:
+ - å°è±¡ç¬”è®°
+ - 代ç 高亮
+ - type: input
+ id: website
+ attributes:
+ label: å‘生问题的网å€
+ placeholder: 如果任æ„网站å‡å¯çš„è¯ï¼Œè¯·éšä¾¿ç•™ä¸‹ä¸€ä¸ªä½ é‡åˆ°é—®é¢˜çš„地å€
+ validations:
+ required: true
diff --git a/LICENSE b/LICENSE
index 3b3e49cb8..a662e6ee5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,674 @@
-MIT License
-
-Copyright (c) 2016 kenshin
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.

è®©ä½ çž¬é—´è¿›å…¥æ²‰æµ¸å¼é˜…读的扩展,还原阅读的本质,æå‡ä½ 的阅读体验。
为了达到完美的阅读模å¼è¿™ä¸ªå°ç›®æ ‡ ,我适é…了 数百ç§ç±»åž‹ çš„ç½‘ç«™ï¼Œå› æ¤è¯žç”Ÿäº†ç®€æ‚¦ã€‚
+
+
+> 在 1.0.0 版上线之åˆå°±å·²ç»æž„想了æ¤åŠŸèƒ½ï¼Œæ‰€ä»¥åœ¨æž„ç‘æ¤åŠŸèƒ½æ—¶ï¼ŒåŠ å…¥äº†å¾ˆå¤šåªæœ‰ **简悦 · æ ‡æ³¨** æ‰å…·æœ‰çš„功能。
+
+- äº”ç§æ ‡æ³¨é¢œè‰²
+
+- å››ç§æ ‡æ³¨æ ·å¼
+
+- 自动识别 **æ–‡å—** · **图片** · **ä»£ç æ®µ**
- - 导出到生产力工具,包括:`Dropbox` `Onenote` `Google Drive` `å°è±¡ç¬”è®° / Evernote`,详细请看 [æŽˆæƒæœåŠ¡](http://ksria.com/simpread/docs/#/æŽˆæƒæœåŠ¡)
+- **æ— é™å±‚级** çš„æ ‡ç¾ç³»ç»Ÿ
-- åŒæ¥ · ä¸Šä¼ /下载 é…ç½® · åŒæ¥é€‚é…列表 · [å¿«æ·é”®æ”¯æŒ](http://ksria.com/simpread/docs/#/å¿«æ·é”®) ç‰ï¼›
+- æ¯ä¸ªæ ‡ç¾å‡æ”¯æŒå¤‡æ³¨ä¸Žæ ‡ç¾ç³»ç»Ÿ
-- 高级定制,包括:`å³é”®èœå•` `控制æ å¯éšè—` `阅读进度å¯éšè—` `自动进入阅读模å¼` [白åå•](http://ksria.com/simpread/docs/#/FAQ?id=白åå•) ä»¥åŠ [排除列表](http://ksria.com/simpread/docs/#/FAQ?id=排除列表) ç‰
+- 结åˆç®€æ‚¦å¼ºå¤§çš„å‘é€åˆ°ç”Ÿäº§åŠ›å·¥å…·çš„åŠŸèƒ½ï¼Œå¯å°†å½“剿 ‡æ³¨å‘é€åˆ°ç®€æ‚¦æ”¯æŒçš„å„ç§ç”Ÿäº§åЛ工具
-- ç¨åŽè¯»ï¼›
+- è¿žç»æ ‡æ³¨
-#### 截图:
+- [æµ®åŠ¨æ ‡æ³¨æ ](http://ksria.com/simpread/docs/#/æ ‡æ³¨?id=浮动工具æ )
+
+- [æ ‡æ³¨ä¾§æ ](http://ksria.com/simpread/docs/#/æ ‡æ³¨?id=æ ‡æ³¨ä¾§æ )
+
+> 如何使用以åŠè¯¦ç»†å†…容 [请看这里](http://ksria.com/simpread/docs/#/æ ‡æ³¨)
+
+#### ç¨åŽè¯»  
+
+> 简悦 2.0 å¯ç”¨äº†å…¨æ–°çš„ **[ç¨åŽè¯» 2.0](http://ksria.com/simpread/docs/#/ç¨åŽè¯»)**, 相比较之å‰çš„版本,æ¤ç‰ˆæœ¬çš„ç¨åŽè¯»ç®—åšæ˜¯ä¸€ä¸ªçœŸæ£æ„义的ç¨åŽè¯»ã€‚
+
+
+
+> 简悦的ç¨åŽè¯»å€Ÿé‰´äº† ZK 笔记法的一些特点,专门针对信æ¯çš„æ•´åˆå¢žåŠ äº†å¦‚ä¸‹ä¸€äº›æ–°åŠŸèƒ½ï¼š
+
+- [**åŒå‘链接**](http://ksria.com/simpread/docs/#/åŒå‘链接)
+- [**知识图谱**](http://ksria.com/simpread/docs/#/åŒå‘链接?id=图谱)
+- [**Mindmap**](http://ksria.com/simpread/docs/#/ç¨åŽè¯»?id=Mindmap)
+- **多ç§ä¿¡æ¯å±•示方å¼ï¼ˆå¸ƒå±€ï¼‰**:[Evergreen](http://ksria.com/simpread/docs/#/ç¨åŽè¯»-多ç§å¸ƒå±€?id=Evergreen) · [Workflowy](http://ksria.com/simpread/docs/#/ç¨åŽè¯»-多ç§å¸ƒå±€?id=Workflowy) · [Kanban](http://ksria.com/simpread/docs/#/ç¨åŽè¯»-多ç§å¸ƒå±€?id=Kanban)
+- [**è¯»å–æœ¬åœ° HTML**](https://github.com/Kenshin/simpread/discussions/2146)
+
+
+
+
+
+#### åŒæ¥åŠ©æ‰‹  
+
+
+
+> [简悦 · åŒæ¥åŠ©æ‰‹](http://ksria.com/simpread/docs/#/Sync) 是 **éšç€ç®€æ‚¦ 2.1.0 å‘布的一个全新的 Desktop App**,用于对简悦已知功能的补充,以åŠä¼š **æŒç»æä¾›æ›´å¤š** çš„å¯çŽ©æ€§ï¼ŒåŒ…æ‹¬ï¼š
+
+1. **[è‡ªåŠ¨åŒæ¥](http://ksria.com/simpread/docs/#/è‡ªåŠ¨åŒæ¥)**
+2. **å°ä¹¦ç¾**
+3. 导出到文件 **本地的任æ„ä½ç½®**
+4. **原生 PDF · Epub** 导出
+5. **直接å‘é€åˆ°ä½ çš„ Kindle**
+6. 内置解æž
+7. **邮件å‘é€**
+
+åŒæ¥åŠ©æ‰‹çš„ Logo 自于社区用户 [Shawn](https://shawnan.design/) 的设计。
+
+#### æ’件系统 
+
+ > 使用 JavaScript 编写基于 `简悦` çš„æ’件了,请看 [æ’ä»¶ä¸å¿ƒ](https://simpread.ksria.cn/plugins/)
+
+## 全部功能
+
+
+
+
+
-*
+
+
+
+
+
+
-#### 全部功能:
-
+
+
+
+
+
+
-
+
+
+
+ å¦‚ä½•è‡ªå®šä¹‰æ ·å¼ï¼Œè¯¦ç»† 请看这里
+
å¦‚ä½•è‡ªå®šä¹‰æ ·å¼ï¼Œè¯¦ç»† 请看这里
独ä¹ä¹ä¸å¦‚ä¼—ä¹ä¹ï¼ åˆ†äº«ä½ çš„ä¸»é¢˜
本文由 简悦 SimpRead 转ç ï¼ŒåŽŸæ–‡åœ°å€ ${url}
本文由 简悦 SimpRead 转ç ${href}
本文由 简悦 SimpRead 转ç ${href}
[^\r]+?<\/pre>)/gm,function(e,t){var r=t;return(r=r.replace(/^ /gm,"¨0")).replace(/¨0/g,"")}),i.subParser("hashBlock")("\n"+e+"\n
",t,r)}),r.converter._dispatch("blockQuotes.after",e,t,r)}),i.subParser("codeBlocks",function(e,t,r){return e=r.converter._dispatch("codeBlocks.before",e,t,r),e=(e=(e+="¨0").replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g,function(e,a,n){var o=a,s=n,l="\n";return o=i.subParser("outdent")(o,t,r),o=i.subParser("encodeCode")(o,t,r),o=(o=(o=i.subParser("detab")(o,t,r)).replace(/^\n+/g,"")).replace(/\n+$/g,""),t.omitExtraWLInCodeBlocks&&(l=""),o=""+o+l+"
",i.subParser("hashBlock")(o,t,r)+s})).replace(/¨0/,""),r.converter._dispatch("codeBlocks.after",e,t,r)}),i.subParser("codeSpans",function(e,t,r){return void 0===(e=r.converter._dispatch("codeSpans.before",e,t,r))&&(e=""),e=e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,a,n,o){var s=o;return s=(s=s.replace(/^([ \t]*)/g,"")).replace(/[ \t]*$/g,""),s=a+""+(s=i.subParser("encodeCode")(s,t,r))+"",i.subParser("hashHTMLSpans")(s,t,r)}),r.converter._dispatch("codeSpans.after",e,t,r)}),i.subParser("completeHTMLDocument",function(e,t,r){if(!t.completeHTMLDocument)return e;e=r.converter._dispatch("completeHTMLDocument.before",e,t,r);var a="html",n="\n",i="",o='\n',s="",l="";for(var c in void 0!==r.metadata.parsed.doctype&&(n="\n","html"!==(a=r.metadata.parsed.doctype.toString().toLowerCase())&&"html5"!==a||(o='')),r.metadata.parsed)if(r.metadata.parsed.hasOwnProperty(c))switch(c.toLowerCase()){case"doctype":break;case"title":i=""+r.metadata.parsed.title+" \n";break;case"charset":o="html"===a||"html5"===a?'\n':'\n';break;case"language":case"lang":s=' lang="'+r.metadata.parsed[c]+'"',l+='\n';break;default:l+='\n'}return e=n+"\n\n"+i+o+l+"\n\n"+e.trim()+"\n\n",r.converter._dispatch("completeHTMLDocument.after",e,t,r)}),i.subParser("detab",function(e,t,r){return e=(e=(e=(e=(e=(e=r.converter._dispatch("detab.before",e,t,r)).replace(/\t(?=\t)/g," ")).replace(/\t/g,"¨A¨B")).replace(/¨B(.+?)¨A/g,function(e,t){for(var r=t,a=4-r.length%4,n=0;n/g,">"),r.converter._dispatch("encodeAmpsAndAngles.after",e,t,r)}),i.subParser("encodeBackslashEscapes",function(e,t,r){return e=(e=(e=r.converter._dispatch("encodeBackslashEscapes.before",e,t,r)).replace(/\\(\\)/g,i.helper.escapeCharactersCallback)).replace(/\\([`*_{}\[\]()>#+.!~=|-])/g,i.helper.escapeCharactersCallback),r.converter._dispatch("encodeBackslashEscapes.after",e,t,r)}),i.subParser("encodeCode",function(e,t,r){return e=(e=r.converter._dispatch("encodeCode.before",e,t,r)).replace(/&/g,"&").replace(//g,">").replace(/([*_{}\[\]\\=~-])/g,i.helper.escapeCharactersCallback),r.converter._dispatch("encodeCode.after",e,t,r)}),i.subParser("escapeSpecialCharsWithinTagAttributes",function(e,t,r){return e=(e=(e=r.converter._dispatch("escapeSpecialCharsWithinTagAttributes.before",e,t,r)).replace(/<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,function(e){return e.replace(/(.)<\/?code>(?=.)/g,"$1`").replace(/([\\`*_~=|])/g,i.helper.escapeCharactersCallback)})).replace(/-]|-[^>])(?:[^-]|-[^-])*)--)>/gi,function(e){return e.replace(/([\\`*_~=|])/g,i.helper.escapeCharactersCallback)}),r.converter._dispatch("escapeSpecialCharsWithinTagAttributes.after",e,t,r)}),i.subParser("githubCodeBlocks",function(e,t,r){return t.ghCodeBlocks?(e=r.converter._dispatch("githubCodeBlocks.before",e,t,r),e=(e=(e+="¨0").replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g,function(e,a,n,o){var s=t.omitExtraWLInCodeBlocks?"":"\n";return o=i.subParser("encodeCode")(o,t,r),o=(o=(o=i.subParser("detab")(o,t,r)).replace(/^\n+/g,"")).replace(/\n+$/g,""),o=""+o+s+"
",o=i.subParser("hashBlock")(o,t,r),"\n\n¨G"+(r.ghCodeBlocks.push({text:e,codeblock:o})-1)+"G\n\n"})).replace(/¨0/,""),r.converter._dispatch("githubCodeBlocks.after",e,t,r)):e}),i.subParser("hashBlock",function(e,t,r){return e=(e=r.converter._dispatch("hashBlock.before",e,t,r)).replace(/(^\n+|\n+$)/g,""),e="\n\n¨K"+(r.gHtmlBlocks.push(e)-1)+"K\n\n",r.converter._dispatch("hashBlock.after",e,t,r)}),i.subParser("hashCodeTags",function(e,t,r){return e=r.converter._dispatch("hashCodeTags.before",e,t,r),e=i.helper.replaceRecursiveRegExp(e,function(e,a,n,o){var s=n+i.subParser("encodeCode")(a,t,r)+o;return"¨C"+(r.gHtmlSpans.push(s)-1)+"C"},"]*>","","gim"),r.converter._dispatch("hashCodeTags.after",e,t,r)}),i.subParser("hashElement",function(e,t,r){return function(e,t){var a=t;return a=(a=(a=a.replace(/\n\n/g,"\n")).replace(/^\n/,"")).replace(/\n+$/g,""),"\n\n¨K"+(r.gHtmlBlocks.push(a)-1)+"K\n\n"}}),i.subParser("hashHTMLBlocks",function(e,t,r){e=r.converter._dispatch("hashHTMLBlocks.before",e,t,r);var a=["pre","div","h1","h2","h3","h4","h5","h6","blockquote","table","dl","ol","ul","script","noscript","form","fieldset","iframe","math","style","section","header","footer","nav","article","aside","address","audio","canvas","figure","hgroup","output","video","p"],n=function(e,t,a,n){var i=e;return-1!==a.search(/\bmarkdown\b/)&&(i=a+r.converter.makeHtml(t)+n),"\n\n¨K"+(r.gHtmlBlocks.push(i)-1)+"K\n\n"};t.backslashEscapesHTMLTags&&(e=e.replace(/\\<(\/?[^>]+?)>/g,function(e,t){return"<"+t+">"}));for(var o=0;o<"+a[o]+"\\b[^>]*>)","im"),c="<"+a[o]+"\\b[^>]*>",u=""+a[o]+">";-1!==(s=i.helper.regexIndexOf(e,l));){var d=i.helper.splitAtIndex(e,s),h=i.helper.replaceRecursiveRegExp(d[1],n,c,u,"im");if(h===d[1])break;e=d[0].concat(h)}return e=e.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,i.subParser("hashElement")(e,t,r)),e=(e=i.helper.replaceRecursiveRegExp(e,function(e){return"\n\n¨K"+(r.gHtmlBlocks.push(e)-1)+"K\n\n"},"^ {0,3}\x3c!--","--\x3e","gm")).replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,i.subParser("hashElement")(e,t,r)),r.converter._dispatch("hashHTMLBlocks.after",e,t,r)}),i.subParser("hashHTMLSpans",function(e,t,r){function a(e){return"¨C"+(r.gHtmlSpans.push(e)-1)+"C"}return e=(e=(e=(e=(e=r.converter._dispatch("hashHTMLSpans.before",e,t,r)).replace(/<[^>]+?\/>/gi,function(e){return a(e)})).replace(/<([^>]+?)>[\s\S]*?<\/\1>/g,function(e){return a(e)})).replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g,function(e){return a(e)})).replace(/<[^>]+?>/gi,function(e){return a(e)}),r.converter._dispatch("hashHTMLSpans.after",e,t,r)}),i.subParser("unhashHTMLSpans",function(e,t,r){e=r.converter._dispatch("unhashHTMLSpans.before",e,t,r);for(var a=0;a]*>\\s*]*>","^ {0,3}\\s*
","gim"),r.converter._dispatch("hashPreCodeTags.after",e,t,r)}),i.subParser("headers",function(e,t,r){function a(e){var a,n;if(t.customizedHeaderId){var o=e.match(/\{([^{]+?)}\s*$/);o&&o[1]&&(e=o[1])}return a=e,n=i.helper.isString(t.prefixHeaderId)?t.prefixHeaderId:!0===t.prefixHeaderId?"section-":"",t.rawPrefixHeaderId||(a=n+a),a=t.ghCompatibleHeaderId?a.replace(/ /g,"-").replace(/&/g,"").replace(/¨T/g,"").replace(/¨D/g,"").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g,"").toLowerCase():t.rawHeaderId?a.replace(/ /g,"-").replace(/&/g,"&").replace(/¨T/g,"¨").replace(/¨D/g,"$").replace(/["']/g,"-").toLowerCase():a.replace(/[^\w]/g,"").toLowerCase(),t.rawPrefixHeaderId&&(a=n+a),r.hashLinkCounts[a]?a=a+"-"+r.hashLinkCounts[a]++:r.hashLinkCounts[a]=1,a}e=r.converter._dispatch("headers.before",e,t,r);var n=isNaN(parseInt(t.headerLevelStart))?1:parseInt(t.headerLevelStart),o=t.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,s=t.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm;e=(e=e.replace(o,function(e,o){var s=i.subParser("spanGamut")(o,t,r),l=t.noHeaderId?"":' id="'+a(o)+'"',c=""+s+" ";return i.subParser("hashBlock")(c,t,r)})).replace(s,function(e,o){var s=i.subParser("spanGamut")(o,t,r),l=t.noHeaderId?"":' id="'+a(o)+'"',c=n+1,u=""+s+" ";return i.subParser("hashBlock")(u,t,r)});var l=t.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;return e=e.replace(l,function(e,o,s){var l=s;t.customizedHeaderId&&(l=s.replace(/\s?\{([^{]+?)}\s*$/,""));var c=i.subParser("spanGamut")(l,t,r),u=t.noHeaderId?"":' id="'+a(s)+'"',d=n-1+o.length,h=""+c+" ";return i.subParser("hashBlock")(h,t,r)}),r.converter._dispatch("headers.after",e,t,r)}),i.subParser("horizontalRule",function(e,t,r){e=r.converter._dispatch("horizontalRule.before",e,t,r);var a=i.subParser("hashBlock")("
",t,r);return e=(e=(e=e.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,a),r.converter._dispatch("horizontalRule.after",e,t,r)}),i.subParser("images",function(e,t,r){function a(e,t,a,n,o,s,l,c){var u=r.gUrls,d=r.gTitles,h=r.gDimensions;if(a=a.toLowerCase(),c||(c=""),e.search(/\(\s*>? ?(['"].*['"])?\)$/m)>-1)n="";else if(""===n||null===n){if(""!==a&&null!==a||(a=t.toLowerCase().replace(/ ?\n/g," ")),n="#"+a,i.helper.isUndefined(u[a]))return e;n=u[a],i.helper.isUndefined(d[a])||(c=d[a]),i.helper.isUndefined(h[a])||(o=h[a].width,s=h[a].height)}t=t.replace(/"/g,""").replace(i.helper.regexes.asteriskDashAndColon,i.helper.escapeCharactersCallback);var f='
"}return e=(e=(e=(e=(e=(e=r.converter._dispatch("images.before",e,t,r)).replace(/!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,a)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,function(e,t,r,n,i,o,s,l){return a(e,t,r,n=n.replace(/\s/g,""),i,o,0,l)})).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,a)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,a)).replace(/!\[([^\[\]]+)]()()()()()/g,a),r.converter._dispatch("images.after",e,t,r)}),i.subParser("italicsAndBold",function(e,t,r){function a(e,t,r){return t+e+r}return e=r.converter._dispatch("italicsAndBold.before",e,t,r),e=t.literalMidWordUnderscores?(e=(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,t){return a(t,"","")})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,t){return a(t,"","")})).replace(/\b_(\S[\s\S]*?)_\b/g,function(e,t){return a(t,"","")}):(e=(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e})).replace(/__(\S[\s\S]*?)__/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e})).replace(/_([^\s_][\s\S]*?)_/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e}),e=t.literalMidWordAsterisks?(e=(e=e.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g,function(e,t,r){return a(r,t+"","")})).replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g,function(e,t,r){return a(r,t+"","")})).replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g,function(e,t,r){return a(r,t+"","")}):(e=(e=e.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e})).replace(/\*\*(\S[\s\S]*?)\*\*/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e})).replace(/\*([^\s*][\s\S]*?)\*/g,function(e,t){return/\S$/.test(t)?a(t,"",""):e}),r.converter._dispatch("italicsAndBold.after",e,t,r)}),i.subParser("lists",function(e,t,r){function a(e,a){r.gListLevel++,e=e.replace(/\n{2,}$/,"\n");var n=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,o=/\n[ \t]*\n(?!¨0)/.test(e+="¨0");return t.disableForced4SpacesIndentedSublists&&(n=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm),e=(e=e.replace(n,function(e,a,n,s,l,c,u){u=u&&""!==u.trim();var d=i.subParser("outdent")(l,t,r),h="";return c&&t.tasklists&&(h=' class="task-list-item" style="list-style-type: none;"',d=d.replace(/^[ \t]*\[(x|X| )?]/m,function(){var e='"})),d=d.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g,function(e){return"¨A"+e}),a||d.search(/\n{2,}/)>-1?(d=i.subParser("githubCodeBlocks")(d,t,r),d=i.subParser("blockGamut")(d,t,r)):(d=(d=i.subParser("lists")(d,t,r)).replace(/\n$/,""),d=(d=i.subParser("hashHTMLBlocks")(d,t,r)).replace(/\n\n+/g,"\n\n"),d=o?i.subParser("paragraphs")(d,t,r):i.subParser("spanGamut")(d,t,r)),""+(d=d.replace("¨A",""))+" \n"})).replace(/¨0/g,""),r.gListLevel--,a&&(e=e.replace(/\s+$/,"")),e}function n(e,t){if("ol"===t){var r=e.match(/^ *(\d+)\./);if(r&&"1"!==r[1])return' start="'+r[1]+'"'}return""}function o(e,r,i){var o=t.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,s=t.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,l="ul"===r?o:s,c="";if(-1!==e.search(l))!function t(u){var d=u.search(l),h=n(e,r);-1!==d?(c+="\n\n<"+r+h+">\n"+a(u.slice(0,d),!!i)+""+r+">\n",l="ul"==(r="ul"===r?"ol":"ul")?o:s,t(u.slice(d))):c+="\n\n<"+r+h+">\n"+a(u,!!i)+""+r+">\n"}(e);else{var u=n(e,r);c="\n\n<"+r+u+">\n"+a(e,!!i)+""+r+">\n"}return c}return e=r.converter._dispatch("lists.before",e,t,r),e+="¨0",e=(e=r.gListLevel?e.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,t,r){return o(t,r.search(/[*+-]/g)>-1?"ul":"ol",!0)}):e.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,t,r,a){return o(r,a.search(/[*+-]/g)>-1?"ul":"ol",!1)})).replace(/¨0/,""),r.converter._dispatch("lists.after",e,t,r)}),i.subParser("metadata",function(e,t,r){function a(e){r.metadata.raw=e,(e=(e=e.replace(/&/g,"&").replace(/"/g,""")).replace(/\n {4}/g," ")).replace(/^([\S ]+): +([\s\S]+?)$/gm,function(e,t,a){return r.metadata.parsed[t]=a,""})}return t.metadata?(e=(e=(e=(e=r.converter._dispatch("metadata.before",e,t,r)).replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/,function(e,t,r){return a(r),"¨M"})).replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/,function(e,t,n){return t&&(r.metadata.format=t),a(n),"¨M"})).replace(/¨M/g,""),e=r.converter._dispatch("metadata.after",e,t,r)):e}),i.subParser("outdent",function(e,t,r){return e=(e=(e=r.converter._dispatch("outdent.before",e,t,r)).replace(/^(\t|[ ]{1,4})/gm,"¨0")).replace(/¨0/g,""),r.converter._dispatch("outdent.after",e,t,r)}),i.subParser("paragraphs",function(e,t,r){for(var a=(e=(e=(e=r.converter._dispatch("paragraphs.before",e,t,r)).replace(/^\n+/g,"")).replace(/\n+$/g,"")).split(/\n{2,}/g),n=[],o=a.length,s=0;s=0?n.push(l):l.search(/\S/)>=0&&(l=(l=i.subParser("spanGamut")(l,t,r)).replace(/^([ \t]*)/g,""),l+="
",n.push(l))}for(o=n.length,s=0;s]*>\s*]*>/.test(u)&&(d=!0)}n[s]=u}return e=(e=(e=n.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,""),r.converter._dispatch("paragraphs.after",e,t,r)}),i.subParser("runExtension",function(e,t,r,a){if(e.filter)t=e.filter(t,a.converter,r);else if(e.regex){var n=e.regex;n instanceof RegExp||(n=new RegExp(n,"g")),t=t.replace(n,e.replace)}return t}),i.subParser("spanGamut",function(e,t,r){return e=r.converter._dispatch("spanGamut.before",e,t,r),e=i.subParser("codeSpans")(e,t,r),e=i.subParser("escapeSpecialCharsWithinTagAttributes")(e,t,r),e=i.subParser("encodeBackslashEscapes")(e,t,r),e=i.subParser("images")(e,t,r),e=i.subParser("anchors")(e,t,r),e=i.subParser("autoLinks")(e,t,r),e=i.subParser("simplifiedAutoLinks")(e,t,r),e=i.subParser("emoji")(e,t,r),e=i.subParser("underline")(e,t,r),e=i.subParser("italicsAndBold")(e,t,r),e=i.subParser("strikethrough")(e,t,r),e=i.subParser("ellipsis")(e,t,r),e=i.subParser("hashHTMLSpans")(e,t,r),e=i.subParser("encodeAmpsAndAngles")(e,t,r),t.simpleLineBreaks?/\n\n¨K/.test(e)||(e=e.replace(/\n+/g,"
\n")):e=e.replace(/ +\n/g,"
\n"),r.converter._dispatch("spanGamut.after",e,t,r)}),i.subParser("strikethrough",function(e,t,r){return t.strikethrough&&(e=(e=r.converter._dispatch("strikethrough.before",e,t,r)).replace(/(?:~){2}([\s\S]+?)(?:~){2}/g,function(e,a){return function(e){return t.simplifiedAutoLink&&(e=i.subParser("simplifiedAutoLinks")(e,t,r)),""+e+""}(a)}),e=r.converter._dispatch("strikethrough.after",e,t,r)),e}),i.subParser("stripLinkDefinitions",function(e,t,r){var a=function(e,a,n,o,s,l,c){return a=a.toLowerCase(),n.match(/^data:.+?\/.+?;base64,/)?r.gUrls[a]=n.replace(/\s/g,""):r.gUrls[a]=i.subParser("encodeAmpsAndAngles")(n,t,r),l?l+c:(c&&(r.gTitles[a]=c.replace(/"|'/g,""")),t.parseImgDimensions&&o&&s&&(r.gDimensions[a]={width:o,height:s}),"")};return(e=(e=(e+="¨0").replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm,a)).replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,a)).replace(/¨0/,"")}),i.subParser("tables",function(e,t,r){function a(e){return/^:[ \t]*--*$/.test(e)?' style="text-align:left;"':/^--*[ \t]*:[ \t]*$/.test(e)?' style="text-align:right;"':/^:[ \t]*--*[ \t]*:$/.test(e)?' style="text-align:center;"':""}function n(e,a){var n="";return e=e.trim(),(t.tablesHeaderId||t.tableHeaderId)&&(n=' id="'+e.replace(/ /g,"_").toLowerCase()+'"'),""+(e=i.subParser("spanGamut")(e,t,r))+" \n"}function o(e,a){return""+i.subParser("spanGamut")(e,t,r)+" \n"}function s(e){var s,l=e.split("\n");for(s=0;s\n\n\n",n=0;n\n";for(var i=0;i \n"}return r+" \n\n"}(h,p)}return t.tables?(e=(e=(e=(e=r.converter._dispatch("tables.before",e,t,r)).replace(/\\(\|)/g,i.helper.escapeCharactersCallback)).replace(/^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,s)).replace(/^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm,s),r.converter._dispatch("tables.after",e,t,r)):e}),i.subParser("underline",function(e,t,r){return t.underline?(e=r.converter._dispatch("underline.before",e,t,r),e=(e=t.literalMidWordUnderscores?(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,t){return""+t+""})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,t){return""+t+""}):(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,t){return/\S$/.test(t)?""+t+"":e})).replace(/__(\S[\s\S]*?)__/g,function(e,t){return/\S$/.test(t)?""+t+"":e})).replace(/(_)/g,i.helper.escapeCharactersCallback),e=r.converter._dispatch("underline.after",e,t,r)):e}),i.subParser("unescapeSpecialChars",function(e,t,r){return e=(e=r.converter._dispatch("unescapeSpecialChars.before",e,t,r)).replace(/¨E(\d+)E/g,function(e,t){var r=parseInt(t);return String.fromCharCode(r)}),r.converter._dispatch("unescapeSpecialChars.after",e,t,r)}),i.subParser("makeMarkdown.blockquote",function(e,t){var r="";if(e.hasChildNodes())for(var a=e.childNodes,n=a.length,o=0;o "+(r=r.trim()).split("\n").join("\n> ")}),i.subParser("makeMarkdown.codeBlock",function(e,t){var r=e.getAttribute("language"),a=e.getAttribute("precodenum");return"```"+r+"\n"+t.preList[a]+"\n```"}),i.subParser("makeMarkdown.codeSpan",function(e){return"`"+e.innerHTML+"`"}),i.subParser("makeMarkdown.emphasis",function(e,t){var r="";if(e.hasChildNodes()){r+="*";for(var a=e.childNodes,n=a.length,o=0;o",e.hasAttribute("width")&&e.hasAttribute("height")&&(t+=" ="+e.getAttribute("width")+"x"+e.getAttribute("height")),e.hasAttribute("title")&&(t+=' "'+e.getAttribute("title")+'"'),t+=")"),t}),i.subParser("makeMarkdown.links",function(e,t){var r="";if(e.hasChildNodes()&&e.hasAttribute("href")){var a=e.childNodes,n=a.length;r="[";for(var o=0;o<"+e.getAttribute("href")+">",e.hasAttribute("title")&&(r+=' "'+e.getAttribute("title")+'"'),r+=")"}return r}),i.subParser("makeMarkdown.list",function(e,t,r){var a="";if(!e.hasChildNodes())return"";for(var n=e.childNodes,o=n.length,s=e.getAttribute("start")||1,l=0;l"+t.preList[r]+" "}),i.subParser("makeMarkdown.strikethrough",function(e,t){var r="";if(e.hasChildNodes()){r+="~~";for(var a=e.childNodes,n=a.length,o=0;o",auto:!1,exclude:[]};"remote"==e&&(r.include="",r.html=$("body pre").html().replace(/\n/gi,"
"));return!$("title").html()&&$("head").append(""+decodeURI(t.replace(".txt",""))+" "),r}();if($($("body").children()[0]).is("pre")&&(v(location.href,"file://**/*.md")||v(location.href,"http*://**/*.md")))return function(){var t=location.pathname.split("/").pop(),e={name:"txtread::"+("file:"==location.protocol?"local":"remote"),title:"",desc:"",include:"",auto:!1,exclude:[]},r=(new y.default.Converter).makeHtml($("body pre").text());return e.html=r,!$("title").html()&&$("head").append(""+decodeURI(t.replace(".md",""))+" "),e}();var t=/<\S+ (class|id)=("|')?[\w-_=;:' ]+("|')?>?$|<[^/][-_a-zA-Z0-9]+>?$/gi,e={name:$("meta[name='simpread:name']").attr("content"),url:$("meta[name='simpread:url']").attr("content"),title:$("meta[name='simpread:title']").attr("content"),desc:$("meta[name='simpread:desc']").attr("content"),include:$("meta[name='simpread:include']").attr("content"),exp:$("meta[name='simpread:exclude']").attr("content"),auto:$("meta[name='simpread:auto']").attr("content"),exclude:[]};if(e.name&&e.include){if(e.url&&!v(location.href,e.url))return;!e.title&&(e.title=""),!e.desc&&(e.desc=""),!e.exp&&(e.exp=""),e.name="metaread::"+e.name,e.auto="true"==e.auto;var r=["title","desc","include","exp"].findIndex(function(r){return""!=e[r]&&!e[r].match(t)});return e.exclude.push(e.exp),delete e.exp,-1==r?e:void 0}return}();if(this.current.url=this.url,n)this.current.auto=n.auto,this.current.url=n.url,delete n.auto,delete n.url,this.current.site=r({},n),this.current.site.name.startsWith("metaread::")&&(this.state="meta"),this.current.site.name.startsWith("txtread::")&&(this.state="txt");else if(_("local",new Map(this.sites.local),this.url,e),_("global",new Map(this.sites.global),this.url,e),_("person",new Map(this.sites.person),this.url,e),_("custom",new Map(this.sites.custom),this.url,e),e.length>0){var i=void 0;if(e.forEach(function(e){e[1].active&&(i=e,t.current.url=i[0],t.current.site=t.Safesite(r({},i[1]),i[2],i[0]),t.state="adapter")}),!i){var a=e[0];a[1].active=!0,this.current.url=a[0],this.current.site=this.Safesite(r({},a[1]),a[2],a[0]),this.state="adapter"}}else{var o=function(){if(location.pathname.includes("thread")||location.pathname.includes("forum.php")){if($(".t_f").length>0&&$(".favatar").find(".authi").length>0&&$(".avatar").find("img").length>0)return{avatar:[{name:"[[{$('.favatar').find('.authi')}]]"},{url:"[[{$('.avatar').find('img')}]]"}],include:"[[{$('.t_f')}]]"}}else if(/\/t\/[\w-]+\/\d+/.test(location.pathname)&&$("meta[name=generator]").attr("content").includes("discourse"))return{avatar:[{name:"[[{$('.topic-avatar').find('.a[data-user-card]')}]]"},{url:"[[{$('.topic-avatar').find('img')}]]"}],include:"[[{$('.cooked')}]]"};return-1}();-1!=o?(this.Newmultisite("read",o),this.state="temp"):this.Readability()}this.current.site.matching=e}},{key:"Addsites",value:function(t){var e=0;if(0==this.sites.global.length)this.sites.global=this.Formatsites(t),e=this.sites.global.length;else{var r=function(t,e){var r=new Map(e),n=[].concat(o(r.keys())),i=0;return t.map(function(t){n.includes(t[0])?n.includes(t[0]):i++}),{count:i,newsites:t}}(this.Formatsites(t),this.sites.global);e=r.count,this.sites.global=r.newsites}return e}},{key:"Addlocalsites",value:function(t){return this.sites.local=[].concat(o(t)),this.sites.local}},{key:"Addallsites",value:function(t){return this.sites={global:[].concat(o(t.global)),person:[].concat(o(t.person)),custom:[].concat(o(t.custom)),local:[].concat(o(t.local))},this.sites}},{key:"Newsite",value:function(t,e,n){var i={mode:t,url:window.location.href,site:{name:"tempread::"+window.location.host,title:" ",desc:"[[{$('meta[name=Description]').attr('content')||$('meta[name=description]').attr('content')}]]",include:"",exclude:[]}};e&&(i.site.html=e),this.current.mode=i.mode,this.current.url=i.url,this.current.site=this.Safesite(r({},i.site),"local",i.url),n&&(this.current.site.excerpt=n)}},{key:"Newmultisite",value:function(t,e){var n={mode:t,url:window.location.href,site:{name:"tempread::"+window.location.host,title:" ",desc:"",include:e.include,exclude:[],avatar:e.avatar}};this.current.mode=n.mode,this.current.url=n.url,this.current.site=this.Safesite(r({},n.site),"local",n.url)}},{key:"Updatesite",value:function(t,e,r){var n=this.sites[t].findIndex(function(t){return t[0]==e});-1==n&&(n=this.sites[t].length),this.sites[t].splice(n,1,r)}},{key:"Deletesite",value:function(t,e,r){var n=this.sites[t].findIndex(function(t){return t[0]==e});-1!=n&&this.sites[t].splice(n,1),r(n)}},{key:"Safesite",value:function(t,e,r){return t.url=r,t.target=e,""==t.name&&(t.name="tempread::"),(!t.avatar||0==t.avatar.length)&&(t.avatar=[{name:""},{url:""}]),(!t.paging||0==t.paging.length)&&(t.paging=[{prev:""},{next:""}]),t}},{key:"Cleansite",value:function(t){return delete t.url,delete t.html,delete t.target,delete t.matching,t.avatar&&t.avatar.length>0&&""==t.avatar[0].name&&delete t.avatar,t.paging&&t.paging.length>0&&""==t.paging[0].prev&&delete t.paging,t}},{key:"Formatsites",value:function(t){var e=new Map,r=!0,n=!1,i=void 0;try{for(var a,l=t.sites[Symbol.iterator]();!(r=(a=l.next()).done);r=!0){var u=a.value;if(0==O(u)){var s=u.url;delete u.url,e.set(s,u)}}}catch(t){n=!0,i=t}finally{try{!r&&l.return&&l.return()}finally{if(n)throw i}}return[].concat(o(e))}},{key:"Clearsites",value:function(t){t?this.sites[t]=[]:this.sites={global:[],custom:[],local:[]}}},{key:"Origins",value:function(t){var e=t.origins.map(function(t){return t.url});return(e=new Set(this.origins.concat(e))).forEach(function(t){""!=t.trim()&&t.trim().startsWith("http")&&t.trim().endsWith(".json")||e.delete(t)}),this.origins=[].concat(o(e)),this.origins}},{key:"Addorigins",value:function(t){return this.sites.custom=[].concat(o(t)),this.sites.custom}},{key:"Clearorigins",value:function(){var t=this.sites.custom.length;return this.sites.custom=[],t}}]),n}();function x(){var t=$("body"),e=!0,r=!1,n=void 0;try{for(var i,a=["[itemprop='articleBody']","article",".post-content",".entry-content",".post-article",".content-post",".article-entry",".article-content",".article-body",".markdown-body",".post",".content"][Symbol.iterator]();!(e=(i=a.next()).done);e=!0){var o=i.value,l=t.find(o);if(l.length>0)return l}}catch(t){r=!0,n=t}finally{try{!e&&a.return&&a.return()}finally{if(r)throw n}}return-1}function k(){var t=document.location,e=(t.href,t.host,t.protocol,t.host,t.protocol.substr(0,t.protocol.indexOf(":")),t.protocol,t.host,t.pathname.substr(0,t.pathname.lastIndexOf("/")+1),new g.Readability(document.cloneNode(!0)).parse());return e}function _(t,e,r){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:[],i=function(t){var e=t.replace("www.","").match(/\.\S+\.\S+/g);return e?e[0].substr(1):t.replace("www.","")},a=u(b),s=[].concat(o(e.keys())),c=r.match(/[.a-zA-z0-9-_]+/g)[1].replace("www.",""),h=i(a.hostname),d=function(){return"/"==a.pathname||/\/(default|index|portal).[0-9a-zA-Z]+$/.test(a.pathname)},f=!0,p=!1,m=void 0;try{for(var g,y=s[Symbol.iterator]();!(f=(g=y.next()).done);f=!0){var w=g.value,x=e.get(w).name,$=i(x);w.startsWith("[[/")&&w.endsWith("/]]")&&new RegExp(w.replace(/^\[\[\/|\/\]\]/g,"")).test(location.href)?n.push([w,l(e.get(w)),t]):d()||w.endsWith("*")||w.replace(/^http[s]?:/,"")!=r.replace(/^http[s]?:/,"")?w.match(/\*/g)&&1==w.match(/\*/g).length&&!d()&&w.endsWith("*")&&c.includes($)&&h==$&&r.includes(x)?n.push([w,l(e.get(w)),t]):v(a.origin+a.pathname,w)&&n.push([w,l(e.get(w)),t]):n.push([w,l(e.get(w)),t])}}catch(t){p=!0,m=t}finally{try{!f&&y.return&&y.return()}finally{if(p)throw m}}}function O(t){if(!t.name||!t.url||!t.include)return-1;if(-1==s(t.title)[0]||-1==s(t.include)[0]||-1==s(t.desc)[0])return-2;if(t.paging){if(2!=t.paging.length)return-3;if(!t.paging[0].prev)return-4;if(!t.paging[1].next)return-5;if(-1==s(t.paging[0].prev)[0]||-1==s(t.paging[1].next)[0])return-6}if(t.avatar){if(2!=t.avatar.length)return-7;if(!t.avatar[0].name)return-8;if(!t.avatar[1].url)return-9;if(-1==s(t.avatar[0].name)[0]||-1==s(t.avatar[1].url)[0])return-10}return 0}function j(t){var e=t.replace(' ',""),r=$(e)[0],n=r.outerHTML.replace(r.innerHTML,""),i=$(n)[0],a=i.tagName.toLowerCase(),o=i.className;return{id:i.id,cls:o,tag:a}}function S(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text",r=$("html");if(h(t)){var n=d(t),i=a(n,2),o=i[0],l=i[1];0==l?t=o:3==l?t=M(r.find(o)):4==l&&(t=o.html())}else"html"==e?t=M(r.find(t)):"multi"==e||(t=r.find(t).text().trim());return t}function M(t){var e="";switch(t.length){case 0:e=" ";break;case 1:e=t.html().trim();break;default:e=t.map(function(t,e){return $(e).html()}).get().join("
")}return e}return function(r){function o(e){t(this,o);var r=i(this,(o.__proto__||Object.getPrototypeOf(o)).call(this,e));return r.version="0.0.4 build 0111",r.org_url=location.href,r.html={},r.plugin={},r.pure=!1,r.cleanup=!1,r}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,w),e(o,[{key:"Exist",value:function(){return this.org_url==location.href}},{key:"AddPlugin",value:function(t){this.plugin={minimatch:t.minimatch,pangu:t.pangu,beautify:t.beautify,stylesheet:t.style,rdability:t.rdability,markdown:t.markdown},n(o.prototype.__proto__||Object.getPrototypeOf(o.prototype),"SetMinimatch",this).call(this,this.plugin.minimatch),n(o.prototype.__proto__||Object.getPrototypeOf(o.prototype),"SetRdability",this).call(this,this.plugin.rdability),n(o.prototype.__proto__||Object.getPrototypeOf(o.prototype),"SetMarkdown",this).call(this,this.plugin.markdown)}},{key:"ReadMode",value:function(){var t,e,r,n,i;this.html=(t=this.current.site,e=l(t),r=c(""==t.title?"":t.title),n=c(t.desc),i=c(t.include),e.title=""==t.title||" "==t.title?$("head title").text():S(r),e.desc=function(t){if(void 0==t)return t;var e=t.length,r=t.indexOf("。")+1;return e>100&&(t=r>0?t.substr(0,r):t.substr(0,101)+"......"),t}(t.excerpt?t.excerpt:S(n)),e.include=""==t.include&&""!=t.html?t.html:S(i,"html"),e.avatar&&e.avatar.length>0&&""==e.avatar[0].name&&delete e.avatar,e.paging&&e.paging.length>0&&""==e.paging[0].prev&&delete e.paging,e.avatar&&e.avatar.forEach(function(t){var e=Object.keys(t).join(),r=t[e];t[e]=S(c(r),"html")}),e.paging&&e.paging.forEach(function(t){var e=Object.keys(t).join(),r=t[e];t[e]=S(c(r))}),e)}},{key:"TempMode",value:function(t,e){this.state="temp",this.dom=e,this.Newsite(t,e.outerHTML)}},{key:"GetDom",value:function(t,e){return S(c(t),e)}},{key:"Include",value:function(){var t=this.current.site.include,e=[],r=c(t);try{if(h(r)){var n=d(t),i=a(n,2),o=i[0],l=i[1];0==l?(t=t.replace(/\[\[{\$\(|}\]\]|\).html\(\)/g,""),e=$(d("[[["+t+"]]]")[0])):3==l&&(e=o)}else r&&(e=$("body").find(r))}catch(t){}return e}},{key:"Exclude",value:function(t){return function(t,e){var r=[],n="",i=!0,o=!1,l=void 0;try{for(var u,s=e[Symbol.iterator]();!(i=(u=s.next()).done);i=!0){var f=u.value;if(h(f)){var p=d(f),m=a(p,2),v=m[0],g=m[1];if(1==g)n=v;else if(2==g){var y=t.html().match(new RegExp(v,"g"));if(y&&y.length>0){var b=y.join("");n="*["+b+"]"}else n=void 0}else 3==g?v.remove():4==g&&v.remove()}else n=c(f);n&&r.push(n)}}catch(t){o=!0,l=t}finally{try{!i&&s.return&&s.return()}finally{if(o)throw l}}return r.join(",")}(t,this.current.site.exclude)}},{key:"Beautify",value:function(t){0!=t.children().length&&this.plugin.beautify&&(this.plugin.beautify.before(this.current.site.name,t),this.cleanup&&this.plugin.beautify.cleanHTML(t,this.pure,this.isMathJax()),this.plugin.beautify.specbeautify(this.current.site.name,t),this.plugin.beautify.removeSpareTag(this.current.site.name,t),this.plugin.beautify.htmlbeautify(t),this.plugin.beautify.commbeautify(this.current.site.name,t))}},{key:"Format",value:function(t){this.plugin.pangu&&this.plugin.pangu.spacingElementByClassName(t)}},{key:"Utils",value:function(){return{dom2Xpath:f,xPath2Dom:p}}}]),o}()});
diff --git a/src/vender/puread/util.js b/src/vender/puread/util.js
deleted file mode 100644
index 94116d2b3..000000000
--- a/src/vender/puread/util.js
+++ /dev/null
@@ -1,141 +0,0 @@
-console.log( "=== PureRead: Util load ===" )
-
-/**
- * Deep clone object
- *
- * @param {object} target object
- * @return {object} new target object
- */
-function clone( target ) {
- return $.extend( true, {}, target );
-}
-
-/**
- * Get URI
- *
- * @return {string} e.g. current site url is http://www.cnbeta.com/articles/1234.html return http://www.cnbeta.com/articles/
- */
-function getURI() {
- const name = (pathname) => {
- pathname = pathname != "/" && pathname.endsWith("/") ? pathname = pathname.replace( /\/$/, "" ) : pathname;
- return pathname.replace( /\/[%@#.~a-zA-Z0-9_-]+$|^\/$/g, "" );
- },
- path = name( window.location.pathname );
- return `${ window.location.protocol }//${ window.location.hostname }${ path }/`;
-}
-
-/**
- * Verify html
- *
- * @param {string} input include html tag, e.g.:
-
- *
- * @return {array} 0: int include ( -1: failï¼› 0: empty html; 1: success; 2: special tag )
- * 1: result
- */
-function verifyHtml( html ) {
- if ( html == "" ) return [ 0, html ];
- else if ( specTest( html )) return [ 2, html ];
- const item = html.match( /<\S+ (class|id)=("|')?[\w-_=;:' ]+("|')?>?$|<[^/][-_a-zA-Z0-9]+>?$/ig );
- if ( item && item.length > 0 ) {
- return [ 1, item ];
- } else {
- return [ -1, undefined ];
- }
-}
-
-/**
- * Conver html to jquery object
- *
- * @param {string} input include html tag, e.g.:
-
- *
- * @return {string} formatting e.g.:
- h2#news_title
- div.introduction
- div.content
- div.clearfix
- div.rating_box
- span
- special tag, @see specTest
- e.g. [['â–½']] [[[$('.article-btn')]]]
- [[/src=\\S+(342459.png)\\S+'/]] [[{$('.content').html()}]]
- *
- */
-function selector( html ) {
- const [ code, item ] = verifyHtml( html );
- if ( code == 2 ) return html;
- else if ( code == 1 ) {
- let [tag, prop, value] = item[0].trim().replace( /['"<>]/g, "" ).replace( / /ig, "=" ).split( "=" ); // ["h2", "class", "title"]
- if ( !prop ) prop = tag;
- else if ( prop.toLowerCase() === "class") prop = `${tag}.${value}`;
- else if ( prop.toLowerCase() === "id" ) prop = `${tag}#${value}`;
- return prop;
- } else {
- return null;
- }
-}
-
-/**
- * Verify special action, action include:
- - [[{juqery code}]] // new Function, e.g. $("xxx").xxx() return string
- - [['text']] // remove ''
- - [[/regexp/]] // regexp e.g. $("sr-rd-content").find( "*[src='http://ifanr-cdn.b0.upaiyun.com/wp-content/uploads/2016/09/AppSo-qrcode-signature.jpg']" )
- - [[[juqery code]]] // new Function, e.g. $("xxx").find() return jquery object
-
- *
- * @param {string} verify content
- * @return {boolen} verify result
- */
-function specTest( content ) {
- return /^(\[\[)[\[{'/]{1}[ \S]+[}'/\]]\]\]{1}($)/g.test( content );
-}
-
-/**
- * Exec special action, action include: @see specTest
- * type: 0, 3 - be chiefly used in include logic
- * type: 1, 2 - be chiefly used in exclude logic
- *
- * @param {string} content
- * @return {array} 0: result; 1: type( include: -1:error 0:{} 1:'' 2:// 3:[])
- */
-function specAction( content ) {
- let [ value, type ] = [ content.replace( /(^)\[\[|\]\]$/g, "" ) ];
- switch (value[0]) {
- case "{":
- value = value.replace( /^{|}$/g, "" );
- content = ( v=>new Function( `return ${v}` )() )(value);
- type = 0;
- break;
- case "'":
- content = value.replace( /^'|'$/g, "" );
- const name = content.match(/^<[a-zA-Z0-9_-]+>/g).join("").replace( /<|>/g, "" );
- const str = content.replace( /<[/a-zA-Z0-9_-]+>/g, "" );
- content = `${name}:contains(${str})`;
- type = 1;
- break;
- case "/":
- content = value.replace( /^\/|\/$/g, "" ).replace( /\\{2}/g, "\\" ).replace( /'/g, '"' );
- type = 2;
- break;
- case "[":
- value = value.replace( /^{|}$/g, "" );
- content = ( v=>new Function( `return ${v}` )() )(value)[0];
- type = 3;
- break;
- default:
- console.error( "Not support current action.", content )
- type = -1;
- break;
- }
- return [ content, type ];
-}
-
-export {
- clone,
- getURI,
- verifyHtml,
- selector,
- specTest,
- specAction
-}
\ No newline at end of file
diff --git a/src/vender/turndown/turndown-plugin-gfm.js b/src/vender/turndown/turndown-plugin-gfm.js
new file mode 100644
index 000000000..ed53990f8
--- /dev/null
+++ b/src/vender/turndown/turndown-plugin-gfm.js
@@ -0,0 +1,167 @@
+var turndownPluginGfm = (function (exports) {
+'use strict';
+
+var highlightRegExp = /highlight-(?:text|source)-([a-z0-9]+)/;
+
+function highlightedCodeBlock (turndownService) {
+ turndownService.addRule('highlightedCodeBlock', {
+ filter: function (node) {
+ var firstChild = node.firstChild;
+ return (
+ node.nodeName === 'DIV' &&
+ highlightRegExp.test(node.className) &&
+ firstChild &&
+ firstChild.nodeName === 'PRE'
+ )
+ },
+ replacement: function (content, node, options) {
+ var className = node.className || '';
+ var language = (className.match(highlightRegExp) || [null, ''])[1];
+
+ return (
+ '\n\n' + options.fence + language + '\n' +
+ node.firstChild.textContent +
+ '\n' + options.fence + '\n\n'
+ )
+ }
+ });
+}
+
+function strikethrough (turndownService) {
+ turndownService.addRule('strikethrough', {
+ filter: ['del', 's', 'strike'],
+ replacement: function (content) {
+ return '~' + content + '~'
+ }
+ });
+}
+
+var indexOf = Array.prototype.indexOf;
+var every = Array.prototype.every;
+var rules = {};
+
+rules.tableCell = {
+ filter: ['th', 'td'],
+ replacement: function (content, node) {
+ return cell(content, node)
+ }
+};
+
+rules.tableRow = {
+ filter: 'tr',
+ replacement: function (content, node) {
+ var borderCells = '';
+ var alignMap = { left: ':--', right: '--:', center: ':-:' };
+
+ if (isHeadingRow(node)) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var border = '---';
+ var align = (
+ node.childNodes[i].getAttribute('align') || ''
+ ).toLowerCase();
+
+ if (align) border = alignMap[align] || border;
+
+ borderCells += cell(border, node.childNodes[i]);
+ }
+ }
+ return '\n' + content + (borderCells ? '\n' + borderCells : '')
+ }
+};
+
+rules.table = {
+ // Only convert tables with a heading row.
+ // Tables with no heading row are kept using `keep` (see below).
+ filter: function (node) {
+ return node.nodeName === 'TABLE' && isHeadingRow(node.rows[0])
+ },
+
+ replacement: function (content) {
+ // Ensure there are no blank lines
+ content = content.replace('\n\n', '\n');
+ return '\n\n' + content + '\n\n'
+ }
+};
+
+rules.tableSection = {
+ filter: ['thead', 'tbody', 'tfoot'],
+ replacement: function (content) {
+ return content
+ }
+};
+
+// A tr is a heading row if:
+// - the parent is a THEAD
+// - or if its the first child of the TABLE or the first TBODY (possibly
+// following a blank THEAD)
+// - and every cell is a TH
+function isHeadingRow (tr) {
+ var parentNode = tr.parentNode;
+ return (
+ parentNode.nodeName === 'THEAD' ||
+ (
+ parentNode.firstChild === tr &&
+ (parentNode.nodeName === 'TABLE' || isFirstTbody(parentNode)) &&
+ every.call(tr.childNodes, function (n) { return n.nodeName === 'TH' })
+ )
+ )
+}
+
+function isFirstTbody (element) {
+ var previousSibling = element.previousSibling;
+ return (
+ element.nodeName === 'TBODY' && (
+ !previousSibling ||
+ (
+ previousSibling.nodeName === 'THEAD' &&
+ /^\s*$/i.test(previousSibling.textContent)
+ )
+ )
+ )
+}
+
+function cell (content, node) {
+ var index = indexOf.call(node.parentNode.childNodes, node);
+ var prefix = ' ';
+ if (index === 0) prefix = '| ';
+ return prefix + content + ' |'
+}
+
+function tables (turndownService) {
+ turndownService.keep(function (node) {
+ return node.nodeName === 'TABLE' && !isHeadingRow(node.rows[0])
+ });
+ for (var key in rules) turndownService.addRule(key, rules[key]);
+}
+
+function taskListItems (turndownService) {
+ turndownService.addRule('taskListItems', {
+ filter: function (node) {
+ return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
+ },
+ replacement: function (content, node) {
+ return (node.checked ? '[x]' : '[ ]') + ' '
+ }
+ });
+}
+
+function gfm (turndownService) {
+ turndownService.use([
+ highlightedCodeBlock,
+ strikethrough,
+ tables,
+ taskListItems
+ ]);
+}
+
+exports.gfm = gfm;
+exports.highlightedCodeBlock = highlightedCodeBlock;
+exports.strikethrough = strikethrough;
+exports.tables = tables;
+exports.taskListItems = taskListItems;
+
+return exports;
+
+}({}));
+
+module.exports = turndownPluginGfm;
\ No newline at end of file
diff --git a/src/vender/turndown/turndown.js b/src/vender/turndown/turndown.js
new file mode 100644
index 000000000..c6411f9a1
--- /dev/null
+++ b/src/vender/turndown/turndown.js
@@ -0,0 +1,912 @@
+var TurndownService = (function () {
+'use strict';
+
+function extend (destination) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+ for (var key in source) {
+ if (source.hasOwnProperty(key)) destination[key] = source[key];
+ }
+ }
+ return destination
+}
+
+function repeat (character, count) {
+ return Array(count + 1).join(character)
+}
+
+var blockElements = [
+ 'address', 'article', 'aside', 'audio', 'blockquote', 'body', 'canvas',
+ 'center', 'dd', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption',
+ 'figure', 'footer', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
+ 'header', 'hgroup', 'hr', 'html', 'isindex', 'li', 'main', 'menu', 'nav',
+ 'noframes', 'noscript', 'ol', 'output', 'p', 'pre', 'section', 'table',
+ 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'
+];
+
+function isBlock (node) {
+ return blockElements.indexOf(node.nodeName.toLowerCase()) !== -1
+}
+
+var voidElements = [
+ 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
+ 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
+];
+
+function isVoid (node) {
+ return voidElements.indexOf(node.nodeName.toLowerCase()) !== -1
+}
+
+var voidSelector = voidElements.join();
+function hasVoid (node) {
+ return node.querySelector && node.querySelector(voidSelector)
+}
+
+var rules = {};
+
+rules.paragraph = {
+ filter: 'p',
+
+ replacement: function (content) {
+ return '\n\n' + content + '\n\n'
+ }
+};
+
+rules.lineBreak = {
+ filter: 'br',
+
+ replacement: function (content, node, options) {
+ return options.br + '\n'
+ }
+};
+
+rules.heading = {
+ filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
+
+ replacement: function (content, node, options) {
+ var hLevel = Number(node.nodeName.charAt(1));
+
+ if (options.headingStyle === 'setext' && hLevel < 3) {
+ var underline = repeat((hLevel === 1 ? '=' : '-'), content.length);
+ return (
+ '\n\n' + content + '\n' + underline + '\n\n'
+ )
+ } else {
+ return '\n\n' + repeat('#', hLevel) + ' ' + content + '\n\n'
+ }
+ }
+};
+
+rules.blockquote = {
+ filter: 'blockquote',
+
+ replacement: function (content) {
+ content = content.replace(/^\n+|\n+$/g, '');
+ content = content.replace(/^/gm, '> ');
+ return '\n\n' + content + '\n\n'
+ }
+};
+
+rules.list = {
+ filter: ['ul', 'ol'],
+
+ replacement: function (content, node) {
+ var parent = node.parentNode;
+ if (parent.nodeName === 'LI' && parent.lastElementChild === node) {
+ return '\n' + content
+ } else {
+ return '\n\n' + content + '\n\n'
+ }
+ }
+};
+
+rules.listItem = {
+ filter: 'li',
+
+ replacement: function (content, node, options) {
+ content = content
+ .replace(/^\n+/, '') // remove leading newlines
+ .replace(/\n+$/, '\n') // replace trailing newlines with just a single one
+ .replace(/\n/gm, '\n '); // indent
+ var prefix = options.bulletListMarker + ' ';
+ var parent = node.parentNode;
+ if (parent.nodeName === 'OL') {
+ var start = parent.getAttribute('start');
+ var index = Array.prototype.indexOf.call(parent.children, node);
+ prefix = (start ? Number(start) + index : index + 1) + '. ';
+ }
+ return (
+ prefix + content + (node.nextSibling && !/\n$/.test(content) ? '\n' : '')
+ )
+ }
+};
+
+rules.indentedCodeBlock = {
+ filter: function (node, options) {
+ return (
+ options.codeBlockStyle === 'indented' &&
+ node.nodeName === 'PRE' &&
+ node.firstChild &&
+ node.firstChild.nodeName === 'CODE'
+ )
+ },
+
+ replacement: function (content, node, options) {
+ return (
+ '\n\n ' +
+ node.firstChild.textContent.replace(/\n/g, '\n ') +
+ '\n\n'
+ )
+ }
+};
+
+rules.fencedCodeBlock = {
+ filter: function (node, options) {
+ return (
+ options.codeBlockStyle === 'fenced' &&
+ node.nodeName === 'PRE' &&
+ node.firstChild &&
+ node.firstChild.nodeName === 'CODE'
+ )
+ },
+
+ replacement: function (content, node, options) {
+ var className = node.firstChild.className || '';
+ var language = (className.match(/language-(\S+)/) || [null, ''])[1];
+
+ return (
+ '\n\n' + options.fence + language + '\n' +
+ node.firstChild.textContent +
+ '\n' + options.fence + '\n\n'
+ )
+ }
+};
+
+rules.horizontalRule = {
+ filter: 'hr',
+
+ replacement: function (content, node, options) {
+ return '\n\n' + options.hr + '\n\n'
+ }
+};
+
+rules.inlineLink = {
+ filter: function (node, options) {
+ return (
+ options.linkStyle === 'inlined' &&
+ node.nodeName === 'A' &&
+ node.getAttribute('href')
+ )
+ },
+
+ replacement: function (content, node) {
+ var href = node.getAttribute('href');
+ var title = node.title ? ' "' + node.title + '"' : '';
+ return '[' + content + '](' + href + title + ')'
+ }
+};
+
+rules.referenceLink = {
+ filter: function (node, options) {
+ return (
+ options.linkStyle === 'referenced' &&
+ node.nodeName === 'A' &&
+ node.getAttribute('href')
+ )
+ },
+
+ replacement: function (content, node, options) {
+ var href = node.getAttribute('href');
+ var title = node.title ? ' "' + node.title + '"' : '';
+ var replacement;
+ var reference;
+
+ switch (options.linkReferenceStyle) {
+ case 'collapsed':
+ replacement = '[' + content + '][]';
+ reference = '[' + content + ']: ' + href + title;
+ break
+ case 'shortcut':
+ replacement = '[' + content + ']';
+ reference = '[' + content + ']: ' + href + title;
+ break
+ default:
+ var id = this.references.length + 1;
+ replacement = '[' + content + '][' + id + ']';
+ reference = '[' + id + ']: ' + href + title;
+ }
+
+ this.references.push(reference);
+ return replacement
+ },
+
+ references: [],
+
+ append: function (options) {
+ var references = '';
+ if (this.references.length) {
+ references = '\n\n' + this.references.join('\n') + '\n\n';
+ this.references = []; // Reset references
+ }
+ return references
+ }
+};
+
+rules.emphasis = {
+ filter: ['em', 'i'],
+
+ replacement: function (content, node, options) {
+ if (!content.trim()) return ''
+ return options.emDelimiter + content + options.emDelimiter
+ }
+};
+
+rules.strong = {
+ filter: ['strong', 'b'],
+
+ replacement: function (content, node, options) {
+ if (!content.trim()) return ''
+ return options.strongDelimiter + content + options.strongDelimiter
+ }
+};
+
+rules.code = {
+ filter: function (node) {
+ var hasSiblings = node.previousSibling || node.nextSibling;
+ var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings;
+
+ return node.nodeName === 'CODE' && !isCodeBlock
+ },
+
+ replacement: function (content) {
+ if (!content.trim()) return ''
+
+ var delimiter = '`';
+ var leadingSpace = '';
+ var trailingSpace = '';
+ var matches = content.match(/`+/gm);
+ if (matches) {
+ if (/^`/.test(content)) leadingSpace = ' ';
+ if (/`$/.test(content)) trailingSpace = ' ';
+ while (matches.indexOf(delimiter) !== -1) delimiter = delimiter + '`';
+ }
+
+ return delimiter + leadingSpace + content + trailingSpace + delimiter
+ }
+};
+
+rules.image = {
+ filter: 'img',
+
+ replacement: function (content, node) {
+ var alt = node.alt || '';
+ var src = node.getAttribute('src') || '';
+ var title = node.title || '';
+ var titlePart = title ? ' "' + title + '"' : '';
+ return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''
+ }
+};
+
+/**
+ * Manages a collection of rules used to convert HTML to Markdown
+ */
+
+function Rules (options) {
+ this.options = options;
+ this._keep = [];
+ this._remove = [];
+
+ this.blankRule = {
+ replacement: options.blankReplacement
+ };
+
+ this.keepReplacement = options.keepReplacement;
+
+ this.defaultRule = {
+ replacement: options.defaultReplacement
+ };
+
+ this.array = [];
+ for (var key in options.rules) this.array.push(options.rules[key]);
+}
+
+Rules.prototype = {
+ add: function (key, rule) {
+ this.array.unshift(rule);
+ },
+
+ keep: function (filter) {
+ this._keep.unshift({
+ filter: filter,
+ replacement: this.keepReplacement
+ });
+ },
+
+ remove: function (filter) {
+ this._remove.unshift({
+ filter: filter,
+ replacement: function () {
+ return ''
+ }
+ });
+ },
+
+ forNode: function (node) {
+ if (node.isBlank) return this.blankRule
+ var rule;
+
+ if ((rule = findRule(this.array, node, this.options))) return rule
+ if ((rule = findRule(this._keep, node, this.options))) return rule
+ if ((rule = findRule(this._remove, node, this.options))) return rule
+
+ return this.defaultRule
+ },
+
+ forEach: function (fn) {
+ for (var i = 0; i < this.array.length; i++) fn(this.array[i], i);
+ }
+};
+
+function findRule (rules, node, options) {
+ for (var i = 0; i < rules.length; i++) {
+ var rule = rules[i];
+ if (filterValue(rule, node, options)) return rule
+ }
+ return void 0
+}
+
+function filterValue (rule, node, options) {
+ var filter = rule.filter;
+ if (typeof filter === 'string') {
+ if (filter === node.nodeName.toLowerCase()) return true
+ } else if (Array.isArray(filter)) {
+ if (filter.indexOf(node.nodeName.toLowerCase()) > -1) return true
+ } else if (typeof filter === 'function') {
+ if (filter.call(rule, node, options)) return true
+ } else {
+ throw new TypeError('`filter` needs to be a string, array, or function')
+ }
+}
+
+/**
+ * The collapseWhitespace function is adapted from collapse-whitespace
+ * by Luc Thevenard.
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Luc Thevenard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * collapseWhitespace(options) removes extraneous whitespace from an the given element.
+ *
+ * @param {Object} options
+ */
+function collapseWhitespace (options) {
+ var element = options.element;
+ var isBlock = options.isBlock;
+ var isVoid = options.isVoid;
+ var isPre = options.isPre || function (node) {
+ return node.nodeName === 'PRE'
+ };
+
+ if (!element.firstChild || isPre(element)) return
+
+ var prevText = null;
+ var prevVoid = false;
+
+ var prev = null;
+ var node = next(prev, element, isPre);
+
+ while (node !== element) {
+ if (node.nodeType === 3 || node.nodeType === 4) { // Node.TEXT_NODE or Node.CDATA_SECTION_NODE
+ var text = node.data.replace(/[ \r\n\t]+/g, ' ');
+
+ if ((!prevText || / $/.test(prevText.data)) &&
+ !prevVoid && text[0] === ' ') {
+ text = text.substr(1);
+ }
+
+ // `text` might be empty at this point.
+ if (!text) {
+ node = remove(node);
+ continue
+ }
+
+ node.data = text;
+
+ prevText = node;
+ } else if (node.nodeType === 1) { // Node.ELEMENT_NODE
+ if (isBlock(node) || node.nodeName === 'BR') {
+ if (prevText) {
+ prevText.data = prevText.data.replace(/ $/, '');
+ }
+
+ prevText = null;
+ prevVoid = false;
+ } else if (isVoid(node)) {
+ // Avoid trimming space around non-block, non-BR void elements.
+ prevText = null;
+ prevVoid = true;
+ }
+ } else {
+ node = remove(node);
+ continue
+ }
+
+ var nextNode = next(prev, node, isPre);
+ prev = node;
+ node = nextNode;
+ }
+
+ if (prevText) {
+ prevText.data = prevText.data.replace(/ $/, '');
+ if (!prevText.data) {
+ remove(prevText);
+ }
+ }
+}
+
+/**
+ * remove(node) removes the given node from the DOM and returns the
+ * next node in the sequence.
+ *
+ * @param {Node} node
+ * @return {Node} node
+ */
+function remove (node) {
+ var next = node.nextSibling || node.parentNode;
+
+ node.parentNode.removeChild(node);
+
+ return next
+}
+
+/**
+ * next(prev, current, isPre) returns the next node in the sequence, given the
+ * current and previous nodes.
+ *
+ * @param {Node} prev
+ * @param {Node} current
+ * @param {Function} isPre
+ * @return {Node}
+ */
+function next (prev, current, isPre) {
+ if ((prev && prev.parentNode === current) || isPre(current)) {
+ return current.nextSibling || current.parentNode
+ }
+
+ return current.firstChild || current.nextSibling || current.parentNode
+}
+
+/*
+ * Set up window for Node.js
+ */
+
+var root = (typeof window !== 'undefined' ? window : {});
+
+/*
+ * Parsing HTML strings
+ */
+
+function canParseHTMLNatively () {
+ var Parser = root.DOMParser;
+ var canParse = false;
+
+ // Adapted from https://gist.github.com/1129031
+ // Firefox/Opera/IE throw errors on unsupported types
+ try {
+ // WebKit returns null on unsupported types
+ if (new Parser().parseFromString('', 'text/html')) {
+ canParse = true;
+ }
+ } catch (e) {}
+
+ return canParse
+}
+
+function createHTMLParser () {
+ var Parser = function () {};
+
+ {
+ if (shouldUseActiveX()) {
+ Parser.prototype.parseFromString = function (string) {
+ var doc = new window.ActiveXObject('htmlfile');
+ doc.designMode = 'on'; // disable on-page scripts
+ doc.open();
+ doc.write(string);
+ doc.close();
+ return doc
+ };
+ } else {
+ Parser.prototype.parseFromString = function (string) {
+ var doc = document.implementation.createHTMLDocument('');
+ doc.open();
+ doc.write(string);
+ doc.close();
+ return doc
+ };
+ }
+ }
+ return Parser
+}
+
+function shouldUseActiveX () {
+ var useActiveX = false;
+ try {
+ document.implementation.createHTMLDocument('').open();
+ } catch (e) {
+ if (window.ActiveXObject) useActiveX = true;
+ }
+ return useActiveX
+}
+
+var HTMLParser = canParseHTMLNatively() ? root.DOMParser : createHTMLParser();
+
+function RootNode (input) {
+ var root;
+ if (typeof input === 'string') {
+ var doc = htmlParser().parseFromString(
+ // DOM parsers arrange elements in the and .
+ // Wrapping in a custom element ensures elements are reliably arranged in
+ // a single element.
+ '' + input + ' ',
+ 'text/html'
+ );
+ root = doc.getElementById('turndown-root');
+ } else {
+ root = input.cloneNode(true);
+ }
+ collapseWhitespace({
+ element: root,
+ isBlock: isBlock,
+ isVoid: isVoid
+ });
+
+ return root
+}
+
+var _htmlParser;
+function htmlParser () {
+ _htmlParser = _htmlParser || new HTMLParser();
+ return _htmlParser
+}
+
+function Node (node) {
+ node.isBlock = isBlock(node);
+ node.isCode = node.nodeName.toLowerCase() === 'code' || node.parentNode.isCode;
+ node.isBlank = isBlank(node);
+ node.flankingWhitespace = flankingWhitespace(node);
+ return node
+}
+
+function isBlank (node) {
+ return (
+ ['A', 'TH', 'TD', 'IFRAME', 'SCRIPT', 'AUDIO', 'VIDEO'].indexOf(node.nodeName) === -1 &&
+ /^\s*$/i.test(node.textContent) &&
+ !isVoid(node) &&
+ !hasVoid(node)
+ )
+}
+
+function flankingWhitespace (node) {
+ var leading = '';
+ var trailing = '';
+
+ if (!node.isBlock) {
+ var hasLeading = /^[ \r\n\t]/.test(node.textContent);
+ var hasTrailing = /[ \r\n\t]$/.test(node.textContent);
+
+ if (hasLeading && !isFlankedByWhitespace('left', node)) {
+ leading = ' ';
+ }
+ if (hasTrailing && !isFlankedByWhitespace('right', node)) {
+ trailing = ' ';
+ }
+ }
+
+ return { leading: leading, trailing: trailing }
+}
+
+function isFlankedByWhitespace (side, node) {
+ var sibling;
+ var regExp;
+ var isFlanked;
+
+ if (side === 'left') {
+ sibling = node.previousSibling;
+ regExp = / $/;
+ } else {
+ sibling = node.nextSibling;
+ regExp = /^ /;
+ }
+
+ if (sibling) {
+ if (sibling.nodeType === 3) {
+ isFlanked = regExp.test(sibling.nodeValue);
+ } else if (sibling.nodeType === 1 && !isBlock(sibling)) {
+ isFlanked = regExp.test(sibling.textContent);
+ }
+ }
+ return isFlanked
+}
+
+var reduce = Array.prototype.reduce;
+var leadingNewLinesRegExp = /^\n*/;
+var trailingNewLinesRegExp = /\n*$/;
+var escapes = [
+ [/\\/g, '\\\\'],
+ [/\*/g, '\\*'],
+ [/^-/g, '\\-'],
+ [/^\+ /g, '\\+ '],
+ [/^(=+)/g, '\\$1'],
+ [/^(#{1,6}) /g, '\\$1 '],
+ [/`/g, '\\`'],
+ [/^~~~/g, '\\~~~'],
+ [/\[/g, '\\['],
+ [/\]/g, '\\]'],
+ [/^>/g, '\\>'],
+ [/_/g, '\\_'],
+ [/^(\d+)\. /g, '$1\\. ']
+];
+escapes = [];
+
+function TurndownService (options) {
+ if (!(this instanceof TurndownService)) return new TurndownService(options)
+
+ var defaults = {
+ rules: rules,
+ headingStyle: 'setext',
+ hr: '* * *',
+ bulletListMarker: '*',
+ codeBlockStyle: 'indented',
+ fence: '```',
+ emDelimiter: '_',
+ strongDelimiter: '**',
+ linkStyle: 'inlined',
+ linkReferenceStyle: 'full',
+ br: ' ',
+ blankReplacement: function (content, node) {
+ return node.isBlock ? '\n\n' : ''
+ },
+ keepReplacement: function (content, node) {
+ return node.isBlock ? '\n\n' + node.outerHTML + '\n\n' : node.outerHTML
+ },
+ defaultReplacement: function (content, node) {
+ return node.isBlock ? '\n\n' + content + '\n\n' : content
+ }
+ };
+ this.options = extend({}, defaults, options);
+ this.rules = new Rules(this.options);
+}
+
+TurndownService.prototype = {
+ /**
+ * The entry point for converting a string or DOM node to Markdown
+ * @public
+ * @param {String|HTMLElement} input The string or DOM node to convert
+ * @returns A Markdown representation of the input
+ * @type String
+ */
+
+ turndown: function (input) {
+ if (!canConvert(input)) {
+ throw new TypeError(
+ input + ' is not a string, or an element/document/fragment node.'
+ )
+ }
+
+ if (input === '') return ''
+
+ var output = process.call(this, new RootNode(input));
+ return postProcess.call(this, output)
+ },
+
+ /**
+ * Add one or more plugins
+ * @public
+ * @param {Function|Array} plugin The plugin or array of plugins to add
+ * @returns The Turndown instance for chaining
+ * @type Object
+ */
+
+ use: function (plugin) {
+ if (Array.isArray(plugin)) {
+ for (var i = 0; i < plugin.length; i++) this.use(plugin[i]);
+ } else if (typeof plugin === 'function') {
+ plugin(this);
+ } else {
+ throw new TypeError('plugin must be a Function or an Array of Functions')
+ }
+ return this
+ },
+
+ /**
+ * Adds a rule
+ * @public
+ * @param {String} key The unique key of the rule
+ * @param {Object} rule The rule
+ * @returns The Turndown instance for chaining
+ * @type Object
+ */
+
+ addRule: function (key, rule) {
+ this.rules.add(key, rule);
+ return this
+ },
+
+ /**
+ * Keep a node (as HTML) that matches the filter
+ * @public
+ * @param {String|Array|Function} filter The unique key of the rule
+ * @returns The Turndown instance for chaining
+ * @type Object
+ */
+
+ keep: function (filter) {
+ this.rules.keep(filter);
+ return this
+ },
+
+ /**
+ * Remove a node that matches the filter
+ * @public
+ * @param {String|Array|Function} filter The unique key of the rule
+ * @returns The Turndown instance for chaining
+ * @type Object
+ */
+
+ remove: function (filter) {
+ this.rules.remove(filter);
+ return this
+ },
+
+ /**
+ * Escapes Markdown syntax
+ * @public
+ * @param {String} string The string to escape
+ * @returns A string with Markdown syntax escaped
+ * @type String
+ */
+
+ escape: function (string) {
+ return escapes.reduce(function (accumulator, escape) {
+ return accumulator.replace(escape[0], escape[1])
+ }, string)
+ }
+};
+
+/**
+ * Reduces a DOM node down to its Markdown string equivalent
+ * @private
+ * @param {HTMLElement} parentNode The node to convert
+ * @returns A Markdown representation of the node
+ * @type String
+ */
+
+function process (parentNode) {
+ var self = this;
+ return reduce.call(parentNode.childNodes, function (output, node) {
+ node = new Node(node);
+
+ var replacement = '';
+ if (node.nodeType === 3) {
+ replacement = node.isCode ? node.nodeValue : self.escape(node.nodeValue);
+ } else if (node.nodeType === 1) {
+ replacement = replacementForNode.call(self, node);
+ }
+
+ return join(output, replacement)
+ }, '')
+}
+
+/**
+ * Appends strings as each rule requires and trims the output
+ * @private
+ * @param {String} output The conversion output
+ * @returns A trimmed version of the ouput
+ * @type String
+ */
+
+function postProcess (output) {
+ var self = this;
+ this.rules.forEach(function (rule) {
+ if (typeof rule.append === 'function') {
+ output = join(output, rule.append(self.options));
+ }
+ });
+
+ return output.replace(/^[\t\r\n]+/, '').replace(/[\t\r\n\s]+$/, '')
+}
+
+/**
+ * Converts an element node to its Markdown equivalent
+ * @private
+ * @param {HTMLElement} node The node to convert
+ * @returns A Markdown representation of the node
+ * @type String
+ */
+
+function replacementForNode (node) {
+ var rule = this.rules.forNode(node);
+ var content = process.call(this, node);
+ var whitespace = node.flankingWhitespace;
+ if (whitespace.leading || whitespace.trailing) content = content.trim();
+ return (
+ whitespace.leading +
+ rule.replacement(content, node, this.options) +
+ whitespace.trailing
+ )
+}
+
+/**
+ * Determines the new lines between the current output and the replacement
+ * @private
+ * @param {String} output The current conversion output
+ * @param {String} replacement The string to append to the output
+ * @returns The whitespace to separate the current output and the replacement
+ * @type String
+ */
+
+function separatingNewlines (output, replacement) {
+ var newlines = [
+ output.match(trailingNewLinesRegExp)[0],
+ replacement.match(leadingNewLinesRegExp)[0]
+ ].sort();
+ var maxNewlines = newlines[newlines.length - 1];
+ return maxNewlines.length < 2 ? maxNewlines : '\n\n'
+}
+
+function join (string1, string2) {
+ var separator = separatingNewlines(string1, string2);
+
+ // Remove trailing/leading newlines and replace with separator
+ string1 = string1.replace(trailingNewLinesRegExp, '');
+ string2 = string2.replace(leadingNewLinesRegExp, '');
+
+ return string1 + separator + string2
+}
+
+/**
+ * Determines whether an input can be converted
+ * @private
+ * @param {String|HTMLElement} input Describe this parameter
+ * @returns Describe what it returns
+ * @type String|Object|Array|Boolean|Number
+ */
+
+function canConvert (input) {
+ return (
+ input != null && (
+ typeof input === 'string' ||
+ (input.nodeType && (
+ input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11
+ ))
+ )
+ )
+}
+
+return TurndownService;
+
+}());
+
+
+module.exports = TurndownService;
\ No newline at end of file
diff --git a/src/vender/webdav.js b/src/vender/webdav.js
new file mode 100644
index 000000000..65c800536
--- /dev/null
+++ b/src/vender/webdav.js
@@ -0,0 +1,164 @@
+/* A simple WebDav implementation in JavaScript
+ https://github.com/aslakhellesoy/webdavjs @license MIT
+*/
+var WebDAV = {
+ GET: function(url, callback) {
+ return this.request('GET', url, {}, null, 'text', callback);
+ },
+
+ PROPFIND: function(url, callback) {
+ return this.request('PROPFIND', url, {
+ Depth: "1"
+ }, null, 'xml', callback);
+ },
+
+ MKCOL: function(url, callback) {
+ return this.request('MKCOL', url, {}, null, 'text', callback);
+ },
+
+ DELETE: function(url, callback) {
+ return this.request('DELETE', url, {}, null, 'text', callback);
+ },
+
+ PUT: function(url, data, callback) {
+ return this.request('PUT', url, {}, data, 'text', callback);
+ },
+
+ Author: function(user, password) {
+ this.user = user;
+ this.password = password;
+ },
+
+ request: function(verb, url, headers, data, type, callback) {
+ var xhr = new XMLHttpRequest();
+ var body = function() {
+ var b = xhr.responseText;
+ if (type == 'xml') {
+ var xml = xhr.responseXML;
+ if (xml) {
+ b = xml.firstChild.nextSibling ? xml.firstChild.nextSibling : xml.firstChild;
+ }
+ }
+ return b;
+ };
+
+ if (callback) {
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE && verb == "PROPFIND") {
+ var b = body();
+ if (b) {
+ callback(b);
+ }
+ } else if (xhr.readyState === XMLHttpRequest.DONE) {
+ callback(xhr);
+ }
+ };
+ }
+ xhr.open(verb, url, !! callback);
+ xhr.setRequestHeader("Content-Type", "text/xml; charset=UTF-8");
+ this.user && this.password &&
+ xhr.setRequestHeader("Authorization", "Basic " + btoa(this.user + ":" + this.password))
+ for (var header in headers) {
+ xhr.setRequestHeader(header, headers[header]);
+ }
+ xhr.send(data);
+
+ if (!callback) {
+ return body();
+ }
+ }
+};
+
+// An Object-oriented API around WebDAV.
+WebDAV.Fs = function(rootUrl, user, password) {
+ WebDAV.Author(user, password);
+ this.rootUrl = rootUrl;
+ var fs = this;
+
+ this.file = function(href) {
+ this.type = 'file';
+
+ this.url = fs.urlFor(href);
+
+ this.name = fs.nameFor(this.url);
+
+ this.read = function(callback) {
+ return WebDAV.GET(this.url, callback);
+ };
+
+ this.write = function(data, callback) {
+ return WebDAV.PUT(this.url, data, callback);
+ };
+
+ this.rm = function(callback) {
+ return WebDAV.DELETE(this.url, callback);
+ };
+
+ return this;
+ };
+
+ this.dir = function(href) {
+ this.type = 'dir';
+
+ this.url = fs.urlFor(href);
+
+ this.name = fs.nameFor(this.url);
+
+ this.children = function(callback) {
+ var childrenFunc = function(doc) {
+ if (doc.childNodes == null) {
+ throw ('No such directory: ' + url);
+ }
+ var result = [];
+ // Start at 1, because the 0th is the same as self.
+ for (var i = 1; i < doc.childNodes.length; i++) {
+ var response = doc.childNodes[i];
+ var href = decodeURI( response.getElementsByTagName('d:href')[0].firstChild.nodeValue.replace(/\/$/, ''));
+ var propstat = response.getElementsByTagName('d:propstat')[0];
+ var prop = propstat.getElementsByTagName('d:prop')[0];
+ var resourcetype = prop.getElementsByTagName('d:resourcetype')[0];
+ var collection = resourcetype.getElementsByTagName('d:collection')[0];
+
+ if (collection) {
+ result[i - 1] = new fs.dir(href);
+ } else {
+ result[i - 1] = new fs.file(href);
+ }
+ }
+ return result;
+ };
+
+ if (callback) {
+ WebDAV.PROPFIND(this.url, function(doc) {
+ callback(childrenFunc(doc));
+ });
+ } else {
+ return childrenFunc(WebDAV.PROPFIND(this.url));
+ }
+ };
+
+ this.rm = function(callback) {
+ return WebDAV.DELETE(this.url, callback);
+ };
+
+ this.mkdir = function(callback) {
+ return WebDAV.MKCOL(this.url, callback);
+ };
+
+ return this;
+ };
+
+ this.urlFor = function(href) {
+ return (/^http/.test(href) ? href : this.rootUrl + href);
+ };
+
+ this.nameFor = function(url) {
+ return url.replace(/.*\/(.*)/, '$1');
+ };
+
+ return this;
+};
+
+if (typeof module !== 'undefined') {
+ module.exports = WebDAV;
+}
\ No newline at end of file
diff --git a/src/vender/wiz.js b/src/vender/wiz.js
new file mode 100644
index 000000000..6e2942ebd
--- /dev/null
+++ b/src/vender/wiz.js
@@ -0,0 +1,126 @@
+/**
+ * Soure from https://github.com/xcffl/WizWebClipperWE
+ */
+
+var Base64 = {
+ // private property
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+ // public method for encoding
+ encode : function(input) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = Base64._utf8_encode(input);
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+ output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+ }
+
+ return output;
+ },
+ // private method for UTF-8 encoding
+ _utf8_encode : function(string) {
+ string = string.replace(/\r\n/g, "\n");
+ var utftext = "";
+ for (var n = 0; n < string.length; n++) {
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ } else if ((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ } else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ }
+};
+
+var wiz_base64Encode = function( str ) {
+ var scriptFilter = function (html) {
+ return html.replace(/",
- "",
- "
å¯¹æœ¬æ–‡çš„å®¡æ ¡
']]", - "[['䏿–‡ç«™æŠ•稿或者å‚与内容翻译工作
']]", - "[['QCon北京2017']]" - ] - },{ - "name" : "news.infoq.com", - "url" : "http://www.infoq.com/cn/news/**/*", - "title" : "", - "desc" : "", - "include" : "",
- "exclude" : [
- "",
- "",
- "",
- "",
- "",
- ""
+ ""
]
},{
"name" : "segmentfault.com",
@@ -963,7 +1094,7 @@
"desc" : "",
"include" : "",
"exclude" : [
- "[[/src=\\S+(liiLIZF8Uh6yM.jpg)\\S+/]]"
+ ""
]
},{
"name" : "ifeve.com",
@@ -1020,10 +1151,10 @@
"name" : "my.oschina.net",
"url" : "https://my.oschina.net/**/*/blog/*",
"title" : "",
- "desc" : " ",
+ "desc" : "",
"include" : "",
"exclude" : [
- ""
+ "[[/src=\\S+(hot3)\\S+'/]]"
]
},{
"name" : "oschina.net",
@@ -1044,6 +1175,24 @@
"exclude" : [
""
]
+ },{
+ "name" : "news.iteye.com",
+ "url" : "http*://www.iteye.com/news/*",
+ "title" : "
", + "desc" : "", + "include" : "",
+ "exclude" : [
+ ""
+ ]
+ },{
+ "name" : "blog.iteye.com",
+ "url" : "http*://*.iteye.com/blog/*",
+ "title" : "",
+ "desc" : "",
+ "include" : " ",
+ "exclude" : [
+ ""
+ ]
},{
"name" : "geek.csdn.net",
"url" : "http*://geek.csdn.net/news/detail/*",
@@ -1063,9 +1212,11 @@
"url" : "http*://blog.csdn.net/*/article/details/*",
"title" : "",
"desc" : "",
- "include" : " ",
+ "include" : "[[[(function(){var e=$('#content_views');if(!e.length)e=$('#article_content');return e;}())]]]",
"exclude" : [
- ""
+ "",
+ "",
+ "