mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-21 21:05:34 +03:00
faa28b5a44
Move `public/*` to `public/assets/*` Some old PRs (like #15219) introduced inconsistent directory system. For example: why the local directory "public" is accessed by `http://site/assets`? How to serve the ".well-known" files properly in the public directory? For convention rules, the "public" directory is widely used for the website's root directory. It shouldn't be an exception for Gitea. So, this PR makes the things consistent: * `http://site/assets/foo` means `{CustomPath}/public/assets/foo`. * `{CustomPath}/public/.well-known` and `{CustomPath}/public/robots.txt` can be used in the future. This PR is also a prerequisite for a clear solution for: * #21942 * #25892 * discourse.gitea.io: [.well-known path serving custom files behind proxy?](https://discourse.gitea.io/t/well-known-path-serving-custom-files-behind-proxy/5445/1) This PR is breaking for users who have custom "public" files (CSS/JS). After getting approvals, I will update the documents. ---- ## ⚠️ BREAKING ⚠️ If you have files in your "custom/public/" folder, please move them to "custom/public/assets/". --------- Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Giteabot <teabot@gitea.io>
82 lines
2.5 KiB
JavaScript
Executable file
82 lines
2.5 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
import imageminZopfli from 'imagemin-zopfli';
|
|
import {optimize} from 'svgo';
|
|
import {fabric} from 'fabric';
|
|
import {readFile, writeFile} from 'node:fs/promises';
|
|
|
|
function exit(err) {
|
|
if (err) console.error(err);
|
|
process.exit(err ? 1 : 0);
|
|
}
|
|
|
|
function loadSvg(svg) {
|
|
return new Promise((resolve) => {
|
|
fabric.loadSVGFromString(svg, (objects, options) => {
|
|
resolve({objects, options});
|
|
});
|
|
});
|
|
}
|
|
|
|
async function generate(svg, path, {size, bg}) {
|
|
const outputFile = new URL(path, import.meta.url);
|
|
|
|
if (String(outputFile).endsWith('.svg')) {
|
|
const {data} = optimize(svg, {
|
|
plugins: [
|
|
'preset-default',
|
|
'removeDimensions',
|
|
{
|
|
name: 'addAttributesToSVGElement',
|
|
params: {attributes: [{width: size}, {height: size}]}
|
|
},
|
|
],
|
|
});
|
|
await writeFile(outputFile, data);
|
|
return;
|
|
}
|
|
|
|
const {objects, options} = await loadSvg(svg);
|
|
const canvas = new fabric.Canvas();
|
|
canvas.setDimensions({width: size, height: size});
|
|
const ctx = canvas.getContext('2d');
|
|
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
|
|
|
|
if (bg) {
|
|
canvas.add(new fabric.Rect({
|
|
left: 0,
|
|
top: 0,
|
|
height: size * (1 / (size / options.height)),
|
|
width: size * (1 / (size / options.width)),
|
|
fill: 'white',
|
|
}));
|
|
}
|
|
|
|
canvas.add(fabric.util.groupSVGElements(objects, options));
|
|
canvas.renderAll();
|
|
|
|
let png = Buffer.from([]);
|
|
for await (const chunk of canvas.createPNGStream()) {
|
|
png = Buffer.concat([png, chunk]);
|
|
}
|
|
|
|
png = await imageminZopfli({more: true})(png);
|
|
await writeFile(outputFile, png);
|
|
}
|
|
|
|
async function main() {
|
|
const gitea = process.argv.slice(2).includes('gitea');
|
|
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
|
|
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
|
|
|
|
await Promise.all([
|
|
generate(logoSvg, '../public/assets/img/logo.svg', {size: 32}),
|
|
generate(logoSvg, '../public/assets/img/logo.png', {size: 512}),
|
|
generate(faviconSvg, '../public/assets/img/favicon.svg', {size: 32}),
|
|
generate(faviconSvg, '../public/assets/img/favicon.png', {size: 180}),
|
|
generate(logoSvg, '../public/assets/img/avatar_default.png', {size: 200}),
|
|
generate(logoSvg, '../public/assets/img/apple-touch-icon.png', {size: 180, bg: true}),
|
|
gitea && generate(logoSvg, '../public/assets/img/gitea.svg', {size: 32}),
|
|
]);
|
|
}
|
|
|
|
main().then(exit).catch(exit);
|