Skip to content

Commit

Permalink
Feature: Copy page selection as Markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
yorkxin committed Apr 23, 2024
1 parent 42d7ff9 commit 24e9410
Show file tree
Hide file tree
Showing 11 changed files with 1,168 additions and 2 deletions.
3 changes: 3 additions & 0 deletions chrome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"type": "module"
},
"commands": {
"selection-as-markdown": {
"description": "selection as Markdown"
},
"current-tab-link": {
"description": "current tab: [title](url)"
},
Expand Down
3 changes: 3 additions & 0 deletions firefox-mv2/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"persistent": false
},
"commands": {
"selection-as-markdown": {
"description": "selection as Markdown"
},
"current-tab-link": {
"description": "current tab: [title](url)"
},
Expand Down
3 changes: 3 additions & 0 deletions firefox/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
"type": "module"
},
"commands": {
"selection-as-markdown": {
"description": "selection as Markdown"
},
"current-tab-link": {
"description": "current tab: [title](url)"
},
Expand Down
30 changes: 30 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"debug-firefox": "npx nodemon --exec 'sh compile.sh firefox' & npx web-ext run -s firefox/ --url about:debugging#/runtime/this-firefox https://example.com",
"eslint": "eslint .",
"clean": "rm -rf ./build/* firefox/dist/* firefox-mv2/dist/* chrome/dist/*",
"convert-images": "./utils/convert-images.sh"
"convert-images": "./utils/convert-images.sh",
"postinstall": "cp node_modules/turndown/dist/turndown.js src/vendor/"
},
"license": "MIT",
"devDependencies": {
Expand All @@ -27,5 +28,8 @@
"nodemon": "^2.0.19",
"nyc": "^15.1.0",
"typescript": "^2.9.2"
},
"dependencies": {
"turndown": "^7.1.3"
}
}
56 changes: 55 additions & 1 deletion src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ function createMenus() {
type: 'normal',
contexts: ['image'],
});

chrome.contextMenus.create({
id: 'selection-as-markdown',
title: 'Copy Selection as Markdown', // TODO: how to fetch alt text?
type: 'normal',
contexts: ['selection'],
});
}

chrome.alarms.onAlarm.addListener((alarm) => {
Expand All @@ -102,6 +109,43 @@ chrome.alarms.onAlarm.addListener((alarm) => {
}
});

// NOTE: this function should be executed in content script.
function selectionToMarkdown(turndownOptions) {
// eslint-disable-next-line no-undef
const turndownService = new TurndownService(turndownOptions);
const sel = getSelection();
const container = document.createElement('div');
for (let i = 0, len = sel.rangeCount; i < len; i += 1) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
const html = container.innerHTML;
return turndownService.turndown(html);
}

function getTurndownOptions() {
return {
// For all options see https://github.com/mixmark-io/turndown?tab=readme-ov-file#options
headingStyle: 'atx',
bulletListMarker: markdownInstance.unorderedListChar,
};
}

async function convertSelectionInTabToMarkdown(tab) {
await chrome.scripting.executeScript({
target: { tabId: tab.id, allFrames: true },
files: ['dist/vendor/turndown.js'],
});
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id, allFrames: true },
func: selectionToMarkdown,
args: [
getTurndownOptions(),
],
});

return results.map((frame) => frame.result).join('\n\n');
}

async function handleContentOfContextMenu(info, tab) {
let text;
switch (info.menuItemId) {
Expand Down Expand Up @@ -136,6 +180,11 @@ async function handleContentOfContextMenu(info, tab) {
break;
}

case 'selection-as-markdown': {
text = await convertSelectionInTabToMarkdown(tab);
break;
}

default: {
throw new TypeError(`unknown context menu: ${info}`);
}
Expand Down Expand Up @@ -241,7 +290,12 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => {
chrome.commands.onCommand.addListener(async (command) => {
try {
const tab = await mustGetCurrentTab();
const text = await handleExport(command);
let text = '';
if (command === 'selection-as-markdown') {
text = await convertSelectionInTabToMarkdown(tab);
} else {
text = await handleExport(command);
}
await writeUsingContentScript(tab, text);
await flashBadge('success');
return Promise.resolve(true);
Expand Down
26 changes: 26 additions & 0 deletions src/ui/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,29 @@ Homepage: https://github.com/jgthms/bulma
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.

### Turndown.js

Homepage: https://github.com/mixmark-io/turndown

MIT License

Copyright (c) 2017 Dom Christie

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.
Loading

0 comments on commit 24e9410

Please sign in to comment.