Add extra copyright, links in the copyright owner and year range

This commit is contained in:
Richie Bendall 2019-05-31 23:44:35 +12:00
parent 549dbb9627
commit cd4dcaaf34
No known key found for this signature in database
GPG key ID: 1C6A99DFA9D306FC
19 changed files with 169 additions and 93 deletions

View file

@ -10,4 +10,7 @@ before_install: npm i -g yarn
install: yarn install
script: yarn test
script:
- yarn test
- yarn lint
- yarn build

View file

@ -40,7 +40,6 @@ Available fields:
- email
- format
- gravatar
- version
- theme
### copyright
@ -59,13 +58,29 @@ You can also use an array to hold multiple copyright holders:
```json
{
"copyright": ["Remy Sharp (http://remysharp.com)", "Richie Bendall (https://richienb.github.io)"]
"copyright": ["Remy Sharp", "Richie Bendall"]
}
```
Which will be formatted as:
Remy Sharp (http://remysharp.com) and Richie Bendall (https://richienb.github.io)
Remy Sharp and Richie Bendall
If you additionally want to include a URL and email with each copyright holder, use objects in the array:
```json
{
"copyright": [{
"name": "Remy Sharp, https://remysharp.com",
"url": "https://remysharp.com",
"email": "remy@remysharp.com"
}, {
"name": "Richie Bendall, https://www.richie-bendall.ml",
"url": "https://www.richie-bendall.ml",
"email": "richiebendall@gmail.com"
}]
}
```
### url
@ -117,28 +132,6 @@ And if you want to show your gravatar, just add the `gravatar` boolean property:
Note that the gravatar requires the email property. You also need to check the compatibility of the chosen theme. Currently, only the default theme supports Gravatar.
### License version targeting
License version targeting allows you to link your MIT license to a specific revision in this project - therefore fixing it permanently to a specific license text.
Though I don't expect the license text to change ever, this is just some extra assurance for you.
Targeting requires the [sha from the license commit](https://github.com/remy/mit-license/commits/master/LICENSE.html). This can be specified on the URL (in your permalink) or in the JSON file.
For example: <http://rem.mit-license.org/a526bf7ad1> (make sure to view-source) shows an older version of the LICENSE.html file (compared to the [latest version](http://rem.mit-license.org) - the older version didn't have the new themes).
This can also be targeted in my JSON file:
```json
{
"copyright": "Remy Sharp, http://remysharp.com",
"url": "http://remysharp.com",
"version": "a526rbf7"
}
```
Note that if no version is supplied, the latest copy of the LICENSE.html will be displayed with your information included.
### Themes
If you've got an eye for design (or like me: not): you can contribute a theme by adding a CSS file to the `themes` directory. You can use the latest CSS technologies since they are automatically polyfilled. The default theme is simple and clean, but you can add your own as you like.
@ -198,13 +191,6 @@ The following types of requests can be made to this project:
the json file (currently none specified on `rem`)
- <http://rem.mit-license.org/license.html> HTML
- <http://rem.mit-license.org/license.txt> Text
- <http://rem.mit-license.org/a526bf7ad1> a526bf7ad1 version, HTML, or the
default format specified in the json file (again, none specified for
`rem` so defaults to HTML)
- <http://rem.mit-license.org/a526bf7ad1/license.html> a526bf7ad1 version,
HTML
- <http://rem.mit-license.org/a526bf7ad1/license.txt> a526bf7ad1 version,
text
The url also supports including a start year:
@ -212,7 +198,7 @@ The url also supports including a start year:
show a license year range of 2009-2016 (2016 being the current year)
- [http://rem.mit-license.org/2009-2010](http://rem.mit-license.org/2009-2010/)
allows me to force the year range
- <http://rem.mit-license.org/a526bf7ad1/2009-2010/license.txt> a526bf7ad1 version, with year range of 2009-2010 in plain text
- <http://rem.mit-license.org/2009-2010/license.txt> year range of 2009-2010 in plain text
Finally, the url also supports pinning the year

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>BSD Zero Clause License (0BSD)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.</p>

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>Academic Free License v3.0 (AFL-3.0)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>This Academic Free License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>GNU Affero General Public License (AGPL-3.0)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</p> <p> Preamble</p>
@ -634,7 +634,7 @@
the "copyright" line and a pointer to where the full notice is found.</p>
<p> &lt;one line to give the program's name and a brief idea of what it does.&gt;
Copyright © <%= info %></p>
Copyright © <%- info %></p>
<p> This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>The ISC License (ISC)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>The MIT License (MIT)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>NCSA Open Source License (NCSA)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>The SIL Open Font License (OFL)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:

View file

@ -7,7 +7,7 @@
<article>
<%- gravatar %>
<h1>The Universal Permissive License (UPL)</h1>
<p>Copyright © <%= info %></p>
<p>Copyright © <%- info %></p>
<p>Subject to the condition set forth below, permission is hereby granted to any
person obtaining a copy of this software, associated documentation and/or data

View file

@ -1,3 +1,3 @@
<footer>
<p><a href="https://github.com/remy/mit-license">Fork this project to create your own MIT license that you can always link to.</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/remy/mit-license">Fork this project to create your own MIT license that you can always link to.</a></p>
</footer>

View file

@ -1,7 +1,10 @@
<head>
<title>MIT License</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="description"
content="The MIT License is a permissive free software license originating at the Massachusetts Institute of Technology. As a permissive license, it puts only very limited restriction on reuse and has, therefore, an excellent license compatibility.">
<!--
Welcome fellow open source developer. This project is here for you to
link to if you're like me and keep forgetting to include the

View file

@ -2,21 +2,23 @@
"author": "Remy Sharp <remy@leftlogic.com> (http://remysharp.com/)",
"name": "mit-licence",
"description": "Hosted MIT License with details controlled through this repo",
"private": true,
"version": "1.0.0",
"repository": {
"type": "git",
"url": "git@github.com:remy/mit-license.git"
},
"scripts": {
"build": "tsc server.ts",
"start": "ts-node-dev --respawn --transpileOnly --no-notify server.ts",
"serve": "tsc server.ts && node server.js",
"serve": "yarn build && node server.js",
"test": "node test.js",
"lint": "eslint server.ts util.ts test.js --color --fix"
"lint": "eslint server.ts util.ts test.js --color"
},
"bugs": {
"url": "https://github.com/remy/mit-license/issues"
},
"license": "SEE LICENSE IN LICENSE",
"license": "MIT",
"dependencies": {
"@octokit/rest": "^16.27.3",
"btoa": "^1.2.1",
@ -25,6 +27,7 @@
"ejs": "^2.6.1",
"express": "^4.17.1",
"express-minify": "^1.0.0",
"git-pull": "^0.1.0",
"humanize-list": "^1.0.1",
"md5": "^2.2.1",
"node-html-parser": "^1.1.15",
@ -34,8 +37,10 @@
"typescript": "^3.4.5"
},
"devDependencies": {
"@types/btoa": "^1.2.3",
"@types/compression": "^0.0.36",
"@types/css": "^0.0.31",
"@types/ejs": "^2.6.3",
"@types/express": "^4.16.1",
"@types/express-minify": "^0.1.34",
"@types/md5": "^2.1.33",

2
robots.txt Normal file
View file

@ -0,0 +1,2 @@
User-agent: *
Disallow:

146
server.ts
View file

@ -1,18 +1,33 @@
import express = require('express')
/*
IMPORTANT: Set the `github_token` environment variable to a personal access token
with at least the `public_repo` scope for the API.
Server port: The `PORT` environment variable can also be set to control the port the server
should be hosted on.
*/
// Core
import * as path from 'path'
import * as fs from 'fs'
// Server
const PORT = process.env.PORT || 80
import express = require('express')
import compression = require('compression')
import minify = require('express-minify')
import postcssMiddleware = require('postcss-middleware')
// License viewing
import * as ejs from 'ejs'
import {yearNow, stripTags, trimArray} from './util'
import * as HTML from 'node-html-parser'
import md5 = require('md5');
import humanizeList from 'humanize-list'
import minify = require('express-minify')
import ejs = require('ejs')
import { yearNow, stripTags, trimArray } from './util'
import HTML = require('node-html-parser')
import postcssMiddleware = require('postcss-middleware')
import btoa = require('btoa')
const github = require("@octokit/rest")({
// License creation
import btoa = require('btoa')
import gitpull = require('git-pull')
const github = require('@octokit/rest')({
// GitHub personal access token
auth: process.env.github_token,
@ -29,10 +44,11 @@ app.use(minify({
app.set('view engine', 'ejs')
// Setup static files
app.use('/robots.txt', express.static('robots.txt'))
app.use('/users', express.static('users'))
app.use('/themes', postcssMiddleware({
plugins: [require('postcss-preset-env')({ browsers: '>= 0%', stage: 0 })],
src: req => path.join(__dirname, 'themes', req.path)
plugins: [require('postcss-preset-env')({browsers: '>= 0%', stage: 0})],
src: (req) => path.join(__dirname, 'themes', req.path),
}))
app.use('/themes', express.static('themes'))
app.use('/favicon.ico', express.static(__dirname + '/favicon.ico'))
@ -45,33 +61,36 @@ app.use((_req, res, next) => {
})
// Parse URL-encoded bodies (as sent by HTML forms)
// app.use(express.urlencoded({ extended: true }))
//
app.use(express.urlencoded({extended: true}))
// Parse JSON bodies (as sent by API clients)
app.use(express.json())
// HTTP POST API
app.post('/', (req, res) => {
// Get differnet parts of hostname (example: remy.mit-license.org -> ['remy', 'mit-license', 'org'])
const params = req.hostname.split(".")
console.log(req.body)
const params = req.hostname.split('.')
// If there isn't enough part of the hostname
if (params.length < 2) res.status(400).send("Please specify a subdomain in the URL.")
res.json(req.body)
return
if (params.length < 2) res.status(400).send('Please specify a subdomain in the URL.')
github.repos.createFile({
owner: "remy",
repo: "mit-license",
owner: 'remy',
repo: 'mit-license',
path: `users/${params[0]}.json`,
message: `Automated creation of user ${params[0]}.`,
content: btoa(),
content: btoa(''),
committer: {
name: "MIT License Bot",
email: "remy@leftlogic.com"
name: 'MIT License Bot',
email: 'remy@leftlogic.com',
},
})
gitpull(__dirname, (err: any, _consoleOutput: any) => {
if (err) {
res.status(502).end()
} else {
res.status(201).end()
}
})
})
@ -91,21 +110,66 @@ app.get('*', (req, res) => {
const user = JSON.parse(data || '{}')
// If error opening
if (err) {
if (err.code === 'ENOENT') {
// File not found
name = '<copyright holders>'
theme = 'default'
gravatar = ''
} else {
// Other error
if (err.code !== 'ENOENT') {
// Error is not "File not found"
res.status(500).end()
return
}
} else {
// No error
name = typeof user.copyright === 'string' ? user.copyright : humanizeList(user.copyright)
theme = user.theme || 'default'
gravatar = user.gravatar ? `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5(user.email.trim().toLowerCase())}" />` : ''
} else if (!user.locked && user.copyright) {
// No error and valid
name = (() => {
if (typeof user.copyright === 'string') {
// Supports regular format
let template: string
if (user.url) template = `<a href="${user.url}">${user.copyright}</a>`
else template = user.copyright
if (user.email) template += ` &lt;<a href="mailto:${user.email}">${user.email}</a>&gt;`
return template
} else if (user.copyright.every((val: any) => typeof val === 'string')) {
// Supports: ['Remy Sharp', 'Richie Bendall']
return humanizeList(user)
} else {
/*
Supports:
[{
"name": "Remy Sharp, https://remysharp.com",
"url": "https://remysharp.com",
"email": "remy@remysharp.com"
},{
"name": "Richie Bendall, https://www.richie-bendall.ml",
"url": "https://www.richie-bendall.ml",
"email": "richiebendall@gmail.com",
}]
*/
let template: string
return humanizeList(user.copyright.map((val) => {
if (val.url) template = `<a href="${val.url}">${val.name}</a>`
else template = val.copyright
if (val.email) template += ` &lt;<a href="mailto:${val.email}">${val.email}</a>&gt;`
return template
}))
}
})()
theme = user.theme
gravatar = (() => {
if (user.gravatar && user.email) {
// Supports regular format
return `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5(user.email.trim().toLowerCase())}" />`
}
else if (typeof user.copyright[0] === 'object' && user.gravatar) {
// Supports mutli-user format
return `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5(user.copyright[0].email.trim().toLowerCase())}" />`
}
else return ''
})()
}
const year = (() => {
@ -115,9 +179,15 @@ app.get('*', (req, res) => {
// rem.mit-license.org/2019
const fromYear = params.find((val) => !isNaN(parseInt(val.replace('-', ''))))
// rem.mit-license.org/2018-2019
const rangeYear = params.find((val) => val.split('-').length === 2)
// If current year
if (customYear) return customYear.replace(/[@-]/g, '')
// If range year
if (rangeYear) return rangeYear
// If from year
if (fromYear) {
// If from year is same as current
@ -135,8 +205,8 @@ app.get('*', (req, res) => {
const format = params.find((val) => val === 'license.html') ? 'html' : params.find((val) => val === 'license.txt') ? 'txt' : user.format || 'html'
const args = {
info: `${year} ${name}`,
theme,
info: `${year} ${name || '&lt;copyright holders&gt;'}`,
theme: theme || 'default',
gravatar,
}

5
users/example.json Normal file
View file

@ -0,0 +1,5 @@
{
"//1": "Security holding user",
"//2": "This user is being locked to allow for an example.",
"locked": true
}

View file

@ -1,8 +1,5 @@
{
"copyright": "Richie Bendall, https://www.richie-bendall.ml",
"url": "https://www.richie-bendall.ml",
"email": "richiebendall@gmail.com",
"format": "html",
"gravatar": true,
"theme": "material-indigo"
"//1": "Security holding user",
"//2": "This user is being locked to prevent complication with localhost.",
"locked": true
}

5
users/null.json Normal file
View file

@ -0,0 +1,5 @@
{
"//1": "Security holding user",
"//2": "This user is being locked to allow for no copyright information.",
"locked": true
}

BIN
yarn.lock

Binary file not shown.