Skip to content

Commit

Permalink
Merge pull request #10 from Shiou-Ju/feat/copy-all-button
Browse files Browse the repository at this point in the history
Feat/copy all button
  • Loading branch information
Shiou-Ju authored Jan 9, 2024
2 parents a7191d0 + 69c5f9f commit b7a3953
Show file tree
Hide file tree
Showing 10 changed files with 2,021 additions and 121 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,6 @@ dist

# local for test
scripts/output
screenshots/


2 changes: 2 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const tsPreset = require('ts-jest/jest-preset');
const puppeteerPreset = require('jest-puppeteer/jest-preset');

module.exports = {
// if implementing unit test:
// collectCoverageFrom: ['src/**/*.ts'],
...tsPreset,
...puppeteerPreset,
globals: {
Expand Down
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,34 @@
"main": "index.js",
"scripts": {
"format": "prettier --write \"**/*.{ts,js,json}\"",
"test": "yarn build && PUPPETEER_DISABLE_HEADLESS_WARNING=true jest",
"build": "rm -rf dist && tsc && cp manifest.json dist/ && cp -r icons dist/"
"test": "yarn build-dev && PUPPETEER_DISABLE_HEADLESS_WARNING=true jest --verbose --coverage",
"build-legacy": "rm -rf dist && tsc && cp manifest.json dist/ && cp -r icons dist/",
"build": "rm -rf dist && webpack --mode production && cp manifest.json dist/ && cp -r icons dist/",
"build-dev": "rm -rf dist && webpack --mode development && cp manifest.json dist/ && cp -r icons dist/"
},
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/preset-env": "^7.23.7",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.6",
"@types/puppeteer": "^7.0.4",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"date-fns": "^3.0.6",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2",
"html-loader": "^4.2.0",
"jest": "^29.7.0",
"jest-puppeteer": "^9.0.2",
"prettier": "^3.1.1",
"puppeteer": "^21.6.1",
"style-loader": "^3.3.3",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"date-fns": "^3.0.6"
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
}
}
140 changes: 110 additions & 30 deletions src/content.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
const addCopyModification = () => {
const promptTitle = '幫我用臺灣使用的繁體中文翻譯以下內容\n';

const exampleTranslation =
'\n\n依照以下的範例:' +
// better to produce result without code block
// '\n```\n\n' +
'\n\n' +
'tan·da n \n' +
'1. 成為某事的地址或表達某事的東西:遠處聽到危險的警報聲。\n' +
'2. 跡象:已經顯現出它的跡象。\n' +
'3. 證據:那是他們不願合作的證據。\n' +
'4. 識別符號;象徵:印尼代表團佩戴著印尼國徽的標誌。\n' +
'5. 指示。\n' +
'- alamiah: 自然產生的標誌,非人為刻意創造。\n' +
'- baca: 用於拼寫系統的標誌(如句號、逗號、冒號)。\n' +
'- bagi: 數學中表示除法完成或進行中的標誌(冒號 [:])。\n' +
'- bakti: 忠誠的表達。\n\n' +
'ber·tan·da v \n' +
'1. 有標誌;有特徵;有商標等。\n' +
'2. 已(戴結婚戒指)結婚。\n\n' +
'pe·tan·da·an n \n' +
'標記的過程、方式、行為。\n' +
// better to produce result without code block
// +'\n```\n';
'\n\n';

const note = '請[不要]放在 code block 給我,謝謝。';
import { SELECTORS } from '../utils/selectors';

const promptTitle = '幫我用臺灣使用的繁體中文翻譯以下內容\n';

const exampleTranslation =
'\n\n依照以下的範例:' +
// better to produce result without code block
// '\n```\n\n' +
'\n\n' +
'tan·da n \n' +
'1. 成為某事的地址或表達某事的東西:遠處聽到危險的警報聲。\n' +
'2. 跡象:已經顯現出它的跡象。\n' +
'3. 證據:那是他們不願合作的證據。\n' +
'4. 識別符號;象徵:印尼代表團佩戴著印尼國徽的標誌。\n' +
'5. 指示。\n' +
'- alamiah: 自然產生的標誌,非人為刻意創造。\n' +
'- baca: 用於拼寫系統的標誌(如句號、逗號、冒號)。\n' +
'- bagi: 數學中表示除法完成或進行中的標誌(冒號 [:])。\n' +
'- bakti: 忠誠的表達。\n\n' +
'ber·tan·da v \n' +
'1. 有標誌;有特徵;有商標等。\n' +
'2. 已(戴結婚戒指)結婚。\n\n' +
'pe·tan·da·an n \n' +
'標記的過程、方式、行為。\n' +
// better to produce result without code block
// +'\n```\n';
'\n\n';

const note = '請[不要]放在 code block 給我,謝謝。';

function ensureTempDiv(id: string, text: string) {
let tempDiv = document.getElementById(id);

if (!tempDiv) {
tempDiv = document.createElement('div');
tempDiv.id = id;
tempDiv.style.position = 'absolute';
tempDiv.style.left = '-9999px';
document.body.appendChild(tempDiv);
}

tempDiv.textContent = text;

return tempDiv;
}

const addCopyModification = () => {
document.addEventListener('copy', (event) => {
const selection = document.getSelection();

Expand All @@ -35,9 +53,8 @@ const addCopyModification = () => {
}

const selectedText = selection.toString();
const wrappedSelected = '```\n' + selectedText + '\n```';

const modifiedText = promptTitle + wrappedSelected + exampleTranslation + note;
const modifiedText = convertSelectedTextToPromptForTranslation(selectedText, promptTitle, exampleTranslation, note);

if (!event.clipboardData) {
return;
Expand All @@ -48,4 +65,67 @@ const addCopyModification = () => {
});
};

function convertSelectedTextToPromptForTranslation(
selection: string,
promptTitle: string,
exampleTranslation: string,
note: string
) {
if (!selection) {
return '';
}

const selectedText = selection.toString();
const wrappedSelected = '```\n' + selectedText + '\n```';

const modifiedText = promptTitle + wrappedSelected + exampleTranslation + note;

return modifiedText;
}

const addCaptureAllBtn = () => {
const btnParent = document.querySelector(SELECTORS.BTN_PARENT_ELEMENT);
if (!btnParent) return;

const button = document.createElement('button');

const originalText = 'Copy all explanation';

button.textContent = originalText;
button.className = 'btn btn-default';
button.id = SELECTORS.ID_BTN_FOR_ALL_EXPLANAION;

const buttonContainer = document.createElement('div');
buttonContainer.appendChild(button);

btnParent.insertAdjacentElement('afterend', buttonContainer);

button.addEventListener('click', async () => {
const explanationElements = document.querySelectorAll(SELECTORS.EXPLANATION_SECTORS);

const allExplanationsText = Array.from(explanationElements)
.map((el) => (el.textContent ? el.textContent.trim() : ''))
.join('\n\n');

const tempDiv = ensureTempDiv('tempClipboardContent', allExplanationsText);

const range = document.createRange();
range.selectNodeContents(tempDiv);
const selection = window.getSelection();

if (!selection) return;

selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');

button.textContent = 'Copied';

setTimeout(() => {
button.textContent = originalText;
}, 1000);
});
};

addCopyModification();
addCaptureAllBtn();
Loading

0 comments on commit b7a3953

Please sign in to comment.