Skip to content

Commit

Permalink
[ctan] refactor service (#2194)
Browse files Browse the repository at this point in the history
* refactor ctan service

* fix service title

* prettier

* add single license test

* move example code to service
  • Loading branch information
pnowaczyk authored and platan committed Oct 20, 2018
1 parent 2bba16c commit 6f589a7
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 73 deletions.
10 changes: 0 additions & 10 deletions lib/all-badge-examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -1004,11 +1004,6 @@ const allBadgeExamples = [
previewUrl: '/cran/l/devtools.svg',
keywords: ['R'],
},
{
title: 'CTAN',
previewUrl: '/ctan/l/novel.svg',
keywords: ['tex'],
},
{
title: 'DUB',
previewUrl: '/dub/l/vibe-d.svg',
Expand Down Expand Up @@ -1348,11 +1343,6 @@ const allBadgeExamples = [
previewUrl: '/cran/v/devtools.svg',
keywords: ['R'],
},
{
title: 'CTAN',
previewUrl: '/ctan/v/tex.svg',
keywords: ['tex'],
},
{
title: 'DUB',
previewUrl: '/dub/v/vibe-d.svg',
Expand Down
162 changes: 103 additions & 59 deletions services/ctan/ctan.service.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,109 @@
'use strict'

const LegacyService = require('../legacy-service')
const {
makeBadgeData: getBadgeData,
makeLabel: getLabel,
} = require('../../lib/badge-data')
const { addv: versionText } = require('../../lib/text-formatters')
const { version: versionColor } = require('../../lib/color-formatters')

module.exports = class Ctan extends LegacyService {
const Joi = require('joi')
const BaseJsonService = require('../base-json')
const { renderLicenseBadge } = require('../../lib/licenses')
const { renderVersionBadge } = require('../../lib/version')

const schema = Joi.object({
license: Joi.array()
.items(Joi.string())
.single(),
version: Joi.object({
number: Joi.string().required(),
}).required(),
}).required()

class BaseCtanService extends BaseJsonService {
async fetch({ library }) {
const url = `http://www.ctan.org/json/pkg/${library}`
return this._requestJson({
schema,
url,
})
}

static get defaultBadgeData() {
return { label: 'ctan' }
}
}

class CtanLicense extends BaseCtanService {
static get defaultBadgeData() {
return { label: 'license' }
}

static get category() {
return 'license'
}

async handle({ library }) {
const json = await this.fetch({ library })
// when present, API returns licenses inconsistently ordered, so fix the order
return renderLicenseBadge({ licenses: json.license && json.license.sort() })
}

static render({ licenses }) {
return renderLicenseBadge({ licenses })
}

static get url() {
return { base: 'ctan' }
return {
base: 'ctan/l',
format: '(.+)',
capture: ['library'],
}
}
static registerLegacyRouteHandler({ camp, cache }) {
camp.route(
/^\/ctan\/([vl])\/([^/]+)\.(svg|png|gif|jpg|json)$/,
cache((data, match, sendBadge, request) => {
const info = match[1] // either `v` or `l`
const pkg = match[2] // eg, tex
const format = match[3]
const url = 'http://www.ctan.org/json/pkg/' + pkg
const badgeData = getBadgeData('ctan', data)
request(url, (err, res, buffer) => {
if (err != null) {
badgeData.text[1] = 'inaccessible'
sendBadge(format, badgeData)
return
}
if (res.statusCode === 404) {
badgeData.text[1] = 'not found'
sendBadge(format, badgeData)
return
}
try {
const parsedData = JSON.parse(buffer)

if (info === 'v') {
const version = parsedData.version.number
badgeData.text[1] = versionText(version)
badgeData.colorscheme = versionColor(version)
sendBadge(format, badgeData)
} else if (info === 'l') {
badgeData.text[0] = getLabel('license', data)
const license = parsedData.license
if (Array.isArray(license) && license.length > 0) {
// API returns licenses inconsistently ordered, so fix the order.
badgeData.text[1] = license.sort().join(',')
badgeData.colorscheme = 'blue'
} else {
badgeData.text[1] = 'unknown'
}
sendBadge(format, badgeData)
} else {
throw Error('Unreachable due to regex')
}
} catch (e) {
badgeData.text[1] = 'invalid'
sendBadge(format, badgeData)
}
})
})
)

static get examples() {
return [
{
title: 'CTAN',
exampleUrl: 'novel',
urlPattern: ':library',
staticExample: this.render({ licenses: ['ppl1.3c', 'ofl'] }),
keywords: ['tex'],
},
]
}
}

class CtanVersion extends BaseCtanService {
static get category() {
return 'version'
}

async handle({ library }) {
const json = await this.fetch({ library })
return renderVersionBadge({ version: json.version.number })
}

static render({ version }) {
return renderVersionBadge({ version })
}

static get url() {
return {
base: 'ctan/v',
format: '(.+)',
capture: ['library'],
}
}

static get examples() {
return [
{
title: 'CTAN',
exampleUrl: 'tex',
urlPattern: ':library',
staticExample: this.render({ version: '3.14159265' }),
keywords: ['tex'],
},
]
}
}

module.exports = {
CtanLicense,
CtanVersion,
}
43 changes: 39 additions & 4 deletions services/ctan/ctan.tester.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
'use strict'

const Joi = require('joi')
const createServiceTester = require('../create-service-tester')
const ServiceTester = require('../service-tester')
const { colorScheme } = require('../test-helpers')
const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')

const t = createServiceTester()

const t = new ServiceTester({
id: 'ctan',
title: 'Comprehensive TEX Archive Network',
})
module.exports = t

t.create('license')
.get('/l/novel.json')
.expectJSON({
name: 'license',
value: 'lppl1.3c,ofl',
value: 'lppl1.3c, ofl',
})

t.create('license missing')
.get('/l/novel.json')
.intercept(nock =>
nock('http://www.ctan.org')
.get('/json/pkg/novel')
.reply(200, {
version: {
number: 'notRelevant',
},
})
)
.expectJSON({
name: 'license',
value: 'missing',
})

t.create('single license')
.get('/l/tex.json')
.intercept(nock =>
nock('http://www.ctan.org')
.get('/json/pkg/tex')
.reply(200, {
license: 'knuth',
version: {
number: 'notRelevant',
},
})
)
.expectJSON({
name: 'license',
value: 'knuth',
})

t.create('version')
Expand Down

0 comments on commit 6f589a7

Please sign in to comment.