基于pycharm实现html文件的快速达成问题讨论
仍然无法实现编译的功能。
1.目录结构
2.1
static-pygments.css
代码:
/* Pygments 代码高亮样式 */
.highlight {
background: #f8f8f8;
border-radius: 4px;
padding: 10px;
overflow: auto;
}
.highlight pre {
margin: 0;
padding: 0;
background: transparent;
}
.highlight .lineno {
color: #aaa;
padding-right: 10px;
border-right: 1px solid #ddd;
margin-right: 10px;
}
/* 语法高亮颜色 */
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #666666 } /* Literal.Number.Bin */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0000FF } /* Name.Function.Magic */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .vm { color: #19177C } /* Name.Variable.Magic */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
2.2 static-style.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
header {
margin-bottom: 30px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
}
header h1 {
color: #2c3e50;
}
.btn {
display: inline-block;
padding: 8px 16px;
background: #ddd;
color: #333;
text-decoration: none;
border-radius: 4px;
border: none;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.btn-primary {
background: #3498db;
color: white;
}
.btn-secondary {
background: #95a5a6;
color: white;
}
.btn-outline {
background: transparent;
border: 1px solid #3498db;
color: #3498db;
}
.btn:hover {
opacity: 0.9;
transform: translateY(-2px);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"], input[type="password"], select, textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-family: inherit;
font-size: 14px;
}
textarea {
resize: vertical;
font-family: monospace;
}
.form-actions {
margin-top: 20px;
}
.snippet-info {
background: #f8f9fa;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
}
.snippet-info p {
margin-bottom: 10px;
}
.snippet-info input {
background: white;
padding: 5px;
width: 100%;
}
.code-container {
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
pre {
margin: 0;
padding: 15px;
background: #f8f9fa;
overflow-x: auto;
}
code {
font-family: 'Courier New', Courier, monospace;
}
.features {
margin-top: 30px;
}
.features ul {
list-style-type: none;
padding-left: 0;
}
.features li {
padding: 5px 0;
position: relative;
padding-left: 20px;
}
.features li:before {
content: "✓";
position: absolute;
left: 0;
color: #27ae60;
}
footer {
margin-top: 30px;
text-align: center;
color: #7f8c8d;
font-size: 14px;
}
.actions {
display: flex;
gap: 10px;
}
/* 创建页面布局 */
.create-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.input-section, .preview-section {
display: flex;
flex-direction: column;
}
.preview-section h3 {
margin-bottom: 15px;
color: #2c3e50;
}
.preview-container {
flex: 1;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
background: #f8f9fa;
min-height: 400px;
overflow: auto;
}
.preview-placeholder {
color: #7f8c8d;
font-style: italic;
text-align: center;
margin-top: 50%;
}
.preview-error {
color: #e74c3c;
text-align: center;
}
/* 密码页面 */
.password-form {
max-width: 400px;
margin: 0 auto;
text-align: center;
}
.password-form h2 {
margin-bottom: 15px;
color: #2c3e50;
}
.password-form p {
margin-bottom: 30px;
color: #7f8c8d;
}
.error-message {
color: #e74c3c;
margin-bottom: 15px;
padding: 10px;
background: #ffeaea;
border-radius: 4px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.create-container {
grid-template-columns: 1fr;
}
header {
flex-direction: column;
align-items: flex-start;
gap: 15px;
}
.actions {
flex-wrap: wrap;
}
}
3.1 templates-create.html
创建代码片段 - 代码分享
创建代码片段
返回首页
实时预览
代码高亮
执行效果
输入代码后,这里会显示语法高亮...
选择执行效果标签查看代码运行结果...
<script>
document.addEventListener('DOMContentLoaded', function() {
const codeTextarea = document.getElementById('code');
const languageSelect = document.getElementById('language');
const highlightResult = document.getElementById('highlight-result');
const executionResult = document.getElementById('execution-result');
const previewTabs = document.querySelectorAll('.preview-tab');
const previewContents = document.querySelectorAll('.preview-content');
let previewTimeout;
// 选项卡切换
previewTabs.forEach(tab => {
tab.addEventListener('click', function() {
const tabName = this.getAttribute('data-tab');
// 更新活跃选项卡
previewTabs.forEach(t => t.classList.remove('active'));
this.classList.add('active');
// 更新内容显示
previewContents.forEach(content => content.classList.remove('active'));
document.getElementById(`${tabName}-preview`).classList.add('active');
// 如果是执行效果标签,更新预览
if (tabName === 'execution') {
updateExecutionPreview();
}
});
});
// 更新代码高亮预览
function updateHighlightPreview() {
const code = codeTextarea.value;
const language = languageSelect.value;
if (!code.trim()) {
highlightResult.innerHTML = '输入代码后,这里会显示语法高亮...
';
return;
}
fetch('/preview', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
code: code,
language: language
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
highlightResult.innerHTML = data.html;
} else {
highlightResult.innerHTML = '高亮生成失败
';
}
})
.catch(error => {
console.error('高亮预览错误:', error);
highlightResult.innerHTML = '高亮生成失败
';
});
}
// 更新执行效果预览
function updateExecutionPreview() {
const code = codeTextarea.value;
const language = languageSelect.value;
if (!code.trim()) {
executionResult.innerHTML = '输入代码后,这里会显示执行效果...
';
return;
}
// 根据语言类型执行不同的预览
if (language === 'html' || (language === 'auto' && code.trim().startsWith('<'))) {
previewHTML(code);
} else if (language === 'css' || (language === 'auto' && code.includes('{'))) {
previewCSS(code);
} else if (language === 'javascript' || (language === 'auto' && (code.includes('function') || code.includes('=>')))) {
previewJavaScript(code);
} else {
executionResult.innerHTML = '此语言类型不支持执行预览
';
}
}
// HTML预览
function previewHTML(htmlCode) {
// 创建iframe来安全地预览HTML
const iframe = document.createElement('iframe');
iframe.className = 'html-preview-frame';
iframe.srcdoc = htmlCode;
executionResult.innerHTML = 'HTML渲染效果:
';
executionResult.appendChild(iframe);
}
// CSS预览
function previewCSS(cssCode) {
executionResult.innerHTML = `
CSS样式效果:
这是一个样式预览区域
应用的CSS:
${cssCode}
`;
// 应用CSS样式
try {
const style = document.createElement('style');
style.textContent = cssCode;
document.head.appendChild(style);
// 清理之前的样式
setTimeout(() => {
if (document.head.contains(style)) {
document.head.removeChild(style);
}
}, 100);
} catch (error) {
console.error('CSS应用错误:', error);
}
}
// JavaScript预览
function previewJavaScript(jsCode) {
executionResult.innerHTML = 'JavaScript执行结果:
';
try {
// 在安全环境中执行JavaScript
const result = Function(`"use strict"; ${jsCode}`)();
let output = '';
if (result !== undefined) {
output = typeof result === 'object' ?
JSON.stringify(result, null, 2) :
String(result);
} else {
output = '代码已执行,但没有返回值';
}
executionResult.innerHTML += `
执行成功!
${output}
`;
} catch (error) {
executionResult.innerHTML += `
执行错误:
${error.message}
`;
}
}
// 防抖更新预览
function debouncedUpdatePreview() {
clearTimeout(previewTimeout);
previewTimeout = setTimeout(() => {
updateHighlightPreview();
// 如果执行效果标签是活跃的,也更新它
if (document.querySelector('.preview-tab[data-tab="execution"]').classList.contains('active')) {
updateExecutionPreview();
}
}, 300);
}
// 事件监听
codeTextarea.addEventListener('input', debouncedUpdatePreview);
languageSelect.addEventListener('change', debouncedUpdatePreview);
// 初始预览
updateHighlightPreview();
});
</script>
3.2templates-index.html
简单代码分享
简单代码分享
快速分享你的代码片段
功能特性
- 简单易用的代码粘贴
- 实时预览效果
- 自动过期机制(7天)
- 支持多种编程语言
- 原始代码查看
3.3templates-password.html
密码保护 - 代码分享
密码保护
返回首页
此代码片段受密码保护
请输入密码查看 "{{ snippet.title }}"
3.4 templates-view.html
{{ snippet.title }} - 简单代码分享
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
4.1 app.py
from flask import Flask, render_template, request, redirect, url_for, jsonify
import uuid
import datetime
import sqlite3
import markdown
import html
import pygments
from pygments import highlight
from pygments.lexers import get_lexer_by_name, guess_lexer
from pygments.formatters import HtmlFormatter
import re
import os
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'
# 初始化数据库(包含迁移逻辑)
def init_db():
conn = sqlite3.connect('snippets.db')
c = conn.cursor()
# 创建表(如果不存在)
c.execute('''CREATE TABLE IF NOT EXISTS snippets
(id TEXT PRIMARY KEY,
title TEXT,
code TEXT,
language TEXT,
created_at TIMESTAMP,
expires_at TIMESTAMP,
password TEXT)''')
# 检查并添加缺失的列
c.execute("PRAGMA table_info(snippets)")
columns = [column[1] for column in c.fetchall()]
if 'password' not in columns:
c.execute("ALTER TABLE snippets ADD COLUMN password TEXT")
print("已添加 password 列到数据库")
conn.commit()
conn.close()
print("数据库初始化完成")
def get_db():
conn = sqlite3.connect('snippets.db')
conn.row_factory = sqlite3.Row
return conn
# 代码高亮函数
def highlight_code(code, language):
try:
if language == 'auto':
lexer = guess_lexer(code)
else:
lexer = get_lexer_by_name(language, stripall=True)
formatter = HtmlFormatter(linenos=True, cssclass="highlight")
result = highlight(code, lexer, formatter)
return result
except:
# 如果高亮失败,返回转义的HTML
return f'{html.escape(code)}
'
# 主页
@app.route('/')
def index():
return render_template('index.html')
# 创建代码片段
@app.route('/create', methods=['GET', 'POST'])
def create_snippet():
if request.method == 'POST':
title = request.form.get('title', 'Untitled')
code = request.form.get('code', '')
language = request.form.get('language', 'text')
password = request.form.get('password', '')
snippet_id = str(uuid.uuid4())[:8]
created_at = datetime.datetime.now()
expires_at = created_at + datetime.timedelta(days=7)
conn = get_db()
c = conn.cursor()
c.execute("INSERT INTO snippets VALUES (?, ?, ?, ?, ?, ?, ?)",
(snippet_id, title, code, language, created_at, expires_at, password))
conn.commit()
conn.close()
return redirect(url_for('view_snippet', snippet_id=snippet_id))
return render_template('create.html')
# 查看代码片段
@app.route('/view/', methods=['GET', 'POST'])
def view_snippet(snippet_id):
conn = get_db()
c = conn.cursor()
c.execute("SELECT * FROM snippets WHERE id = ?", (snippet_id,))
snippet = c.fetchone()
conn.close()
if snippet is None:
return "代码片段不存在", 404
expires_at = datetime.datetime.fromisoformat(snippet['expires_at'])
if datetime.datetime.now() > expires_at:
return "此代码片段已过期", 410
# 检查密码保护
if snippet['password']:
if request.method == 'POST':
if request.form.get('password') == snippet['password']:
# 密码正确,显示代码
highlighted_code = highlight_code(snippet['code'], snippet['language'])
return render_template('view.html', snippet=snippet, highlighted_code=highlighted_code)
else:
error = "密码错误"
return render_template('password.html', snippet=snippet, error=error)
else:
return render_template('password.html', snippet=snippet)
highlighted_code = highlight_code(snippet['code'], snippet['language'])
return render_template('view.html', snippet=snippet, highlighted_code=highlighted_code)
# 实时预览API
# 实时预览API - 确保这个路由存在
@app.route('/preview', methods=['POST'])
def preview():
try:
code = request.json.get('code', '')
language = request.json.get('language', 'text')
highlighted_code = highlight_code(code, language)
return jsonify({
'success': True,
'html': highlighted_code
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
})
# 原始代码
@app.route('/raw/')
def raw_snippet(snippet_id):
conn = get_db()
c = conn.cursor()
c.execute("SELECT code FROM snippets WHERE id = ?", (snippet_id,))
snippet = c.fetchone()
conn.close()
if snippet is None:
return "代码片段不存在", 404
return snippet['code'], 200, {'Content-Type': 'text/plain; charset=utf-8'}
if __name__ == '__main__':
init_db()
app.run(debug=True)