提取 codepen 上的代码并转换成 Markdown 格式,从而实现一键迁移至code-flux平台。
// ==UserScript==
// @name codepen 代码提取器
// @namespace https://xxxily.
// @version 0.0.1
// @license MIT
// @description 提取 codepen 上的代码并转换成 Markdown 格式,从而实现一键迁移至code-flux平台。
// @author Blaze
// @match *://*.codepen.io/*
// @match *://*.jsbin.com/*
// @match *://*.jsfiddle.net/*
// @grant GM_setClipboard
// @grant GM_addStyle
// ==/UserScript==
(function () {
'use strict'
// 添加样式
GM_addStyle(`
.code-extractor-btn {
background-color: #4CAF50;
border: none;
color: white;
padding: 5px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
margin: 4px 10px;
cursor: pointer;
border-radius: 4px;
line-height: 32px;
}
.code-extractor-btn:hover {
background-color: #45a049;
}
.code-extractor-message {
position: fixed;
top: 20px;
right: 20px;
background-color: #4CAF50;
color: white;
padding: 15px;
border-radius: 4px;
z-index: 9999;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: opacity 0.3s;
}
`)
// 检查页面上是否有 CodeMirror 实例
function checkForCodeMirror () {
const codeMirrors = document.querySelectorAll('.CodeMirror')
if (codeMirrors.length > 0) {
// 检查是否存在指定的 DOM 元素
const targetButton = document.querySelector('#main-header button[title="Love"]')
if (targetButton) {
// 检查是否已经插入了提取按钮
if (!document.querySelector('.code-extractor-btn')) {
// 创建提取按钮
const extractButton = document.createElement('button')
extractButton.className = 'code-extractor-btn'
extractButton.textContent = '提取代码'
extractButton.addEventListener('click', extractCodeToMarkdown)
// 插入按钮到目标按钮前面
targetButton.parentNode.insertBefore(extractButton, targetButton)
}
} else {
// 如果没有找到目标按钮,可以考虑添加一个悬浮按钮或其他方式
console.log('未找到目标按钮,但页面上存在 CodeMirror 实例')
}
}
}
// 显示消息提示
function showMessage (message) {
// 移除可能存在的旧消息
const oldMessage = document.querySelector('.code-extractor-message')
if (oldMessage) {
oldMessage.remove()
}
// 创建新消息元素
const messageEl = document.createElement('div')
messageEl.className = 'code-extractor-message'
messageEl.textContent = message
document.body.appendChild(messageEl)
// 2秒后自动消失
setTimeout(() => {
messageEl.style.opacity = '0'
setTimeout(() => {
messageEl.remove()
}, 300)
}, 2000)
}
// 从 HTML 代码中提取 title
function extractTitleFromHtml (htmlCode) {
const titleMatch = htmlCode.match(/<title>(.*?)<\/title>/i)
return titleMatch ? titleMatch[1].trim() : null
}
// 获取代码的语言
function getLanguageFromMode (mode) {
if (!mode) return ''
// 处理可能的对象形式
if (typeof mode === 'object' && mode.name) {
mode = mode.name
}
// 映射 CodeMirror 模式到 Markdown 语言标识符
const modeMap = {
javascript: 'javascript',
'text/javascript': 'javascript',
js: 'javascript',
html: 'html',
htmlmixed: 'html',
'text/html': 'html',
css: 'css',
'text/css': 'css',
xml: 'xml',
python: 'python',
ruby: 'ruby',
php: 'php',
clike: 'c',
java: 'java'
// 可以根据需要添加更多映射
}
return modeMap[mode] || ''
}
// 提取代码并转换为 Markdown
function extractCodeToMarkdown () {
const codeMirrors = document.querySelectorAll('.CodeMirror')
if (codeMirrors.length === 0) {
showMessage('未找到 CodeMirror 实例')
return
}
const pageTitle = document.title
let markdownContent = `# ${pageTitle}\n\n`
codeMirrors.forEach((cm, index) => {
if (cm && cm.CodeMirror) {
const editor = cm.CodeMirror
const code = editor.getValue()
const mode = editor.getMode ? editor.getMode() : (editor.options ? editor.options.mode : '')
const language = getLanguageFromMode(mode)
// 如果是 HTML 代码,尝试提取 title
if (language === 'html' && index === 0) {
const htmlTitle = extractTitleFromHtml(code)
if (htmlTitle) {
markdownContent = `# ${htmlTitle}\n\n`
}
}
markdownContent += `\`\`\`${language}\n${code}\n\`\`\`\n\n`
} else if (cm.__vue__ && cm.__vue__.cminstance) {
// 处理某些 Vue 封装的 CodeMirror
const editor = cm.__vue__.cminstance
const code = editor.getValue()
const mode = editor.getMode ? editor.getMode() : (editor.options ? editor.options.mode : '')
const language = getLanguageFromMode(mode)
if (language === 'html' && index === 0) {
const htmlTitle = extractTitleFromHtml(code)
if (htmlTitle) {
markdownContent = `# ${htmlTitle}\n\n`
}
}
markdownContent += `\`\`\`${language}\n${code}\n\`\`\`\n\n`
} else {
// 尝试其他可能的 CodeMirror 实例获取方式
try {
const instance = cm.querySelector('.CodeMirror-code')
if (instance) {
const code = Array.from(instance.querySelectorAll('.CodeMirror-line'))
.map(line => line.textContent)
.join('\n')
markdownContent += `\`\`\`\n${code}\n\`\`\`\n\n`
}
} catch (e) {
console.error('提取代码时出错:', e)
}
}
})
// 复制到剪贴板
GM_setClipboard(markdownContent)
showMessage('代码已成功复制到剪贴板!')
}
// 页面加载完成后检查 CodeMirror
window.addEventListener('load', checkForCodeMirror)
// 定期检查 CodeMirror 是否被动态加载,最多检查10次
let checkCount = 0
const checkInterval = setInterval(() => {
checkForCodeMirror()
checkCount++
// 如果已经找到 CodeMirror 实例或者已经检查了10次,则停止检查
if (document.querySelectorAll('.CodeMirror').length > 0 || checkCount >= 10) {
clearInterval(checkInterval)
}
}, 1000)
})()