Files
gitea-docs/i18n/zh-cn/docusaurus-plugin-content-docs/current/administration/customizing-gitea.md
2026-07-08 04:58:43 +00:00

21 KiB
Raw Blame History

date, slug, sidebar_position, aliases
date slug sidebar_position aliases
2017-04-15T14:56:00+02:00 customizing-gitea 100
/zh-cn/customizing-gitea

自定义 Gitea

自定义 Gitea 通常通过 CustomPath 目录完成。默认情况下它是工作目录WorkPath下的 custom 目录,但如果您的安装方式做了不同设置,也可能位于其他位置。 这是覆盖配置项、模板等内容的核心位置。您可以通过 gitea help 查看 CustomPath,也可以在 站点管理 页面的 Configuration 选项卡中找到该路径。您还可以通过设置 GITEA_CUSTOM 环境变量,或在 gitea 二进制上使用 --custom-path 选项来覆盖 CustomPath。 (命令行选项会覆盖环境变量。)

如果 Gitea 以二进制方式部署,所有默认路径都相对于 Gitea 二进制文件。 如果通过发行版安装,这些路径通常会按照 Linux 文件系统标准进行调整。Gitea 会尝试创建所需目录, 包括 custom/。某些发行版可能会通过 /etc/gitea/custom 提供一个符号链接。

应用配置可以在 CustomConf 文件中找到,默认路径为 $GITEA_CUSTOM/conf/app.ini 但如果您的安装方式修改了配置,也可能位于其他位置。 同样,您可以通过 gitea help 查看该变量,也可以使用 gitea 二进制的 --config 选项覆盖它。

如果在检查 gitea help 后仍找不到 CustomPath 目录,请检查 GITEA_CUSTOM 环境变量; 它可以用来将默认路径覆盖为其他位置。例如,GITEA_CUSTOM 可能由 init 脚本设置。 您也可以在站点管理页面的 “Configuration” 选项卡下检查该值是否已设置。

:::note Gitea 必须执行完整重启后,配置更改才会生效。 :::

提供自定义公共文件

要让 Gitea 提供自定义公共文件(例如页面和图片),请将 $GITEA_CUSTOM/public/ 目录作为 webroot。Gitea 会跟随符号链接。 当前仅提供以下文件:

  • public/robots.txt
  • public/.well-known/ 目录中的文件
  • public/assets/ 目录中的文件

例如,存放在 $GITEA_CUSTOM/public/assets/ 中的 image.png 文件,可以通过 http://gitea.domain.tld/assets/image.png 访问。

如果要构建自定义 logo 和/或 favicon请克隆 Gitea 源码仓库,替换 assets/logo.svg 和/或 assets/favicon.svg,然后运行 make generate-imagesassets/favicon.svg 仅用于 favicon。执行后会更新以下输出文件随后您可以将它们放到服务器上的 $GITEA_CUSTOM/public/assets/img 中:

  • public/assets/img/logo.svg - 用于站点图标、应用图标
  • public/assets/img/logo.png - 用于 Open Graph
  • public/assets/img/avatar_default.png - 用作默认头像图片
  • public/assets/img/apple-touch-icon.png - 用于 iOS 设备书签
  • public/assets/img/favicon.svg - 用于 favicon
  • public/assets/img/favicon.png - 用作不支持 SVG favicon 的浏览器回退图标

如果源图片不是矢量格式,您可以尝试使用诸如这个工具 将光栅图像转换为矢量图。

自定义 Gitea 页面和资源

Gitea 可执行文件内置了运行所需的全部资源:模板、图片、样式表和翻译。您可以在 custom 目录下放置与原路径一致的替换文件来覆盖其中任意资源。例如,要替换 C++ 仓库默认提供的 .gitignore,我们需要替换 options/gitignore/C++。为此,您必须将替换文件放到 $GITEA_CUSTOM/options/gitignore/C++CustomPath 目录位置见本文开头说明)。

Gitea 的每一个页面都可以修改。动态内容通过 go template 生成,您可以通过在 $GITEA_CUSTOM/templates 目录下放置替换文件进行修改。

要获取任意内嵌文件(包括模板),可以使用gitea embedded 工具。 另外,也可以在 Gitea 源码仓库的 templates 目录中找到它们。(注意:示例链接指向 main 分支,请确保所使用的模板与您当前的发布版本兼容。)

请注意,任何包含在 {{}} 中的语句都是 Gitea 的模板语法, 如果您没有完全理解这些组件,就不应修改它们。

自定义首页 / 主页

将与您所使用 Gitea 版本对应的 home.tmpltemplates 目录复制到 $GITEA_CUSTOM/templates。 随后按您的需要编辑即可。 不要忘记重启 Gitea 以应用更改。

添加链接和页签

如果您只是想为顶部导航栏或页脚添加额外链接,或者为仓库视图添加额外页签, 可以将它们分别放入 $GITEA_CUSTOM/templates/custom/ 目录中的 extra_links.tmpl(添加到导航栏的链接)、extra_links_footer.tmpl (添加到页脚左侧的链接)和 extra_tabs.tmpl

例如,假设您在德国,需要添加法律上通常要求提供的 “Impressum”/关于页面,用来说明谁对站点内容负责: 只需将该页面放到 $GITEA_CUSTOM/public/assets/ 目录中 (例如 $GITEA_CUSTOM/public/assets/impressum.html),再在 $GITEA_CUSTOM/templates/custom/extra_links.tmpl$GITEA_CUSTOM/templates/custom/extra_links_footer.tmpl 中加入指向它的链接即可。

为了匹配当前样式,该链接应使用类名 item,并且您可以使用 {{AppSubUrl}} 获取基础 URL <a class="item" href="{{AppSubUrl}}/assets/impressum.html">Impressum</a>

更多信息请参见添加法律页面

您也可以用同样的方式添加新页签,将其放入 extra_tabs.tmpl 中。 与其他页签样式匹配所需的精确 HTML 位于文件 templates/repo/header.tmpl GitHub 源码)。

页面中的其他插入内容

除了 extra_links.tmplextra_tabs.tmpl 之外,您还可以在 $GITEA_CUSTOM/templates/custom/ 目录中放置其他有用的模板:

  • header.tmpl,位于 <head> 结束标签之前,例如可用于添加自定义 CSS 文件。
  • body_outer_pre.tmpl,位于 <body> 起始标签之后。
  • body_inner_pre.tmpl,位于顶部导航栏之前,但已处于主容器 <div class="full height"> 内部。
  • body_inner_post.tmpl,位于主容器结束之前。
  • body_outer_post.tmpl,位于底部 <footer> 元素之前。
  • footer.tmpl,位于 <body> 结束标签之前,是放置额外 JavaScript 的合适位置。

使用 Gitea 变量

您可以在自定义模板中使用各种 Gitea 变量。

首先,临时 启用开发模式:在 app.ini 中将 RUN_MODE = prod 改为 RUN_MODE = dev。 然后在任意模板中添加 {{ $ | DumpVar }},重启 Gitea 并刷新对应页面; 这样会输出所有可用变量。

找到所需数据后,使用对应变量即可;例如,如果您需要仓库名称,可以使用 {{.Repository.Name}}

如果您需要对这些数据做一些转换,而您又不熟悉 Go一种简单的变通办法是先将数据放入 DOM 再添加一小段 JavaScript 脚本来处理它。

示例PlantUML

您可以通过 PlantUML 服务器为 Gitea 的 Markdown 添加 PlantUML 支持。 数据会被编码后发送到 PlantUML 服务器,再由服务器生成图片。官方在 http://www.plantuml.com/plantuml 提供了一个在线演示服务器,但如果您(或您的用户)拥有敏感数据, 则可以改为自建一个 PlantUML 服务器。要启用 PlantUML 渲染, 请从 https://gitea.com/davidsvantesson/plantuml-code-highlight 复制 JavaScript 文件, 并将其放入 $GITEA_CUSTOM/public/assets/ 目录。然后将以下内容添加到 custom/footer.tmpl

<script>
  $(async () => {
    if (!$('.language-plantuml').length) return;
    await Promise.all([
      $.getScript('https://your-gitea-server.com/assets/deflate.js'),
      $.getScript('https://your-gitea-server.com/assets/encode.js'),
      $.getScript('https://your-gitea-server.com/assets/plantuml_codeblock_parse.js'),
    ]);
    // Replace call with address to your plantuml server
    parsePlantumlCodeBlocks("https://www.plantuml.com/plantuml");
  });
</script>

随后,您就可以在 Markdown 中添加如下代码块:

Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: Another authentication Response

该脚本会检测 class="language-plantuml" 的标签,不过您也可以通过为 parsePlantumlCodeBlocks 提供第二个参数来修改这一行为。

示例:使用 Online 3D Viewer 预览 CAD 文件

您可以在自己的 Gitea 实例中实现 CAD 文件预览。这个实现使用的是 Online 3D Viewer

支持以下 3D 文件格式: 3dm, 3ds, 3mf, amf, bim, brep, dae, fbx, fcstd, glb, gltf, ifc, igs, iges, stp, step, stl, obj, off, ply, wrl .gltf 文件仅支持 v2

第 1 部分:添加模板

我们需要在 $GITEA_CUSTOM 中添加模板。 该模板需要保存到 $GITEA_CUSTOM/templates/custom/ 中。 在这里创建 footer.tmpl 文件,并向其中添加以下内容:

nano $GITEA_CUSTOM/templates/custom/footer.tmpl
<script>
    function onPageChange() {
      // Supported 3D file types
      const fileTypes = ['3dm', '3ds', '3mf', 'amf', 'bim', 'brep', 'dae', 'fbx', 'fcstd', 'glb', 'gltf', 'ifc', 'igs', 'iges', 'stp', 'step', 'stl', 'obj', 'off', 'ply', 'wrl'];
  
      // Select matching link
      const links = Array.from(document.querySelectorAll('a.ui.mini.basic.button'));
      const link3D = links.find(link => {
        const href = link.href.toLowerCase();
        return href.includes('/raw/') && fileTypes.some(ext => href.endsWith(`.${ext}`));
      });
  
	if (link3D) {
	  const existingScript = document.querySelector('script[src="/assets/o3dv/o3dv.min.js"]');

	  const initializeViewer = () => {
		const fileUrl = link3D.getAttribute('href');

                const fileView = document.querySelector('.file-view');

		if (!fileView) return;

		// Remove only the old viewer container if it exists
		const oldView3D = document.getElementById('view-3d');
		if (oldView3D) {
		  oldView3D.remove();  // safely remove old viewer container div
		} else {
		  // No #view-3d, so remove all children inside .file-view
		  while (fileView.firstChild) {
		    fileView.removeChild(fileView.firstChild);
		  }
		}

		// Create a new container for the viewer
		const newView3D = document.createElement('div');
		  newView3D.id = 'view-3d';
		  newView3D.style.padding = '0';
		  newView3D.style.margin = '0';
		  newView3D.style.flexGrow = '1';
		  newView3D.style.minHeight = '0';
		  newView3D.style.width = '100%';
		
		const header = document.querySelector('header');
		const headerHeight = header ? header.offsetHeight : 0;

		newView3D.style.height = `calc(100vh - ${headerHeight}px)`;		

		// Append the new container inside fileView
		fileView.appendChild(newView3D);

		const parentDiv = document.getElementById('view-3d');
		if (parentDiv) {
		  const viewer = new OV.EmbeddedViewer(parentDiv, {
			backgroundColor: new OV.RGBAColor(59, 68, 76, 0),
			defaultColor: new OV.RGBColor(200, 200, 200),
			edgeSettings: new OV.EdgeSettings(false, new OV.RGBColor(0, 0, 0), 1),
			environmentSettings: new OV.EnvironmentSettings([
			  '/assets/o3dv/envmaps/fishermans_bastion/negx.jpg',
			  '/assets/o3dv/envmaps/fishermans_bastion/posx.jpg',
			  '/assets/o3dv/envmaps/fishermans_bastion/posy.jpg',
			  '/assets/o3dv/envmaps/fishermans_bastion/negy.jpg',
			  '/assets/o3dv/envmaps/fishermans_bastion/posz.jpg',
			  '/assets/o3dv/envmaps/fishermans_bastion/negz.jpg'
			], false)
		  });

		  viewer.LoadModelFromUrlList([fileUrl]);
		}
	  };

	  if (typeof OV === 'undefined') {
		if (!existingScript) {
		  const script = document.createElement('script');
		  script.onload = initializeViewer;
		  script.src = '/assets/o3dv/o3dv.min.js';
		  document.head.appendChild(script);
		} else {
		  // Script is loading but OV not yet ready — wait for it
		  existingScript.addEventListener('load', initializeViewer);
		}
	  } else {
		// OV already loaded
		initializeViewer();
	  }
	}
    };

    // Run when the page is fully loaded
    document.addEventListener('DOMContentLoaded', onPageChange); 

    const targetSelector = 'a.ui.mini.basic.button[href*="/raw/"]';
    let lastHref = null;
    let timeoutId = null;

    const checkAndRun = () => {
      const rawLink = document.querySelector(targetSelector);
      if (!rawLink) return;

      const currentHref = rawLink.getAttribute('href');
      if (currentHref !== lastHref) {
        lastHref = currentHref;

        const fileName = currentHref.split('/').pop();
        console.log('New Raw file link detected after delay:', fileName);
        
        onPageChange();
      }
    };

    const observer = new MutationObserver(() => {
      // Delay execution by 300ms after last mutation
      clearTimeout(timeoutId);
      timeoutId = setTimeout(checkAndRun, 300);
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true,
    });
</script>

第 2 部分:添加公共文件

现在我们需要下载最新版本的 O3DV。进入 $GITEA_CUSTOM/public/assets/。 使用以下命令创建目录(并进入该目录):

mkdir o3dv
cd o3dv

GitHub 复制最新发行版压缩包链接 (当前示例版本为 v0.18.0)。 然后使用例如 wget 或 curl 下载该文件:

wget https://github.com/kovacsv/Online3DViewer/releases/download/0.18.0/o3dv.zip

或者

curl -L -O https://github.com/kovacsv/Online3DViewer/releases/download/0.18.0/o3dv.zip

再使用例如 unzip 解压归档文件:

unzip o3dv.zip

第 3 部分:目录权限

最后一步,修改 public 目录权限:

chown -R git:git $GITEA_CUSTOM/public

现在一切就绪!重启您的 Gitea 实例以应用这些更改,并在浏览器中进行测试。

简单检查一下。最终目录结构应类似如下:

$GITEA_CUSTOM/templates
-- custom
    `-- footer.tmpl

$GITEA_CUSTOM/public/assets/
-- o3dv
   |-- o3dv.zip
   |-- o3dv.license.md
   |-- o3dv.min.js
   |-- envmaps
    \...

自定义 Gitea 邮件

$GITEA_CUSTOM/templates/mail 目录允许您修改 Gitea 每一种邮件的正文。 可被覆盖的模板可以在 Gitea 源码的 templates/mail 目录中找到。 覆盖方式是将对应文件复制到 $GITEA_CUSTOM/templates/mail 下, 并保持与源码一致的完整路径结构。

任何包含在 {{}} 中的语句都是 Gitea 的模板语法, 如果您没有完全理解这些组件,就不应修改它们。

为 Gitea 添加统计分析

Google Analytics、Matomo原 Piwik以及其他分析服务都可以集成到 Gitea。 要添加跟踪代码,请参考本文的“页面中的其他插入内容”一节, 并将相应 JavaScript 添加到 $GITEA_CUSTOM/templates/custom/header.tmpl 文件中。

自定义 gitignores、labels、licenses、locales 和 readmes

将自定义文件放入 custom/options 下对应的子目录中。

:::note 这些文件不应带有扩展名,例如应使用 Labels,而不是 Labels.txt :::

gitignores

要添加自定义 .gitignore,请在 $GITEA_CUSTOM/options/gitignore 中添加一个文件, 文件内容遵循现有的 .gitignore 规则

自定义 git 配置

从 Gitea 1.20 开始,您可以通过 git.config 区块自定义 git 配置。

启用签名 git push

签名推送 允许客户端对 push 操作本身进行加密签名(而不仅仅是对单个提交签名)。 要启用签名推送,请将以下内容添加到 app.ini

[git.config]
receive.certNonceSeed = <randomstring>

certNonceSeed 应设置为一个随机字符串并妥善保密。它用于生成防重放 nonce。 Gitea 默认已经设置了 receive.advertisePushOptions = true,因此无需额外配置。 请注意Gitea 不会读取 /etc/gitconfig,因此必须像上面这样通过 app.ini 设置该选项。

在客户端侧,可以通过 git push --signed 进行签名推送, 或者使用 git config --global push.gpgSign if-asked 永久启用。

Labels

从 Gitea 1.19 开始,您可以向 $GITEA_CUSTOM/options/label 中添加一个遵循 YAML 标签格式 的文件:

labels:
  - name: "foo/bar"  # 下拉列表中显示的标签名称
    exclusive: true # 是否为作用域标签使用互斥命名空间,作用域分隔符为 /
    color: aabbcc # 十六进制颜色值
    description: Some label # 标签用途的详细描述

旧的传统文件格式 仍可使用,格式如下,但我们强烈建议改用新的 YAML 格式。

#hex-color label name ; label description

更多信息请参阅标签文档

Licenses

要添加自定义许可证,请将包含许可证文本的文件添加到 $GITEA_CUSTOM/options/license

Locales

本地化语言由我们的 Crowdin 管理。 您可以通过将修改后的语言文件放到 $GITEA_CUSTOM/options/locale 中来覆盖某个语言环境。 Gitea 默认的语言文件可以在源码目录 options/locale 中找到, 这些文件可以作为您修改时的参考示例。

如果要添加一个全新的语言环境,除了将文件放到上述位置外, 您还需要在 app.ini[i18n] 部分中添加新的语言代码和名称。 请记住Gitea 会将这些设置视为覆盖项,因此如果您还想保留其他语言, 就需要复制默认值并在其中加入您自己的语言项。

[i18n]
LANGS = en-US,foo-BAR
NAMES = English,FooBar

如果用户浏览器的语言与列表中的任何语言都不匹配,则第一种语言会被用作默认语言。

不同版本之间的语言文件可能会变化,因此强烈建议持续跟踪您自定义过的语言文件。

Readmes

要添加自定义 Readme请将一个 Markdown 格式的文件(不带 .md 扩展名) 放到 $GITEA_CUSTOM/options/readme 中。

:::note Readme 模板支持变量展开。 当前可用变量包括 {Name}(仓库名称)、{Description}{CloneURL.SSH}{CloneURL.HTTPS}{OwnerName} :::

Reactions

要修改反应表情,您可以在 app.ini 中设置允许使用的 reactions。

[ui]
REACTIONS = +1, -1, laugh, confused, heart, hooray, eyes

完整的受支持 emoji 列表见 emoji list

自定义 Gitea 外观

内置主题有 gitea-lightgitea-darkgitea-auto (会自动适应操作系统设置)。

默认主题可以通过 app.iniui 部分的 DEFAULT_THEME 进行修改。

Gitea 还支持用户主题,这意味着每位用户都可以选择要使用的主题。 用户可选主题列表可以通过 app.iniui 部分的 THEMES 值进行配置。

要让所有用户都能使用自定义主题:

  1. 将 CSS 文件添加到 $GITEA_CUSTOM/public/assets/css/theme-<theme-name>.css。 您可以通过执行 gitea help 并查看其中的 “CustomPath” 值来确认实例的 $GITEA_CUSTOM
  2. <theme-name> 添加到 app.iniTHEMES 设置的逗号分隔列表中, 或者将 THEMES 留空以允许所有主题。

名为 theme-my-theme.css 的自定义主题文件会在用户主题选择页面中显示为 my-theme。 您还可以在自定义主题 CSS 文件中加入主题元信息,以提供更多说明。 如果自定义主题是暗色主题,请在 :root 块中设置全局 CSS 变量 --is-dark-theme: true。 这样 Gitea 就可以相应地调整 Monaco 代码编辑器的主题。 如果要实现 “auto” 主题,可以参考 theme-gitea-auto.css

gitea-theme-meta-info {
  --theme-display-name: "My Awesome Theme"; /* this theme will be display as "My Awesome Theme" on the UI */
}
:root {
  --is-dark-theme: true; /* if it is a dark theme */
  --color-primary: #112233;
  /* more custom theme variables ... */
}

社区主题列在 gitea/awesome-gitea#themes

默认主题源码可在这里找到。

自定义字体

可以使用 CSS 变量自定义字体:

:root {
  --fonts-proportional: /* custom proportional fonts */ !important;
  --fonts-monospace: /* custom monospace fonts */ !important;
  --fonts-emoji: /* custom emoji fonts */ !important;
}