Skip to content

Commit a2f37e2

Browse files
authored
Merge pull request #1316 from github/decaf
migrate from coffeescript to plain javascript
2 parents 8975b74 + 396aac3 commit a2f37e2

File tree

3 files changed

+204
-157
lines changed

3 files changed

+204
-157
lines changed

_config.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ defaults:
2020
layout: license
2121

2222
exclude:
23-
- app.coffee
2423
- CNAME
2524
- CONTRIBUTING.md
2625
- Gemfile
@@ -40,7 +39,6 @@ plugins:
4039
- jekyll-sitemap
4140
- jekyll-redirect-from
4241
- jekyll-seo-tag
43-
- jekyll-coffeescript
4442
- jekyll-github-metadata # For 'Improve this page' links
4543

4644
sass:

assets/js/app.coffee

Lines changed: 0 additions & 155 deletions
This file was deleted.

assets/js/app.js

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
class Choosealicense {
2+
constructor() {
3+
this.tooltipAttributesMapperByRuleType = {
4+
permissions: {
5+
heading: 'Permission',
6+
color: 'tooltip--permissions'
7+
},
8+
conditions: {
9+
heading: 'Condition',
10+
color: 'tooltip--conditions'
11+
},
12+
limitations: {
13+
heading: 'Limitation',
14+
color: 'tooltip--limitations'
15+
}
16+
};
17+
18+
this.initTooltips();
19+
this.initClipboard();
20+
this.initLicenseSuggestion();
21+
}
22+
23+
// Selects the content of a given element
24+
selectText(element) {
25+
if (document.body.createTextRange) {
26+
const range = document.body.createTextRange();
27+
range.moveToElementText(element);
28+
range.select();
29+
} else if (window.getSelection) {
30+
const selection = window.getSelection();
31+
const range = document.createRange();
32+
33+
range.selectNodeContents(element);
34+
selection.removeAllRanges();
35+
selection.addRange(range);
36+
}
37+
}
38+
39+
// Init tooltip action
40+
initTooltips() {
41+
const annotations = window.annotations || {};
42+
43+
Object.entries(annotations).forEach(([ruletype, rules]) => {
44+
rules.forEach((rule) => {
45+
const licenseLiElement = $(`.license-${ruletype} .${rule.tag}`).not(
46+
`dd.license-${ruletype} .${rule.tag}`
47+
);
48+
const tooltipAttr = this.tooltipAttributesMapperByRuleType[ruletype];
49+
if (!tooltipAttr) return;
50+
51+
licenseLiElement.attr(
52+
'aria-label',
53+
`${rule.label} ${tooltipAttr.heading.toLowerCase()}: ${rule.description}`
54+
);
55+
licenseLiElement.addClass(
56+
`hint--bottom
57+
hint--large
58+
hint--no-animate
59+
${tooltipAttr.color}
60+
override-hint-inline`
61+
);
62+
});
63+
});
64+
}
65+
66+
// Initializes Clipboard.js
67+
initClipboard() {
68+
const clipboardPrompt = $('.js-clipboard-button').text();
69+
$('.js-clipboard-button').data('clipboard-prompt', clipboardPrompt);
70+
71+
const clip = new Clipboard('.js-clipboard-button');
72+
clip.on('mouseout', this.clipboardMouseout);
73+
clip.on('complete', this.clipboardComplete);
74+
}
75+
76+
// Callback to restore the clipboard button's original text
77+
clipboardMouseout(client, args) {
78+
this.textContent = $(this).data('clipboard-prompt');
79+
}
80+
81+
// Post-copy user feedback callback
82+
clipboardComplete(client, args) {
83+
this.textContent = 'Copied!';
84+
}
85+
86+
// Initializes the repository suggestion feature
87+
initLicenseSuggestion() {
88+
const inputEl = $('#repository-url');
89+
const licenseId = inputEl.attr('data-license-id');
90+
const statusIndicator = $('.status-indicator');
91+
new LicenseSuggestion(inputEl, licenseId, statusIndicator);
92+
}
93+
}
94+
95+
class LicenseSuggestion {
96+
constructor(inputEl, licenseId, statusIndicator) {
97+
this.inputEl = inputEl;
98+
this.licenseId = licenseId;
99+
this.statusIndicator = statusIndicator;
100+
this.inputWrapper = $('.input-wrapper');
101+
this.tooltipErrorClasses = 'hint--bottom tooltip--error hint--always';
102+
103+
this.bindEventHandlers();
104+
}
105+
106+
// Main event handlers for user input
107+
bindEventHandlers() {
108+
this.inputEl
109+
.on('input', () => {
110+
this.setStatus('');
111+
})
112+
.on('keyup', (event) => {
113+
if (event.keyCode === 13 && event.target.value) {
114+
let repositoryFullName;
115+
try {
116+
repositoryFullName = this.parseUserInput(event.target.value);
117+
} catch (error) {
118+
this.setStatus('Error', 'Invalid URL.');
119+
return;
120+
}
121+
122+
this.setStatus('Fetching');
123+
this.fetchInfoFromGithubAPI(
124+
repositoryFullName,
125+
(err, repositoryInfo = null) => {
126+
if (err) {
127+
this.setStatus('Error', err.message);
128+
return;
129+
}
130+
if (repositoryInfo.license) {
131+
const license = repositoryInfo.license;
132+
this.setStatus('Error', this.repositoryLicense(repositoryFullName, license));
133+
} else {
134+
const licenseUrl = encodeURIComponent(
135+
`https://github.com/${repositoryFullName}/community/license/new?template=${this.licenseId}`
136+
);
137+
window.location.href = `https://github.com/login?return_to=${licenseUrl}`;
138+
this.setStatus('');
139+
this.inputEl.val('');
140+
}
141+
}
142+
);
143+
}
144+
});
145+
}
146+
147+
// Try to extract the repository full name from the user input
148+
parseUserInput(userInput) {
149+
const repository = /https?:\/\/github\.com\/([^\/]+)\/([^\/?#]+)/.exec(userInput);
150+
if (!repository) throw new Error('Invalid URL.');
151+
152+
const [, username, project] = repository;
153+
return `${username}/${project.replace(/(\.git)$/, '')}`;
154+
}
155+
156+
// Displays an indicator and tooltips to the user about the current status
157+
setStatus(status = '', message = '') {
158+
const statusClass = status.toLowerCase();
159+
const displayTooltip = (s, m) => {
160+
this.inputWrapper.attr('aria-label', `${s}: ${m}`);
161+
this.inputWrapper.addClass(this.tooltipErrorClasses);
162+
};
163+
164+
switch (status) {
165+
case 'Fetching':
166+
this.statusIndicator.removeClass(`error ${this.tooltipErrorClasses}`).addClass(statusClass);
167+
break;
168+
case 'Error':
169+
this.statusIndicator.removeClass('fetching').addClass(statusClass);
170+
displayTooltip(status, message);
171+
break;
172+
default:
173+
this.statusIndicator.removeClass('fetching error');
174+
this.inputWrapper.removeClass(this.tooltipErrorClasses);
175+
break;
176+
}
177+
}
178+
179+
// Fetches information about a repository from the Github API
180+
fetchInfoFromGithubAPI(repositoryFullName, callback) {
181+
$.getJSON(`https://api.github.com/repos/${repositoryFullName}`, (info) => {
182+
callback(null, info);
183+
}).fail((e) => {
184+
if (e.status === 404) {
185+
callback(new Error(`Repository ${repositoryFullName} not found.`));
186+
} else {
187+
callback(new Error(`Network error when trying to get information about ${repositoryFullName}.`));
188+
}
189+
});
190+
}
191+
192+
// Generates a message showing that a repository is already licensed
193+
repositoryLicense(repositoryFullName, license) {
194+
const foundLicense = window.licenses.find((lic) => lic.spdx_id === license.spdx_id);
195+
if (foundLicense) {
196+
return `The repository ${repositoryFullName} is already licensed under the ${foundLicense.title}.`;
197+
}
198+
return `The repository ${repositoryFullName} is already licensed.`;
199+
}
200+
}
201+
202+
$(() => {
203+
new Choosealicense();
204+
});

0 commit comments

Comments
 (0)