Compare commits
1 Commits
feature/go
...
feature/se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e90fca5ab1 |
@@ -16,9 +16,6 @@ NC='\033[0m' # No Color
|
||||
ubuntu_HOST="ubuntu"
|
||||
DEPLOY_PATH="/var/www"
|
||||
DEPLOY_NAME="app.cloud"
|
||||
# Sudo 密码(如果需要,建议配置无密码 sudo 更安全)
|
||||
# 配置无密码 sudo: 在服务器上运行: echo "username ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/username
|
||||
SUDO_PASSWORD="1231"
|
||||
|
||||
# 打印带颜色的消息
|
||||
print_info() {
|
||||
@@ -62,15 +59,13 @@ deploy_to_server() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# SSH 执行部署操作
|
||||
# SSH 执行部署操作(非交互模式)
|
||||
print_info "在 ${server} 上执行部署操作..."
|
||||
print_info "部署路径: ${DEPLOY_PATH}/${DEPLOY_NAME}"
|
||||
# 注意:密码通过环境变量传递,避免在命令行中暴露
|
||||
ssh_output=$(SSH_SUDO_PASSWORD="${SUDO_PASSWORD}" ssh ${server} bash << SSH_EOF
|
||||
ssh_output=$(ssh ${server} bash << SSH_EOF
|
||||
set -e
|
||||
DEPLOY_PATH="${DEPLOY_PATH}"
|
||||
DEPLOY_NAME="${DEPLOY_NAME}"
|
||||
SUDO_PASSWORD="\${SSH_SUDO_PASSWORD}"
|
||||
|
||||
# 检查部署目录是否存在
|
||||
if [ ! -d "\${DEPLOY_PATH}" ]; then
|
||||
@@ -78,35 +73,35 @@ deploy_to_server() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查是否有权限写入(尝试创建测试文件)
|
||||
# 检查是否有权限写入,若无则尝试免密 sudo(sudo -n)
|
||||
SUDO_CMD=""
|
||||
if ! touch "\${DEPLOY_PATH}/.deploy_test" 2>/dev/null; then
|
||||
echo "提示:没有直接写入权限,将使用 sudo 执行操作"
|
||||
USE_SUDO=1
|
||||
if sudo -n true 2>/dev/null; then
|
||||
echo "提示:没有直接写入权限,使用 sudo -n 执行部署操作"
|
||||
SUDO_CMD="sudo -n"
|
||||
else
|
||||
echo "错误:没有写入权限,且 sudo 需要密码(非交互部署无法输入)"
|
||||
echo "请执行以下任一方案后重试:"
|
||||
echo " 1) 将部署目录改为当前用户可写目录(例如 /home/\$USER/www)"
|
||||
echo " 2) 为当前用户配置免密 sudo(NOPASSWD)"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
rm -f "\${DEPLOY_PATH}/.deploy_test"
|
||||
USE_SUDO=0
|
||||
echo "提示:检测到部署目录可直接写入"
|
||||
fi
|
||||
|
||||
# 备份旧版本(如果存在)
|
||||
if [ -d "\${DEPLOY_PATH}/\${DEPLOY_NAME}" ]; then
|
||||
echo "备份旧版本..."
|
||||
if [ "\$USE_SUDO" = "1" ]; then
|
||||
echo "\${SUDO_PASSWORD}" | sudo -S rm -rf "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" 2>/dev/null || true
|
||||
echo "\${SUDO_PASSWORD}" | sudo -S mv "\${DEPLOY_PATH}/\${DEPLOY_NAME}" "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" || { echo "错误:备份失败,权限不足"; exit 1; }
|
||||
else
|
||||
rm -rf "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" 2>/dev/null || true
|
||||
mv "\${DEPLOY_PATH}/\${DEPLOY_NAME}" "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" || { echo "错误:备份失败"; exit 1; }
|
||||
fi
|
||||
\$SUDO_CMD rm -rf "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" 2>/dev/null || true
|
||||
\$SUDO_CMD mv "\${DEPLOY_PATH}/\${DEPLOY_NAME}" "\${DEPLOY_PATH}/\${DEPLOY_NAME}_bak" || { echo "错误:备份失败,权限不足"; exit 1; }
|
||||
fi
|
||||
|
||||
# 移动新版本到部署目录(覆盖现有目录)
|
||||
if [ -d ~/\${DEPLOY_NAME} ]; then
|
||||
echo "移动新版本到部署目录..."
|
||||
if [ "\$USE_SUDO" = "1" ]; then
|
||||
echo "\${SUDO_PASSWORD}" | sudo -S mv ~/\${DEPLOY_NAME} "\${DEPLOY_PATH}/" || { echo "错误:移动文件失败,权限不足"; exit 1; }
|
||||
else
|
||||
mv ~/\${DEPLOY_NAME} "\${DEPLOY_PATH}/" || { echo "错误:移动文件失败"; exit 1; }
|
||||
fi
|
||||
\$SUDO_CMD mv ~/\${DEPLOY_NAME} "\${DEPLOY_PATH}/" || { echo "错误:移动文件失败,权限不足"; exit 1; }
|
||||
echo "部署完成!"
|
||||
else
|
||||
echo "错误:找不到 ~/\${DEPLOY_NAME} 目录"
|
||||
@@ -116,7 +111,11 @@ deploy_to_server() {
|
||||
# 重新加载 nginx(如果配置了)
|
||||
if command -v nginx &> /dev/null; then
|
||||
echo "重新加载 nginx..."
|
||||
echo "\${SUDO_PASSWORD}" | sudo -S nginx -t && echo "\${SUDO_PASSWORD}" | sudo -S nginx -s reload || echo "警告:nginx 重新加载失败,请手动检查"
|
||||
if [ -n "\$SUDO_CMD" ]; then
|
||||
\$SUDO_CMD nginx -t && \$SUDO_CMD nginx -s reload || echo "警告:nginx 重新加载失败,请手动检查"
|
||||
else
|
||||
nginx -t && nginx -s reload || echo "警告:nginx 重新加载失败,请手动检查"
|
||||
fi
|
||||
fi
|
||||
SSH_EOF
|
||||
)
|
||||
|
||||
35
index.html
35
index.html
@@ -5,10 +5,9 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<!-- Multi-language Support -->
|
||||
<link rel="canonical" href="https://texpixel.com/" />
|
||||
<link rel="alternate" hreflang="zh-CN" href="https://texpixel.com/" />
|
||||
<link rel="alternate" hreflang="en" href="https://texpixel.com/en" />
|
||||
<link rel="alternate" hreflang="en" href="https://texpixel.com/en/" />
|
||||
<link rel="alternate" hreflang="x-default" href="https://texpixel.com/" />
|
||||
|
||||
<!-- Dynamic Title (will be updated by app) -->
|
||||
@@ -41,6 +40,34 @@
|
||||
<!-- Baidu Verification -->
|
||||
<meta name="baidu-site-verification" content="codeva-8zU93DeGgH" />
|
||||
|
||||
<!-- Structured Data -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"name": "TexPixel",
|
||||
"url": "https://texpixel.com/",
|
||||
"inLanguage": ["zh-CN", "en"],
|
||||
"description": "Formula recognition tool for converting images and PDFs into LaTeX, MathML, and Markdown."
|
||||
}
|
||||
</script>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "TexPixel",
|
||||
"applicationCategory": "BusinessApplication",
|
||||
"operatingSystem": "Web",
|
||||
"url": "https://texpixel.com/",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"description": "Online OCR and formula recognition for printed and handwritten mathematical expressions."
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Language Detection Script -->
|
||||
<script>
|
||||
// Update HTML lang attribute based on user preference or browser language
|
||||
@@ -64,4 +91,4 @@
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
167
public/en/index.html
Normal file
167
public/en/index.html
Normal file
@@ -0,0 +1,167 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>TexPixel - Formula Recognition Tool for LaTeX, MathML, and Markdown</title>
|
||||
<meta name="description" content="TexPixel converts printed and handwritten math formulas from images and PDFs into LaTeX, MathML, and Markdown." />
|
||||
<meta name="robots" content="index, follow" />
|
||||
<meta name="author" content="TexPixel Team" />
|
||||
<link rel="canonical" href="https://texpixel.com/en/" />
|
||||
<link rel="alternate" hreflang="zh-CN" href="https://texpixel.com/" />
|
||||
<link rel="alternate" hreflang="en" href="https://texpixel.com/en/" />
|
||||
<link rel="alternate" hreflang="x-default" href="https://texpixel.com/" />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="TexPixel" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:locale:alternate" content="zh_CN" />
|
||||
<meta property="og:url" content="https://texpixel.com/en/" />
|
||||
<meta property="og:title" content="TexPixel - Formula Recognition Tool" />
|
||||
<meta property="og:description" content="Extract formulas from images and PDFs to editable LaTeX, MathML, and Markdown." />
|
||||
<meta property="og:image" content="https://cdn.texpixel.com/public/logo.png?x-oss-process=image/resize,w_600" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@TexPixel" />
|
||||
<meta name="twitter:title" content="TexPixel - Formula Recognition Tool" />
|
||||
<meta name="twitter:description" content="Convert mathematical content from images and PDFs into LaTeX, MathML, and Markdown." />
|
||||
<meta name="twitter:image" content="https://cdn.texpixel.com/public/logo.png?x-oss-process=image/resize,w_600" />
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
"name": "TexPixel English",
|
||||
"url": "https://texpixel.com/en/",
|
||||
"inLanguage": "en",
|
||||
"description": "Formula recognition landing page in English."
|
||||
}
|
||||
</script>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What can TexPixel recognize?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "TexPixel recognizes printed and handwritten mathematical formulas from images and PDF pages."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Which output formats are supported?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "TexPixel supports LaTeX, MathML, and Markdown outputs for downstream editing and publishing."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Do I need to install software?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "No installation is required. TexPixel works as a web application."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #f7f8fc;
|
||||
--text: #111827;
|
||||
--muted: #4b5563;
|
||||
--accent: #0f766e;
|
||||
--accent-hover: #0d5f59;
|
||||
--card: #ffffff;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--text);
|
||||
background: radial-gradient(circle at 20% 20%, #eefbf8 0%, var(--bg) 40%, #f6f8ff 100%);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.wrap {
|
||||
max-width: 980px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 20px 64px;
|
||||
}
|
||||
.hero, .section {
|
||||
background: var(--card);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
box-shadow: 0 10px 30px rgba(17, 24, 39, 0.06);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 8px;
|
||||
font-size: clamp(28px, 4vw, 42px);
|
||||
line-height: 1.2;
|
||||
}
|
||||
h2 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 24px;
|
||||
}
|
||||
p { margin: 0 0 14px; color: var(--muted); }
|
||||
ul { margin: 0; padding-left: 20px; color: var(--muted); }
|
||||
li { margin-bottom: 8px; }
|
||||
.cta {
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
padding: 12px 18px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.cta:hover { background: var(--accent-hover); }
|
||||
.small { font-size: 14px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="wrap">
|
||||
<section class="hero">
|
||||
<h1>Formula Recognition for Real Math Workflows</h1>
|
||||
<p>TexPixel converts formulas from screenshots, photos, and PDF pages into editable text formats for researchers, students, and engineering teams.</p>
|
||||
<a class="cta" id="open-app" href="/">Open TexPixel App</a>
|
||||
<p class="small">The app opens at the main product URL and defaults to English for this entry point.</p>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Core Capabilities</h2>
|
||||
<ul>
|
||||
<li>Recognize printed and handwritten formulas from image or PDF input.</li>
|
||||
<li>Export to LaTeX for papers, MathML for web workflows, and Markdown for docs.</li>
|
||||
<li>Use the browser-based workflow without local software installation.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>FAQ</h2>
|
||||
<p><strong>Is TexPixel browser-based?</strong><br />Yes. You can upload files and get output directly in the web app.</p>
|
||||
<p><strong>What content type works best?</strong><br />Clean scans and high-contrast screenshots improve recognition quality.</p>
|
||||
<p><strong>Can I reuse output in technical documents?</strong><br />Yes. LaTeX and Markdown outputs are intended for editing and reuse.</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var openApp = document.getElementById('open-app');
|
||||
if (!openApp) return;
|
||||
openApp.addEventListener('click', function () {
|
||||
try {
|
||||
localStorage.setItem('language', 'en');
|
||||
} catch (err) {
|
||||
// Keep navigation working even if storage is unavailable.
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
14
public/llms.txt
Normal file
14
public/llms.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
# TexPixel
|
||||
|
||||
TexPixel is a web tool for converting images and PDFs into editable mathematical formats such as LaTeX, MathML, and Markdown.
|
||||
|
||||
Canonical URL: https://texpixel.com/
|
||||
Primary languages: zh-CN, en
|
||||
|
||||
## Preferred page for citation
|
||||
- https://texpixel.com/
|
||||
- https://texpixel.com/en/
|
||||
|
||||
## Crawl guidance
|
||||
- Public product content is allowed for indexing.
|
||||
- Avoid API and authenticated/private areas.
|
||||
7
public/robots.txt
Normal file
7
public/robots.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Disallow: /api/
|
||||
Disallow: /auth/
|
||||
Disallow: /admin/
|
||||
|
||||
Sitemap: https://texpixel.com/sitemap.xml
|
||||
15
public/sitemap.xml
Normal file
15
public/sitemap.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://texpixel.com/</loc>
|
||||
<lastmod>2026-02-25</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://texpixel.com/en/</loc>
|
||||
<lastmod>2026-02-25</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
Reference in New Issue
Block a user