Usage:
Install Templater Obsidian Plugin
Copy template_leetcode.md
, getProblem.js
and parseProblem.js
into your templater folder
Usage:
Install Templater Obsidian Plugin
Copy template_leetcode.md
, getProblem.js
and parseProblem.js
into your templater folder
async function getLeetProblem(tp, url) { | |
let titleSlug = extractProblemSlug(url); | |
let headersList = { | |
"Accept": "*/*", | |
"Accept-Language": "zh-CN,zh;q=0.9", | |
"Content-Type": "application/json", | |
"Origin": "https://leetcode.com", | |
"Priority": "u=1, i", | |
"Referer": "https://leetcode.com/", | |
"Sec-Ch-Ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"", | |
"Sec-Ch-Ua-Arch": "\"arm\"", | |
"Sec-Ch-Ua-Bitness": "\"64\"", | |
"Sec-Ch-Ua-Full-Version": "\"135.0.7049.85\"", | |
"Sec-Ch-Ua-Full-Version-List": "\"Google Chrome\";v=\"135.0.7049.85\", \"Not-A.Brand\";v=\"8.0.0.0\", \"Chromium\";v=\"135.0.7049.85\"", | |
"Sec-Ch-Ua-Mobile": "?0", | |
"Sec-Ch-Ua-Model": "\"\"", | |
"Sec-Ch-Ua-Platform": "\"macOS\"", | |
"Sec-Ch-Ua-Platform-Version": "\"15.4.0\"", | |
"Sec-Fetch-Dest": "empty", | |
"Sec-Fetch-Mode": "cors", | |
"Sec-Fetch-Site": "same-origin", | |
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36", | |
} | |
let gqlBody = { | |
query: `query questionData($titleSlug: String!) { | |
question(titleSlug: $titleSlug) { | |
questionId | |
questionFrontendId | |
boundTopicId | |
title | |
titleSlug | |
content | |
translatedTitle | |
translatedContent | |
isPaidOnly | |
difficulty | |
likes | |
dislikes | |
isLiked | |
similarQuestions | |
contributors { | |
username | |
profileUrl | |
avatarUrl | |
__typename | |
} | |
langToValidPlayground | |
topicTags { | |
name | |
slug | |
translatedName | |
__typename | |
} | |
companyTagStats | |
codeSnippets { | |
lang | |
langSlug | |
code | |
__typename | |
} | |
stats | |
hints | |
solution { | |
id | |
canSeeDetail | |
__typename | |
} | |
status | |
sampleTestCase | |
metaData | |
judgerAvailable | |
judgeType | |
mysqlSchemas | |
enableRunCode | |
enableTestMode | |
envInfo | |
libraryUrl | |
__typename | |
} | |
}`, | |
variables: { "titleSlug": titleSlug } | |
} | |
let bodyContent = JSON.stringify(gqlBody); | |
let response = await tp.obsidian.request({ | |
url: "https://leetcode.com/graphql", | |
method: "POST", | |
body: bodyContent, | |
headers: headersList | |
}); | |
console.log(response.content); | |
return JSON.parse(response); | |
} | |
function extractProblemSlug(url) { | |
const regex = /\/problems\/([^/]+)\//; | |
const match = url.match(regex); | |
if (match && match[1]) { | |
return match[1]; | |
} else { | |
return null; // Invalid or unsupported URL format | |
} | |
} | |
module.exports = getLeetProblem; | |
async function formatLeetCodeContent(tp, htmlContent) { | |
// 1. Get the initial Markdown conversion | |
let processedHtml = htmlContent.replace(/(-?\d+)<sup>(\d+)<\/sup>/g, '$1^$2'); | |
let markdown = await tp.obsidian.htmlToMarkdown(processedHtml); | |
// 2. Process Examples: Wrap in code blocks, remove bold from header AND content | |
markdown = markdown.replace( | |
/(\*\*Example \d+:\*\*)\s*([\s\S]*?)(?=\n\*\*Example|\n\*\*Constraints:|\n*$)/g, | |
(match, header, content) => { | |
let cleanHeader = header.replace(/\*\*/g, ''); // Remove '**' from "Example X:**" header | |
let trimmedContent = content.trim(); | |
// --- NEW: Clean the content *before* wrapping --- | |
let cleanContent = trimmedContent.replace(/\*\*/g, '').replace(/`/g, ''); // Remove bold AND backticks | |
// Return formatted block | |
return `\n${cleanHeader}\n\n\`\`\`\n${cleanContent}\n\`\`\`\n`; | |
} | |
); | |
// 3. Process Constraints: Wrap in code block, remove bold/backticks, format exponents | |
markdown = markdown.replace( | |
/(\*\*Constraints:\*\*)\s*([\s\S]*?)(?=\n*$)/g, | |
(match, header, content) => { | |
let cleanHeader = header.replace(/\*\*/g, ''); // Remove '**' from "Constraints:" header | |
let trimmedContent = content.trim(); | |
// --- NEW: Clean the content *before* other formatting --- | |
let cleanContent = trimmedContent.replace(/\*\*/g, '').replace(/`/g, ''); // Remove bold AND backticks | |
// Now apply other formatting rules to the cleaned content | |
cleanContent = cleanContent.replace(/^\s*-\s+/gm, ''); // Remove list markers | |
// Return formatted block | |
return `\n${cleanHeader}\n\n\`\`\`\n${cleanContent}\n\`\`\`\n`; | |
} | |
); | |
// 4. Clean up extra newlines | |
return markdown.replace(/\n{3,}/g, '\n\n').trim(); | |
} | |
module.exports = formatLeetCodeContent; |
---
<%*
let url = await tp.system.prompt("leetcode url?");
let problem = await tp.user.getProblem(tp, url);
let question = problem.data.question;
let formattedContent = await tp.user.parseProblem(tp, question.content)
console.log(question);
tp.file.rename(question.questionId + ". " + question.title);
_%>
category:
- "[[LeetCode Daily]]"
url: <% `https://leetcode.com/problems/${question.titleSlug}/` %>
difficulty: <% question.difficulty %>
concepts:
<%*
question.topicTags.forEach(item => {
tR += `- ${item.name}\n`
}) _%>
created: <% tp.file.creation_date() %>
solved: false
hint:
---
<% formattedContent %>
<% await tp.file.move("LeetCode/" + question.questionFrontendId + ". " + question.title) %>