Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct SVG rendering #12157

Merged
merged 1 commit into from
Jul 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ coverage.all
/public/serviceworker.js
/public/css
/public/fonts
/public/img/svg
/web_src/fomantic/build
/VERSION

Expand Down
23 changes: 20 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,13 @@ FOMANTIC_DEST_DIR := web_src/fomantic/build
WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) $(FOMANTIC_DEST)
WEBPACK_CONFIGS := webpack.config.js
WEBPACK_DEST := public/js/index.js public/css/index.css
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js public/img/svg
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js

BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))

SVG_DEST_DIR := public/img/svg

TAGS ?=
TAGS_SPLIT := $(subst $(COMMA), ,$(TAGS))
TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
Expand Down Expand Up @@ -158,6 +160,7 @@ help:
@echo " - lint-backend lint backend files"
@echo " - watch-frontend watch frontend files and continuously rebuild"
@echo " - webpack build webpack files"
@echo " - svg build svg files"
@echo " - fomantic build fomantic files"
@echo " - generate run \"go generate\""
@echo " - fmt format the Go code"
Expand Down Expand Up @@ -292,8 +295,8 @@ lint: lint-backend lint-frontend
lint-backend: golangci-lint revive vet swagger-check swagger-validate test-vendor

.PHONY: lint-frontend
lint-frontend: node_modules
npx eslint web_src/js webpack.config.js
lint-frontend: node_modules svg-check
npx eslint web_src/js build webpack.config.js
npx stylelint web_src/less

.PHONY: watch-frontend
Expand Down Expand Up @@ -605,6 +608,20 @@ $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_
npx webpack --hide-modules --display-entrypoints=false
@touch $(WEBPACK_DEST)

.PHONY: svg
svg: node-check | node_modules
rm -rf $(SVG_DEST_DIR)
node build/generate-svg.js

.PHONY: svg-check
svg-check: svg
@diff=$$(git diff $(SVG_DEST_DIR)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make svg' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi;

.PHONY: update-translations
update-translations:
mkdir -p ./translations
Expand Down
63 changes: 63 additions & 0 deletions build/generate-svg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env node
'use strict';

const fastGlob = require('fast-glob');
const Svgo = require('svgo');
const {resolve, parse} = require('path');
const {readFile, writeFile, mkdir} = require('fs').promises;

const glob = (pattern) => fastGlob.sync(pattern, {cwd: resolve(__dirname), absolute: true});
const outputDir = resolve(__dirname, '../public/img/svg');

function exit(err) {
if (err) console.error(err);
process.exit(err ? 1 : 0);
}

async function processFile(file, {prefix = ''} = {}) {
const name = `${prefix}${parse(file).name}`;

const svgo = new Svgo({
plugins: [
{removeXMLNS: true},
{removeDimensions: true},
{
addClassesToSVGElement: {
classNames: [
'svg',
name,
],
},
},
{
addAttributesToSVGElement: {
attributes: [
{'width': '16'},
{'height': '16'},
{'aria-hidden': 'true'},
],
},
},
],
});

const {data} = await svgo.optimize(await readFile(file, 'utf8'));
await writeFile(resolve(outputDir, `${name}.svg`), data);
}

async function main() {
try {
await mkdir(outputDir);
} catch {}

for (const file of glob('../node_modules/@primer/octicons/build/svg/*.svg')) {
await processFile(file, {prefix: 'octicon-'});
}

for (const file of glob('../web_src/svg/*.svg')) {
await processFile(file);
}
}

main().then(exit).catch(exit);

4 changes: 4 additions & 0 deletions docs/content/doc/advanced/hacking-on-gitea.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ make lint-frontend

Note: When working on frontend code, set `USE_SERVICE_WORKER` to `false` in `app.ini` to prevent undesirable caching of frontend assets.

### Building and adding SVGs

SVG icons are built using the `make svg` target which compiles the icon sources defined in `build/generate-svg.js` into the output directory `public/img/svg`. Custom icons can be added in the `web_src/svg` directory.

### Building Images

To build the images, ImageMagick, `inkscape` and `zopflipng` binaries must be available in
Expand Down
32 changes: 32 additions & 0 deletions modules/svg/discover_bindata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build bindata

package svg

import (
"path"
"path/filepath"

"code.gitea.io/gitea/modules/public"
)

// Discover returns a map of discovered SVG icons in bindata
func Discover() map[string]string {
svgs := make(map[string]string)

for _, file := range public.AssetNames() {
matched, _ := filepath.Match("img/svg/*.svg", file)
if matched {
content, err := public.Asset(file)
if err == nil {
filename := path.Base(file)
svgs[filename[:len(filename)-4]] = string(content)
}
}
}

return svgs
}
31 changes: 31 additions & 0 deletions modules/svg/discover_nobindata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build !bindata

package svg

import (
"io/ioutil"
"path"
"path/filepath"

"code.gitea.io/gitea/modules/setting"
)

// Discover returns a map of discovered SVG icons in the file system
func Discover() map[string]string {
svgs := make(map[string]string)

files, _ := filepath.Glob(path.Join(setting.StaticRootPath, "public", "img", "svg", "*.svg"))
for _, file := range files {
content, err := ioutil.ReadFile(file)
if err == nil {
filename := path.Base(file)
svgs[filename[:len(filename)-4]] = string(content)
}
}

return svgs
}
13 changes: 13 additions & 0 deletions modules/svg/svg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package svg

// SVGs contains discovered SVGs
var SVGs map[string]string

// Init discovers SVGs and populates the `SVGs` variable
func Init() {
SVGs = Discover()
}
13 changes: 12 additions & 1 deletion modules/templates/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/gitdiff"
Expand Down Expand Up @@ -439,9 +440,19 @@ func NewTextFuncMap() []texttmpl.FuncMap {
}}
}

var widthRe = regexp.MustCompile(`width="[0-9]+?"`)
var heightRe = regexp.MustCompile(`height="[0-9]+?"`)

// SVG render icons
func SVG(icon string, size int) template.HTML {
return template.HTML(fmt.Sprintf(`<svg class="svg %s" width="%d" height="%d" aria-hidden="true"><use xlink:href="#%s" /></svg>`, icon, size, size, icon))
if svgStr, ok := svg.SVGs[icon]; ok {
if size != 16 {
svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size))
svgStr = heightRe.ReplaceAllString(svgStr, fmt.Sprintf(`height="%d"`, size))
}
return template.HTML(svgStr)
}
return template.HTML("")
}

// Safe render raw as HTML
Expand Down
Loading