From 30ab381af538aaee3ee391ac1205bdccb437f854 Mon Sep 17 00:00:00 2001 From: Renkin <906155099@qq.com> Date: Wed, 18 Oct 2023 11:00:25 +0800 Subject: [PATCH 1/3] feat: English version is supported in a small range of app.js --- src/App.js | 63 ++++++++++++++++++++++++-------------------- src/locales/cn.js | 45 +++++++++++++++++++++++++++++++ src/locales/en.js | 46 ++++++++++++++++++++++++++++++++ src/locales/index.js | 47 +++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 28 deletions(-) create mode 100644 src/locales/cn.js create mode 100644 src/locales/en.js create mode 100644 src/locales/index.js diff --git a/src/App.js b/src/App.js index 1181752..d927523 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import React, { useState, Suspense } from "react"; +import React, { useState, Suspense, useEffect } from "react"; import { Button, Table, Empty, Tabs, Image } from "antd"; import "highlight.js/styles/github.css"; @@ -22,6 +22,7 @@ import "./App.css"; import CodeTemplates from "./codeTemplates/codeTemplate"; import ComplexityRating from "./complexityRating/index"; import SolutionTemplate from "./solutionTemplate/index"; +import Locale, { initLang } from "./locales"; // import { data as a } from "./db/binary-tree"; const DataStrutureVis = isInExtension() @@ -41,7 +42,7 @@ const chrome = window.chrome; const columns = [ { - title: "题目", + title: Locale.app.allSolutions.columns.title, dataIndex: "name", width: "300", align: "center", @@ -56,7 +57,7 @@ const columns = [ ), }, { - title: "标签", + title: Locale.app.allSolutions.columns.tag, dataIndex: "pre", align: "center", render: (tags) => ( @@ -121,6 +122,9 @@ function App() { // }, 1000); // console.log(a); + useEffect(() => { + initLang(); + }) return (
{page !== "" ? ( ) : ( "" )} {hasSolution && page === "" ? ( ))}
@@ -191,9 +196,9 @@ function App() {
- +
- 所有已收录的题目 + {Locale.app.allCollected}
- + - + {isInExtension() ? ( ) : ( Loading...}> @@ -226,40 +234,39 @@ function App() { )} {!isInExtension() && ( - + )} - + - + {isInExtension() && ( - -
- 一般只要你开启了自动更新,那么当插件更新之后 - chrome会在五个小时以内自动更新。 - 如果你想第一时间更新,或者您禁用了自动更新,都可以在这里检测最新版。 -
+ +
{Locale.app.checkTips}
)} - +
- 作者是一个 Github 40K star 的前端架构师,leetcode 刷题插件 - leetcode-cheatsheet - 作者,掌握各种算法套路,写了十几万字的算法刷题套路电子书,公众号回复 - 电子书获取。 +
{Locale.app.selfIntroduction}
diff --git a/src/locales/cn.js b/src/locales/cn.js new file mode 100644 index 0000000..6161605 --- /dev/null +++ b/src/locales/cn.js @@ -0,0 +1,45 @@ +export const cn = { + app: { + back: "返回主页", + viewSolution: "查看本题题解", + viewInHandpickCollection: (t) => `该题已被收录到精选合集《${t}》点击查看`, + notCollected: "本题暂未被力扣加加收录,点击查看所有已收录题目~", + allCollected: "所有已收录的题目", + writingExplanation: "正在撰写题解...", + goToTheWebsiteToUse: "去网站使用", + checkTips: + "一般只要你开启了自动更新,那么当插件更新之后chrome会在五个小时以内自动更新。如果你想第一时间更新,或者您禁用了自动更新,都可以在这里检测最新版。", + checkBtn: "检测更新", + selfIntroduction: + "作者是一个 Github 40K star 的前端架构师,leetcode 刷题插件leetcode-cheatsheet作者,掌握各种算法套路,写了十几万字的算法刷题套路电子书,公众号回复【电子书】获取。", + allSolutions: { + columns: { + title: "题目", + tag: "标签", + }, + }, + }, + codeTemplateTab: { + name: "代码模板", + }, + dataStructureVisualizationTab: { + name: "数据结构可视化", + }, + + explanationTemplateTab: { + name: "题解模板", + }, + complexityQuickCheckTab: { + name: "复杂度速查", + }, + learningRouteTab: { + name: "学习路线", + }, + checkForUpdatesTab: { + name: "检查更新", + }, + aboutMeTab: { + name: "关于我", + }, +}; +export default cn; diff --git a/src/locales/en.js b/src/locales/en.js new file mode 100644 index 0000000..da78d0f --- /dev/null +++ b/src/locales/en.js @@ -0,0 +1,46 @@ +export const en = { + app: { + back: "Back to Home page", + viewSolution: "View solution", + viewInHandpickCollection: (t) => `This question has been collected in the handpick collection《${t}》Click to view`, + notCollected: "This question has not been collected by LeetCode Plus, click to view all collected questions", + allCollected: "All collected questions", + writingExplanation: "Writing explanation", + goToTheWebsiteToUse: "Go to the website to use", + checkTips: + "Generally, as long as you turn on automatic updates, chrome will automatically update within five hours after the plug-in is updated. If you want to update as soon as possible, or if you disable automatic updates, you can check the latest version here.", + checkBtn: "Check for updates", + selfIntroduction: + "The author is a front-end architect with 40K stars on Github, the author of the leetcode-cheatsheet leetcode plugin, master all kinds of algorithm routines, and wrote hundreds of thousands of words of algorithm brushing e-books. Reply to the public account [电子书] to get.", + allSolutions: { + columns: { + title: "Title", + tag: "Tag", + }, + }, + }, + codeTemplateTab: { + name: "Code Template", + }, + dataStructureVisualizationTab: { + name: "Data Structure Visualization", + }, + + explanationTemplateTab: { + name: "Explanation Template", + }, + complexityQuickCheckTab: { + name: "Complexity Quick Check", + }, + learningRouteTab: { + name: "Learning Route", + }, + checkForUpdatesTab: { + name: "Check for Updates", + }, + aboutMeTab: { + name: "About Me", + }, + }; + export default en; + \ No newline at end of file diff --git a/src/locales/index.js b/src/locales/index.js new file mode 100644 index 0000000..5b07f1c --- /dev/null +++ b/src/locales/index.js @@ -0,0 +1,47 @@ +import cn from "./cn"; +import en from "./en"; +import { getStorage, setStorage } from "../utils"; +const STORAGE_LANG_KEY = "LEETCODE_CHEAT_LANG"; +const LEETCODE_URL_CN = "https://leetcode.cn"; +const LEETCODE_URL_EN = "https://leetcode.com"; +const DEFAULT_LANG = "cn"; + +let lang = DEFAULT_LANG; + +const ALL_LANGS = { + cn, + en, +}; + +export const ALL_LANG_OPTIONS = { + cn: "简体中文", + en: "English", +}; + +export const AllLangs = Object.keys(ALL_LANGS); + +export const initLang = async () => { + lang = (await getStorage(STORAGE_LANG_KEY)) || DEFAULT_LANG; + setLang(lang); +}; + +export const setLang = (_lang) => { + const isCnHref = window.location.href.includes(LEETCODE_URL_CN); + lang = _lang || (isCnHref ? "cn" : "en"); + setStorage(STORAGE_LANG_KEY, lang); +}; + +// const getForPath = (obj, path) => { +// const pathArr = path.split("."); +// let result = obj; +// for (const key of pathArr) { +// result = result[key]; +// } +// return result; +// } + + +// window.t = (keypath) => { +// return getForPath({Locale:ALL_LANGS[lang]}, keypath) +// } +export default ALL_LANGS[lang]; From e8c73ea5b05bed2785dc253699cdb18e9dbd6e0b Mon Sep 17 00:00:00 2001 From: Renkin <906155099@qq.com> Date: Wed, 18 Oct 2023 17:43:14 +0800 Subject: [PATCH 2/3] feat: Use the 't' function to generate text --- src/App.js | 47 ++++++++++++++++++++----------------------- src/locales/cn.js | 16 +++++++-------- src/locales/en.js | 16 +++++++-------- src/locales/index.js | 48 ++++++++++++++++++++++++++------------------ 4 files changed, 67 insertions(+), 60 deletions(-) diff --git a/src/App.js b/src/App.js index d927523..ad79427 100644 --- a/src/App.js +++ b/src/App.js @@ -22,7 +22,7 @@ import "./App.css"; import CodeTemplates from "./codeTemplates/codeTemplate"; import ComplexityRating from "./complexityRating/index"; import SolutionTemplate from "./solutionTemplate/index"; -import Locale, { initLang } from "./locales"; +import { t, initLang } from "./locales"; // import { data as a } from "./db/binary-tree"; const DataStrutureVis = isInExtension() @@ -42,7 +42,7 @@ const chrome = window.chrome; const columns = [ { - title: Locale.app.allSolutions.columns.title, + title: t("Locale.app.allSolutions.columns.title"), dataIndex: "name", width: "300", align: "center", @@ -57,7 +57,7 @@ const columns = [ ), }, { - title: Locale.app.allSolutions.columns.tag, + title: t("Locale.app.allSolutions.columns.tag"), dataIndex: "pre", align: "center", render: (tags) => ( @@ -88,7 +88,9 @@ function App() { chrome.tabs && // eslint-disable-next-line chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => { + console.log("[leetcode 插件打印]:chrome.tabs.query", tabs); const currentUrl = tabs[0].url; + initLang(currentUrl); const match = currentUrl.match(/problems\/(.+?)\//); const problemId = match && match[1]; setProblemId(problemId); @@ -122,9 +124,6 @@ function App() { // }, 1000); // console.log(a); - useEffect(() => { - initLang(); - }) return (
{page !== "" ? ( ) : ( "" )} {hasSolution && page === "" ? ( ))}
@@ -196,9 +193,9 @@ function App() {
- +
- {Locale.app.allCollected} + {t("Locale.app.allCollected")}
- + {isInExtension() ? ( ) : ( Loading...}> @@ -236,7 +233,7 @@ function App() { {!isInExtension() && ( @@ -244,29 +241,29 @@ function App() { - + {isInExtension() && ( - -
{Locale.app.checkTips}
+ +
{t("Locale.app.checkTips")}
)} - +
-
{Locale.app.selfIntroduction}
+
{t("Locale.app.selfIntroduction")}
diff --git a/src/locales/cn.js b/src/locales/cn.js index 6161605..6ca8fed 100644 --- a/src/locales/cn.js +++ b/src/locales/cn.js @@ -2,7 +2,7 @@ export const cn = { app: { back: "返回主页", viewSolution: "查看本题题解", - viewInHandpickCollection: (t) => `该题已被收录到精选合集《${t}》点击查看`, + viewInHandpickCollection:"该题已被收录到精选合集《{slotText}》点击查看", notCollected: "本题暂未被力扣加加收录,点击查看所有已收录题目~", allCollected: "所有已收录的题目", writingExplanation: "正在撰写题解...", @@ -19,26 +19,26 @@ export const cn = { }, }, }, - codeTemplateTab: { + codeTemplate: { name: "代码模板", }, - dataStructureVisualizationTab: { + dataStructureVisualization: { name: "数据结构可视化", }, - explanationTemplateTab: { + explanationTemplate: { name: "题解模板", }, - complexityQuickCheckTab: { + complexityQuickCheck: { name: "复杂度速查", }, - learningRouteTab: { + learningRoute: { name: "学习路线", }, - checkForUpdatesTab: { + checkForUpdates: { name: "检查更新", }, - aboutMeTab: { + aboutMe: { name: "关于我", }, }; diff --git a/src/locales/en.js b/src/locales/en.js index da78d0f..8e28b42 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -2,7 +2,7 @@ export const en = { app: { back: "Back to Home page", viewSolution: "View solution", - viewInHandpickCollection: (t) => `This question has been collected in the handpick collection《${t}》Click to view`, + viewInHandpickCollection:"This question has been collected in the handpick collection《{slotText}》Click to view", notCollected: "This question has not been collected by LeetCode Plus, click to view all collected questions", allCollected: "All collected questions", writingExplanation: "Writing explanation", @@ -19,26 +19,26 @@ export const en = { }, }, }, - codeTemplateTab: { + codeTemplate: { name: "Code Template", }, - dataStructureVisualizationTab: { + dataStructureVisualization: { name: "Data Structure Visualization", }, - explanationTemplateTab: { + explanationTemplate: { name: "Explanation Template", }, - complexityQuickCheckTab: { + complexityQuickCheck: { name: "Complexity Quick Check", }, - learningRouteTab: { + learningRoute: { name: "Learning Route", }, - checkForUpdatesTab: { + checkForUpdates: { name: "Check for Updates", }, - aboutMeTab: { + aboutMe: { name: "About Me", }, }; diff --git a/src/locales/index.js b/src/locales/index.js index 5b07f1c..cbf34c4 100644 --- a/src/locales/index.js +++ b/src/locales/index.js @@ -1,7 +1,7 @@ import cn from "./cn"; import en from "./en"; -import { getStorage, setStorage } from "../utils"; -const STORAGE_LANG_KEY = "LEETCODE_CHEAT_LANG"; +// import { getStorage, setStorage } from "../utils"; +// const STORAGE_LANG_KEY = "LEETCODE_CHEAT_LANG"; const LEETCODE_URL_CN = "https://leetcode.cn"; const LEETCODE_URL_EN = "https://leetcode.com"; const DEFAULT_LANG = "cn"; @@ -20,28 +20,38 @@ export const ALL_LANG_OPTIONS = { export const AllLangs = Object.keys(ALL_LANGS); -export const initLang = async () => { - lang = (await getStorage(STORAGE_LANG_KEY)) || DEFAULT_LANG; - setLang(lang); +export const initLang = async (currentUrl) => { + const isCnHref = currentUrl.includes(LEETCODE_URL_CN); + setLang(isCnHref ? "cn" : "en"); }; export const setLang = (_lang) => { - const isCnHref = window.location.href.includes(LEETCODE_URL_CN); - lang = _lang || (isCnHref ? "cn" : "en"); - setStorage(STORAGE_LANG_KEY, lang); + lang = _lang || DEFAULT_LANG; }; -// const getForPath = (obj, path) => { -// const pathArr = path.split("."); -// let result = obj; -// for (const key of pathArr) { -// result = result[key]; -// } -// return result; -// } +const getForPath = (obj, path) => { + const pathArr = path.split("."); + let result = obj; + for (const key of pathArr) { + result = result[key]; + } + return result; +}; +export const t = (keypath, slotText) => { + const langData ={ Locale: ALL_LANGS[lang] } + if (!keypath) return ""; + let content = getForPath(langData, keypath); + if (slotText) { + if (Array.isArray(slotText)) { + slotText.map((item, idx) => { + content = content.replace(`{${idx}}`, item); + }) + } else { + content = content.replace("{slotText}", slotText); + } + } + return content; +}; -// window.t = (keypath) => { -// return getForPath({Locale:ALL_LANGS[lang]}, keypath) -// } export default ALL_LANGS[lang]; From cde9a4ac0f68d94a3460f41d9d5aec204e0d6bd7 Mon Sep 17 00:00:00 2001 From: Renkin <906155099@qq.com> Date: Thu, 19 Oct 2023 14:52:09 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8F=AF=E8=A7=86?= =?UTF-8?q?=E5=8C=96=E8=B0=83=E8=AF=95=E5=92=8C=E5=86=99=E9=A2=98=E8=A7=A3?= =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/contentScript.js | 79 +++++++++++++++++++--------------- src/solutionTemplate/index.jsx | 8 ++-- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/contentScript.js b/src/contentScript.js index 5775d2a..2194bb0 100644 --- a/src/contentScript.js +++ b/src/contentScript.js @@ -211,7 +211,7 @@ function getProviedTestCases(includeArray = true) { // } function goToVisDebug() { - const language = document.querySelector("#lang-select").innerText; + const language = getCodeLanguage(); const supportedLanguages = ["Python3", "JavaScript", "C++"]; const languageMap = { Python3: "3", @@ -345,11 +345,24 @@ int main() ); } +function getCodeLanguage() { + const langMap = { + "cpp": "C++", + "python3": "Python3", + "java": "Java", + "c": "C", + "javascript": "JavaScript", + } + const l =window?.monaco?.editor?.getModels()[0]?.getLanguageId() || + localStorage.getItem("global_lang") + + return langMap[l.toLowerCase()] + +} function insertButton() { const buttons = document.querySelectorAll("button"); for (var i = 0; i < buttons.length; ++i) { - if (buttons[i].innerText.includes("执行代码")) { - + if (buttons[i].innerText.includes("运行")) { // const container = document.createElement("div"); // buttons[i].parentElement.prepend(container); @@ -363,18 +376,18 @@ function insertButton() { // ); // const writeSolutionButton = document.createElement("div"); - const copyButton = buttons[i].cloneNode(true); - copyButton.innerText = "复制用例"; - copyButton.style["margin-left"] = "10px"; - copyButton.onclick = () => { - const cases = getProviedTestCases(); - if (cases.filter(Boolean).length === 0) return bjwd(); - copyToClipboard(cases.join("\n")); - message.success({ - content: "复制成功~", - }); - }; - buttons[i].parentElement.prepend(copyButton); + // const copyButton = buttons[i].cloneNode(true); + // copyButton.innerText = "复制用例"; + // copyButton.style["margin-left"] = "10px"; + // copyButton.onclick = () => { + // const cases = getProviedTestCases(); + // if (cases.filter(Boolean).length === 0) return bjwd(); + // copyToClipboard(cases.join("\n")); + // message.success({ + // content: "复制成功~", + // }); + // }; + // buttons[i].parentElement.prepend(copyButton); const writeSolutionButton = document.createElement("a"); writeSolutionButton.innerText = "写题解"; writeSolutionButton.style["margin-right"] = "20px"; @@ -383,29 +396,25 @@ function insertButton() { writeSolutionButton.onclick = () => { // d: "1579. 保证图可完全遍历" - const ele = document.querySelector(`[data-cypress="QuestionTitle"]`); + const desc = document.querySelector( + "[data-track-load=\"description_content\"]" + ).innerHTML; - if (!ele) { + if (!desc) { return message.warn({ content: "获取题目描述失败,请先切换到题目描述标签", }); } - const d = ele.innerHTML; - const title = d.match(/(\d+.+)(?=<)/)[1]; - const link = window.location.origin + d.match(/href="(.*?)"/)[1]; - const language = document.querySelector("#lang-select").innerText; + const title = document.title; + const link = window.location.href; + const language = getCodeLanguage(); // let code = document.querySelector( // ".monaco-scrollable-element,.editor-scrollable" // ).innerText; const code = window?.monaco?.editor?.getModels()[0]?.getValue(); - const desc = document.querySelector("#question-detail-main-tabs") - ?.children[1]?.children[0]?.children[1]?.innerText; - if (!desc) { - return message.warn({ - content: "获取题目描述失败,请先切换到题目描述标签", - }); - } + // const desc = document.querySelector("#question-detail-main-tabs")?.children[1]?.children[0]?.children[1]?.innerText; + const hide = message.loading("正在存储题目信息,请稍后~", 0); writeSolutionButton.setAttribute("disabled", true); // Dismiss manually and asynchronously @@ -478,7 +487,7 @@ function insertButton() { buttons[i].parentElement.prepend(visDebugButton); inserted = true; } else if (buttons[i].innerText.includes("提交")) { - const click = buttons[i].onclick + const click = buttons[i].onclick; buttons[i].onclick = (...args) => { click.call(buttons[i], ...args); @@ -518,12 +527,12 @@ const timerId = setInterval(() => { clearInterval(timerId); return console.error("初始化 chrome 插件 content script 失败"); } - insertButton() - if (inserted && submitProxied) { - window.location.title = ""; - // 可进入禅定模式 - zenAble(); - } + insertButton(); + // if (inserted && submitProxied) { + // window.location.title = ""; + // // 可进入禅定模式 + // zenAble(); + // } retried++; }, 1000); diff --git a/src/solutionTemplate/index.jsx b/src/solutionTemplate/index.jsx index 0696913..61cb401 100644 --- a/src/solutionTemplate/index.jsx +++ b/src/solutionTemplate/index.jsx @@ -81,9 +81,7 @@ ${link} ## 题目描述 -\`\`\` ${desc} -\`\`\` ## 前置知识 @@ -343,9 +341,9 @@ export default class SolutionTemplate extends PureComponent { this.setLanguage(v); this.setTemplate( template - .replace(new RegExp(`\`\`\`.+`, "mg"), `\`\`\`${v}`) - .replace( - new RegExp(`语言支持:.+`, "mg"), + .replace(new RegExp(`\`\`\`.+`, "mg"), `\`\`\`${v}`) + .replace( + new RegExp(`语言支持:.+`, "mg"), `语言支持:${displayLanguage(v)}` ) .replace(