Skip to content

Commit

Permalink
Generate JSON badges without using a template [GithubSearch] (#3395)
Browse files Browse the repository at this point in the history
Warm up for #2428.
  • Loading branch information
paulmelnikow authored Apr 30, 2019
1 parent 7980a65 commit ae2499b
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 122 deletions.
19 changes: 4 additions & 15 deletions __snapshots__/make-badge.spec.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions core/base-service/legacy-request-handler.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ describe('The request handler', function() {
label: 'testing',
message: '123',
color: 'lightgrey',
link: [],
})
})
})
Expand All @@ -130,6 +131,7 @@ describe('The request handler', function() {
label: 'testing',
message: '123',
color: 'lightgrey',
link: [],
})
})
})
Expand Down Expand Up @@ -158,6 +160,7 @@ describe('The request handler', function() {
label: 'testing',
message: '123',
color: 'lightgrey',
link: [],
})
})

Expand All @@ -174,6 +177,7 @@ describe('The request handler', function() {
label: 'testing',
message: 'Maximum response size exceeded',
color: 'lightgrey',
link: [],
})
})

Expand Down
130 changes: 67 additions & 63 deletions gh-badges/lib/make-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,56 @@ templateFiles.forEach(async filename => {
const extension = path.extname(filename).slice(1)
const style = filename.slice(0, -`-template.${extension}`.length)
// Compile the template. Necessary to always have a working template.
templates[`${style}-${extension}`] = dot.template(templateData)
if (extension === 'svg') {
// Substitute dot code.
const mapping = new Map()
let mappingIndex = 1
const untemplatedSvg = templateData.replace(/{{.*?}}/g, match => {
// Weird substitution that currently works for all templates.
const mapKey = `99999990${mappingIndex}.1`
mappingIndex++
mapping.set(mapKey, match)
return mapKey
})

const svgo = new SVGO()
const { data, error } = await svgo.optimize(untemplatedSvg)

if (error !== undefined) {
console.error(
`Template ${filename}: ${error}\n` +
' Generated untemplated SVG:\n' +
`---\n${untemplatedSvg}---\n`
)
return
}
templates[style] = dot.template(templateData)
// Substitute dot code.
const mapping = new Map()
let mappingIndex = 1
const untemplatedSvg = templateData.replace(/{{.*?}}/g, match => {
// Weird substitution that currently works for all templates.
const mapKey = `99999990${mappingIndex}.1`
mappingIndex++
mapping.set(mapKey, match)
return mapKey
})

const svgo = new SVGO()
const { data, error } = await svgo.optimize(untemplatedSvg)

if (error !== undefined) {
console.error(
`Template ${filename}: ${error}\n` +
' Generated untemplated SVG:\n' +
`---\n${untemplatedSvg}---\n`
)
return
}

// Substitute dot code back.
let svg = data
const unmappedKeys = []
mapping.forEach((value, key) => {
let keySubstituted = false
svg = svg.replace(RegExp(key, 'g'), () => {
keySubstituted = true
return value
})
if (!keySubstituted) {
unmappedKeys.push(key)
}
// Substitute dot code back.
let svg = data
const unmappedKeys = []
mapping.forEach((value, key) => {
let keySubstituted = false
svg = svg.replace(RegExp(key, 'g'), () => {
keySubstituted = true
return value
})
if (unmappedKeys.length > 0) {
console.error(
`Template ${filename} has unmapped keys ` +
`${unmappedKeys.join(', ')}.\n` +
' Generated untemplated SVG:\n' +
`---\n${untemplatedSvg}\n---\n` +
' Generated template:\n' +
`---\n${svg}\n---\n`
)
return
if (!keySubstituted) {
unmappedKeys.push(key)
}

templates[`${style}-${extension}`] = dot.template(svg)
})
if (unmappedKeys.length > 0) {
console.error(
`Template ${filename} has unmapped keys ` +
`${unmappedKeys.join(', ')}.\n` +
' Generated untemplated SVG:\n' +
`---\n${untemplatedSvg}\n---\n` +
' Generated template:\n' +
`---\n${svg}\n---\n`
)
return
}

templates[style] = dot.template(svg)
})

function escapeXml(s) {
Expand All @@ -92,7 +90,7 @@ function capitalize(s) {
return s.charAt(0).toUpperCase() + s.slice(1)
}

function makeBadge({
module.exports = function makeBadge({
format,
template,
text,
Expand All @@ -109,12 +107,27 @@ function makeBadge({
// String coercion and whitespace removal.
text = text.map(value => `${value}`.trim())

if (format !== 'json') {
format = 'svg'
const [left, right] = text

color = normalizeColor(color || colorB || colorscheme)
labelColor = normalizeColor(labelColor || colorA)

// This ought to be the responsibility of the server, not `makeBadge`.
if (format === 'json') {
return JSON.stringify({
label: left,
message: right,
logoWidth,
color,
labelColor,
link: links,
name: left,
value: right,
})
}

if (!(`${template}-${format}` in templates)) {
template = format === 'svg' ? 'flat' : 'default'
if (!(template in templates)) {
template = 'flat'
}
if (template.startsWith('popout')) {
if (logo) {
Expand All @@ -131,7 +144,6 @@ function makeBadge({
text = text.map(value => value.toUpperCase())
}

const [left, right] = text
let leftWidth = (anafanafo(left) / 10) | 0
// Increase chances of pixel grid alignment.
if (leftWidth % 2 === 0) {
Expand All @@ -152,9 +164,6 @@ function makeBadge({
logoPadding = logo ? 3 : 0
}

color = color || colorB || colorscheme
labelColor = labelColor || colorA

const context = {
text: [left, right],
escapedText: text.map(escapeXml),
Expand All @@ -164,18 +173,13 @@ function makeBadge({
logoPosition,
logoWidth,
logoPadding,
// `color` and `labelColor` are included for the `default` JSON template.
color: normalizeColor(color),
labelColor: normalizeColor(labelColor),
colorA: toSvgColor(labelColor),
colorB: toSvgColor(color),
escapeXml,
}

const templateFn = templates[`${template}-${format}`]
const templateFn = templates[template]

// The call to template() can raise an exception.
return templateFn(context)
}

module.exports = makeBadge
33 changes: 8 additions & 25 deletions gh-badges/lib/make-badge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const { test, given, forCases } = require('sazerac')
const { expect } = require('chai')
const snapshot = require('snap-shot-it')
const eol = require('eol')
const isSvg = require('is-svg')
const makeBadge = require('./make-badge')

Expand Down Expand Up @@ -63,7 +62,7 @@ describe('The badge generator', function() {
given('almostred'),
given('brightmaroon'),
given('cactus')
).expect(null)
).expect(undefined)
})
})

Expand Down Expand Up @@ -93,34 +92,18 @@ describe('The badge generator', function() {
})

describe('JSON', function() {
it('should always produce the same JSON (unless we have changed something!)', function() {
it('should produce the expected JSON', function() {
const json = makeBadge({
text: ['cactus', 'grown'],
format: 'json',
links: ['https://example.com/', 'https://other.example.com/'],
})
const jsonWithLFEndings = eol.lf(json)
snapshot(jsonWithLFEndings)
})

it('should replace unknown json template with "default"', function() {
const jsonBadgeWithUnknownStyle = makeBadge({
text: ['name', 'Bob'],
format: 'json',
template: 'unknown_style',
})
const jsonBadgeWithDefaultStyle = makeBadge({
text: ['name', 'Bob'],
format: 'json',
template: 'default',
})
expect(jsonBadgeWithUnknownStyle).to.equal(jsonBadgeWithDefaultStyle)
expect(JSON.parse(jsonBadgeWithUnknownStyle)).to.deep.equal({
name: 'name',
value: 'Bob',
label: 'name',
message: 'Bob',
color: null,
expect(JSON.parse(json)).to.deep.equal({
name: 'cactus',
label: 'cactus',
value: 'grown',
message: 'grown',
link: ['https://example.com/', 'https://other.example.com/'],
})
})

Expand Down
10 changes: 0 additions & 10 deletions gh-badges/templates/default-template.json

This file was deleted.

12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@
"danger-plugin-no-test-shortcuts": "^2.0.0",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"eol": "^0.9.1",
"escape-string-regexp": "^2.0.0",
"eslint": "^5.16.0",
"eslint-config-prettier": "^4.1.0",
Expand Down
2 changes: 1 addition & 1 deletion services/dependabot/dependabot.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ t.create('semver stability (valid)')
label: 'semver stability',
message: isIntegerPercentage,
link: [
'https://dependabot.com/compatibility-score.html?package-manager=bundler&dependency-name=puma&version-scheme=semver',
'https://dependabot.com/compatibility-score.html?package-manager=bundler&dependency-name=puma&version-scheme=semver',
],
})

Expand Down
2 changes: 1 addition & 1 deletion services/twitter/twitter.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ t.create('URL')
label: 'tweet',
message: '',
link: [
'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fshields.io',
'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fshields.io',
'https://twitter.com/search?q=https%3A%2F%2Fshields.io',
],
})

0 comments on commit ae2499b

Please sign in to comment.