Browse Source

switch to parcel

canonical-url
Jeremy Danyow 4 years ago
parent
commit
b53500630d
  1. 17
      .editorconfig
  2. 7
      .gitignore
  3. 5
      .vscode/settings.json
  4. 4
      README.md
  5. 4583
      package-lock.json
  6. 61
      package.json
  7. 2
      src/_buttons.scss
  8. 147
      src/configuration-component.ts
  9. 55
      src/debug.html
  10. 17
      src/github.ts
  11. 0
      src/icons/android-chrome-192x192.png
  12. 0
      src/icons/android-chrome-256x256.png
  13. 0
      src/icons/apple-touch-icon-120x120.png
  14. 0
      src/icons/apple-touch-icon-152x152.png
  15. 0
      src/icons/apple-touch-icon-180x180.png
  16. 0
      src/icons/apple-touch-icon-60x60.png
  17. 0
      src/icons/apple-touch-icon-76x76.png
  18. 0
      src/icons/apple-touch-icon.png
  19. 0
      src/icons/browserconfig.xml
  20. 0
      src/icons/favicon-16x16.png
  21. 0
      src/icons/favicon-32x32.png
  22. 0
      src/icons/favicon.ico
  23. 0
      src/icons/manifest.json
  24. 0
      src/icons/mstile-150x150.png
  25. 0
      src/icons/safari-pinned-tab.svg
  26. 0
      src/icons/utterances-300.png
  27. 16
      src/index.html
  28. 34
      src/index.scss
  29. 5
      src/oauth.ts
  30. 23
      src/repo-config.ts
  31. 2
      src/utterances-api.ts
  32. 4
      src/utterances.html
  33. 5
      src/utterances.scss
  34. 22
      src/utterances.ts
  35. 7
      tsconfig.json
  36. 5
      tslint.json
  37. 3
      utterances.json
  38. 4241
      yarn.lock

17
.editorconfig

@ -1,21 +1,6 @@ @@ -1,21 +1,6 @@
root = true
[{.editorconfig,.gitignore,package.json,tsconfig.json,README.md}]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
[.vscode/**]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
[src/**]
end_of_line = lf
[*]
insert_final_newline = true
indent_style = space
indent_size = 2

7
.gitignore vendored

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
node_modules
debug
dist
output
.cache
chrome
dist
node_modules

5
.vscode/settings.json vendored

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"html.format.enable": false,
"json.format.enable": false
"json.format.enable": false,
"editor.detectIndentation": false,
"editor.tabSize": 2
}

4
README.md

@ -12,7 +12,9 @@ A lightweight comments widget built on GitHub issues. @@ -12,7 +12,9 @@ A lightweight comments widget built on GitHub issues.
When Utterances loads, the GitHub [issue search API](https://developer.github.com/v3/search/#search-issues) is used to find the issue associated with the page based on `url`, `pathname` or `title`. The issue's comments are displayed in the familiar GitHub style.
When a matching issue is not found, [utterances-bot](https://github.com/utterances-bot) will automatically create one the first time someone comments.
*What if we can find an issue that matches the page?*
No problem- [utterances-bot](https://github.com/utterances-bot) will automatically create one the first time someone comments.
To comment, users must authorize the utterances app to post on their behalf using the GitHub [OAuth flow](https://developer.github.com/v3/oauth/#web-application-flow). Alternatively, users can comment on the GitHub issue directly.

4583
package-lock.json generated

File diff suppressed because it is too large Load Diff

61
package.json

@ -3,47 +3,32 @@ @@ -3,47 +3,32 @@
"version": "0.1.4",
"license": "MIT",
"scripts": {
"lint": "tslint --project tsconfig.json",
"clean": "rm -rf output && rm -rf debug && rm -rf dist && mkdir debug && mkdir dist",
"rollup-client": "rollup output/client.js --output.format iife --output.file debug/client.js",
"rollup-utterances": "rollup output/utterances.js --output.format iife --output.file debug/utterances.js",
"rollup-index": "rollup output/index.js --output.format iife --output.file debug/index.js",
"rollup": "yarn run rollup-client && yarn run rollup-utterances && yarn run rollup-index",
"html": "cp src/*.html debug/ && cp src/authorized.html dist/",
"sass": "node-sass src --output debug --include-path node_modules",
"optimize-client": "uglifyjs --compress --mangle --output dist/client.js -- debug/client.js",
"optimize-utterances": "inliner --skip-absolute-urls debug/utterances.html > dist/utterances.html",
"optimize-index": "inliner --skip-absolute-urls debug/index.html > dist/index.html",
"optimize": "yarn run optimize-client && yarn run optimize-utterances && yarn run optimize-index",
"watch-output": "chokidar \"output/**/*.js\" --command \"yarn run rollup\"",
"watch-html": "chokidar \"src/*.html\" --command \"yarn run html\"",
"watch-debug": "chokidar \"debug/*/**\" --command \"yarn run optimize\"",
"watch": "concurrently --kill-others \"tsc --watch\" \"yarn run sass -- --watch --recursive\" \"yarn run watch-output\" \"yarn run watch-html\" \"yarn run watch-debug\"",
"serve-debug": "browser-sync start --server debug --files=\"debug/**/*\" --port 9000 --no-open --no-ui --no-online --no-ghost-mode",
"serve-dist": "browser-sync start --server dist --files=\"dist/**/*\" --port 8000 --no-open --no-ui --no-online --no-ghost-mode",
"serve": "concurrently --kill-others \"yarn run serve-debug\" \"yarn run serve-dist\"",
"predevelop": "yarn run clean && yarn run html && tsc && yarn run rollup && yarn run sass && yarn run optimize",
"develop": "concurrently --kill-others \"yarn run watch\" \"yarn run serve\"",
"clean": "rm -rf dist",
"prestart": "yarn run clean",
"start": "parcel src/utterances.html --no-hmr --public-url / --port 4000 & parcel watch src/client.ts & parcel watch src/index.html & parcel watch src/authorized.html",
"prebuild": "yarn run clean",
"build": "yarn run html && tsc && yarn run rollup && yarn run sass && yarn run optimize",
"predeploy": "yarn run build && cp -R icons dist/ && cp .nojekyll dist/ && cp CNAME dist/ && cp utterances.json dist/",
"deploy": "gh-pages --dist dist",
"chrome": "google-chrome --disable-web-security --allow-running-insecure-content --user-data-dir=\"chrome\""
"build": "parcel build src/utterances.html && parcel build src/client.ts && parcel build src/index.html && parcel build src/authorized.html",
"predeploy": "yarn run build && cp .nojekyll dist/ && cp CNAME dist/",
"deploy": "echo \"gh-pages --dist dist\"",
"(postinstall is temporary: using unreased version of parcel)": "",
"postinstall": "cd node_modules/parcel-bundler && yarn install && yarn build && cd ../.."
},
"devDependencies": {
"browser-sync": "^2.18.13",
"chokidar-cli": "^1.2.0",
"concurrently": "^3.5.1",
"gh-pages": "^1.1.0",
"inliner": "^1.13.1",
"node-sass": "^4.7.2",
"primer-base": "^1.6.1",
"primer-buttons": "^2.5.1",
"primer-forms": "^2.0.1",
"primer-markdown": "^3.7.3",
"rollup": "^0.52.1",
"tslint": "^5.8.0",
"typescript": "^2.6.2",
"uglify-js": "^3.2.1"
"node-sass": "^4.8.3",
"parcel-bundler": "parcel-bundler/parcel#master",
"primer-alerts": "^1.5.5",
"primer-base": "^1.7.0",
"primer-buttons": "^2.5.3",
"primer-forms": "^2.1.0",
"primer-markdown": "^3.7.5",
"tslint": "^5.9.1",
"typescript": "^2.7.2"
},
"sass": {
"includePaths": [
"node_modules"
]
}
}

2
src/_buttons.scss

@ -1,5 +1,3 @@ @@ -1,5 +1,3 @@
@import "primer-base/index";
.btn {
position: relative;
display: inline-block;

147
src/configuration-component.ts

@ -1,37 +1,30 @@ @@ -1,37 +1,30 @@
import repoRegex from './repo-regex';
export class ConfigurationComponent {
public element: HTMLFormElement;
private script: HTMLDivElement;
private utterancesJson: HTMLDivElement;
private createJsonButton: HTMLButtonElement;
private repo: HTMLInputElement;
private branch: HTMLInputElement;
private blog: HTMLInputElement;
private repoIsValid: boolean;
private branchIsValid: boolean;
constructor() {
this.element = document.createElement('form');
this.element.innerHTML = `
<h3>Repository & Branch</h3>
<p>Enter the GitHub repository and branch Utterances will connect to.</p>
<h3>Repository</h3>
<p>
Choose the repository utterances will connect to.
</p>
<ol>
<li>Make sure the repo is public, otherwise your readers will not be able to view the issues/comments.</li>
<li>Make sure the <a href="https://github.com/apps/utterances">utterances app</a>
is installed on the repo, otherwise users will not be able to post comments.
</li>
</ol>
<fieldset>
<div>
<label for="repo">Repo:</label><br/>
<label for="repo">repo:</label><br/>
<input id="repo" class="form-control" type="text" placeholder="owner/repo">
<p class="note">
A <strong>public</strong> GitHub repository. This is where the blog
post issues and issue-comments will be posted.
</p>
</div>
<div>
<label for="branch">Branch:</label><br/>
<input id="branch" class="form-control" type="text" placeholder="master" value="master">
<p class="note">
The branch where the utterances.json file will be stored.
</p>
</div>
</fieldset>
<h3>Blog Post<->Issue Mapping</h3>
@ -85,36 +78,16 @@ export class ConfigurationComponent { @@ -85,36 +78,16 @@ export class ConfigurationComponent {
<input type="radio" value="specific-term" name="mapping">
Issue title contains specific term
<p class="note">
You configure Utterances to search for an issue whose title contains a specific term.
You configure Utterances to search for an issue whose title contains a specific term of your choosing.
If a matching issue is not found, Utterances will automatically create one the first
time someone comments on your post.
time someone comments on your post. The issue's title will be the term you chose.
</p>
</label>
</div>
</fieldset>
<h3>Blog</h3>
<p>Choose the blog(s) that will be permitted to post issues and issue comments to
your GitHub repository via Utterances.</p>
<fieldset>
<div>
<label for="blog">Blog URL:</label><br/>
<input id="blog" class="form-control" type="text" placeholder="https://interesting.net/blog/">
<p class="note">
The base url of the blog that will post issues and comments to
the repo. Separate multiple urls with a comma.
</p>
</div>
</fieldset>
<h3>Enable Utterances</h3>
<p>Add the utterances.json file to your GitHub repo</p>
<div class="config-field" id="utterances-json" class="highlight highlight-text-html-basic"></div>
<button id="create-utterances-json" type="button" class="btn btn-blue code-action" disabled>Create...</button>
<br/>
<br/>
<p>Add the following script tag to your blog's template. Position it where you want the
comments to appear. Customize the layout using the <code>.utterances</code> and
<code>.utterances-frame</code> selectors.
@ -128,21 +101,8 @@ export class ConfigurationComponent { @@ -128,21 +101,8 @@ export class ConfigurationComponent {
this.element.action = 'javascript:';
this.script = this.element.querySelector('#script') as HTMLDivElement;
this.utterancesJson = this.element.querySelector('#utterances-json') as HTMLDivElement;
this.repo = this.element.querySelector('#repo') as HTMLInputElement;
this.repoValidation();
this.branch = this.element.querySelector('#branch') as HTMLInputElement;
this.branchValidation();
this.blog = this.element.querySelector('#blog') as HTMLInputElement;
this.createJsonButton = this.element.querySelector('#create-utterances-json') as HTMLButtonElement;
this.createJsonButton.addEventListener('click', () => {
const encodedJson = encodeURIComponent(this.utterancesJson.textContent as string);
// tslint:disable-next-line:max-line-length
const url = `https://github.com/${this.repo.value}/new/${encodeURIComponent(this.branch.value)}?filename=utterances.json&value=${encodedJson}`;
window.open(url, '_blank');
});
const copyButton = this.element.querySelector('#copy-button') as HTMLButtonElement;
copyButton.addEventListener(
@ -159,20 +119,15 @@ export class ConfigurationComponent { @@ -159,20 +119,15 @@ export class ConfigurationComponent {
let mappingAttr: string;
// tslint:disable-next-line:prefer-conditional-expression
if (mapping.value === 'issue-number') {
mappingAttr = this.makeConfigScriptAttribute('issue-number', '123');
mappingAttr = this.makeConfigScriptAttribute('issue-number', '[ENTER ISSUE NUMBER HERE]');
} else if (mapping.value === 'specific-term') {
mappingAttr = this.makeConfigScriptAttribute('issue-term', '????');
mappingAttr = this.makeConfigScriptAttribute('issue-term', '[ENTER TERM HERE]');
} else {
mappingAttr = this.makeConfigScriptAttribute('issue-term', mapping.value);
}
this.script.innerHTML = this.makeConfigScript(
this.makeConfigScriptAttribute('repo', this.repo.value) + '\n' +
this.makeConfigScriptAttribute('branch', this.branch.value) + '\n' +
this.makeConfigScriptAttribute('repo', this.repo.value === '' ? '[ENTER REPO HERE]' : this.repo.value) + '\n' +
mappingAttr);
const origins = this.stringToOriginsArray(this.blog.value);
this.utterancesJson.innerHTML = this.makeUtterancesJson(origins);
}
private makeConfigScriptAttribute(name: string, value: string) {
@ -185,76 +140,6 @@ export class ConfigurationComponent { @@ -185,76 +140,6 @@ export class ConfigurationComponent {
return `<pre><span class="pl-s1">&lt;<span class="pl-ent">script</span> <span class="pl-e">src</span>=<span class="pl-s"><span class="pl-pds">"</span>https://utteranc.es/client.js<span class="pl-pds">"</span></span></span>\n${attrs}\n<span class="pl-s1"> <span class="pl-e">async</span>&gt;</span>\n<span class="pl-s1">&lt;/<span class="pl-ent">script</span>&gt;</span></pre>`;
}
private makeUtterancesJson(origins: string[]) {
// tslint:disable-next-line:max-line-length
const makeOriginHtml = (origin: string) => `<span class="pl-s"><span class="pl-pds">"</span>${origin}<span class="pl-pds">"</span></span>`;
const originsHtml = origins.map(makeOriginHtml).join(', ');
// tslint:disable-next-line:max-line-length
return `<pre>{\n <span class="pl-s"><span class="pl-pds">"</span>origins<span class="pl-pds">"</span></span>: [${originsHtml}]\n}</pre>`;
}
private stringToOriginsArray(value: string) {
const a = document.createElement('a');
return value.split(',')
.map(x => x.trim())
.filter(x => x.length)
.map(x => {
a.href = x;
return a.protocol + '//' + a.host;
});
}
private repoValidation() {
const control = this.repo.parentElement as HTMLDivElement;
this.repo.addEventListener('input', () => {
this.createJsonButton.disabled = true;
control.classList.remove('has-error', 'has-success');
});
this.repo.addEventListener('blur', () => {
if (!repoRegex.test(this.repo.value)) {
control.classList.add('has-error');
return;
}
fetch('https://api.github.com/repos/' + this.repo.value, { method: 'HEAD' })
.then(response => {
if (response.ok) {
this.repoIsValid = true;
this.createJsonButton.disabled = !this.branchIsValid;
control.classList.add('has-success');
} else if (response.status === 404) {
control.classList.add('has-error');
}
});
});
}
private branchValidation() {
const control = this.branch.parentElement as HTMLDivElement;
this.branch.addEventListener('input', () => {
this.createJsonButton.disabled = true;
control.classList.remove('has-error', 'has-success');
});
this.branch.addEventListener('blur', () => {
if (!this.repoIsValid) {
return;
}
if (!/^[\w\n-]+$/.test(this.branch.value)) {
control.classList.add('has-error');
return;
}
fetch(`https://api.github.com/repos/${this.repo.value}/branches/${this.branch.value}`, { method: 'HEAD' })
.then(response => {
if (response.ok) {
this.branchIsValid = true;
this.createJsonButton.disabled = !this.repoIsValid;
control.classList.add('has-success');
} else if (response.status === 404) {
control.classList.add('has-error');
}
});
});
}
private copyTextToClipboard(text: string) {
const textArea = document.createElement('textarea');
// tslint:disable-next-line:max-line-length

55
src/debug.html

@ -1,55 +0,0 @@ @@ -1,55 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>utterances</title>
<meta name="description" content="A lightweight commenting system using GitHub issues.">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css">
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
<link rel="manifest" href="icons/manifest.json">
<link rel="mask-icon" href="icons/safari-pinned-tab.svg" color="#4c2889">
<link rel="shortcut icon" href="icons/favicon.ico">
<meta name="apple-mobile-web-app-title" content="Utterances">
<meta name="application-name" content="Utterances">
<meta name="msapplication-config" content="icons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<script>
if (!window.Promise || !window.fetch) {
document.write(
'<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.0/bluebird.min.js" integrity="sha256-/l7dZnd9iW5Iw9P2Qn/0ghByeFDKnIcPd4DTptDaK20=" crossorigin="anonymous"><\/script>',
'<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js" integrity="sha256-aB35laj7IZhLTx58xw/Gm1EKOoJJKZt6RY+bH1ReHxs=" crossorigin="anonymous"><\/script>',
'<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"><\/script>'
);
}
</script>
</head>
<body>
<section class="timeline">
<article class="timeline-comment">
<a class="avatar" href="https://github.com/utterance">
<img alt="@utterances" height="44" width="44"
src="https://avatars3.githubusercontent.com/u/27908738?v=3&s=88">
</a>
<div class="comment">
<header class="comment-header">
<a class="text-link" href="https://github.com/utterance">
<strong>utterances</strong>
</a>
</header>
</div>
</article>
</section>
<script src="index.js"></script>
<script src="client.js"
repo="jdanyow/utterances-demo"
branch="master"
issue-term="pathname"
async>
</script>
</body>
</html>

17
src/github.ts

@ -24,7 +24,7 @@ function githubRequest(relativeUrl: string, init?: RequestInit) { @@ -24,7 +24,7 @@ function githubRequest(relativeUrl: string, init?: RequestInit) {
init.cache = 'no-cache'; // force conditional request
const request = new Request(GITHUB_API + relativeUrl, init);
request.headers.set('Accept', GITHUB_ENCODING__REACTIONS_PREVIEW);
if (token.value !== null) {
if (!/^search\//.test(relativeUrl) && token.value !== null) {
request.headers.set('Authorization', `token ${token.value}`);
}
return request;
@ -77,12 +77,25 @@ function readRelNext(response: Response) { @@ -77,12 +77,25 @@ function readRelNext(response: Response) {
return +match[1];
}
function githubFetch(request: Request) {
function githubFetch(request: Request): Promise<Response> {
return fetch(request).then(response => {
if (response.status === 401) {
token.value = null;
}
if (response.status === 403) {
response.json().then(data => {
if (data.message === 'Resource not accessible by integration') {
window.dispatchEvent(new CustomEvent('not-installed'));
}
});
}
processRateLimit(response);
if (request.method === 'GET' && [401, 403].indexOf(response.status) !== -1) {
request.headers.delete('Authorization');
return githubFetch(request);
}
return response;
});
}

0
icons/android-chrome-192x192.png → src/icons/android-chrome-192x192.png

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

0
icons/android-chrome-256x256.png → src/icons/android-chrome-256x256.png

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

0
icons/apple-touch-icon-120x120.png → src/icons/apple-touch-icon-120x120.png

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

0
icons/apple-touch-icon-152x152.png → src/icons/apple-touch-icon-152x152.png

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

0
icons/apple-touch-icon-180x180.png → src/icons/apple-touch-icon-180x180.png

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

0
icons/apple-touch-icon-60x60.png → src/icons/apple-touch-icon-60x60.png

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

0
icons/apple-touch-icon-76x76.png → src/icons/apple-touch-icon-76x76.png

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

0
icons/apple-touch-icon.png → src/icons/apple-touch-icon.png

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

0
icons/browserconfig.xml → src/icons/browserconfig.xml

0
icons/favicon-16x16.png → src/icons/favicon-16x16.png

Before

Width:  |  Height:  |  Size: 616 B

After

Width:  |  Height:  |  Size: 616 B

0
icons/favicon-32x32.png → src/icons/favicon-32x32.png

Before

Width:  |  Height:  |  Size: 923 B

After

Width:  |  Height:  |  Size: 923 B

0
icons/favicon.ico → src/icons/favicon.ico

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

0
icons/manifest.json → src/icons/manifest.json

0
icons/mstile-150x150.png → src/icons/mstile-150x150.png

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

0
icons/safari-pinned-tab.svg → src/icons/safari-pinned-tab.svg

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 722 B

0
icons/utterances-300.png → src/icons/utterances-300.png

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

16
src/index.html

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<meta name="description" content="A lightweight commenting system using GitHub issues.">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="index.scss">
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
@ -21,7 +21,8 @@ @@ -21,7 +21,8 @@
document.write(
'<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.0/bluebird.min.js" integrity="sha256-/l7dZnd9iW5Iw9P2Qn/0ghByeFDKnIcPd4DTptDaK20=" crossorigin="anonymous"><\/script>',
'<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js" integrity="sha256-aB35laj7IZhLTx58xw/Gm1EKOoJJKZt6RY+bH1ReHxs=" crossorigin="anonymous"><\/script>',
'<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"><\/script>'
'<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"><\/script>',
'<script src="https://cdn.jsdelivr.net/npm/custom-event-polyfill@0.3.0/custom-event-polyfill.min.js"><\/script>'
);
}
</script>
@ -43,13 +44,20 @@ @@ -43,13 +44,20 @@
</article>
</section>
<script src="index.js"></script>
<script src="index.ts"></script>
<script src="https://utteranc.es/client.js"
<!-- <script src="https://utteranc.es/client.js"
repo="utterance/utterances"
branch="gh-pages"
issue-term="homepage"
async>
</script> -->
<script src="http://localhost:4000/client.js"
repo="jdanyow/utterances-demo"
branch="master"
issue-term="pathname"
async>
</script>
<script>

34
src/index.scss

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
// @import "primer-base/index";
@import "primer-forms/index";
@import "primer-base/index";
@import "primer-forms/lib/form-control.scss";
@import "primer-forms/lib/form-group.scss";
@import "primer-forms/lib/input-group.scss";
@import "primer-markdown/index";
@import "pygments-vs";
@import "util";
@ -35,34 +37,6 @@ @@ -35,34 +37,6 @@
margin-top: -$spacer-2;
margin-bottom: $spacer-3;
}
.has-error {
label {
color: $text-red;
}
input {
border-color: $border-red;
}
.note {
color: $text-red;
}
}
.has-success {
label {
color: $text-green;
}
input {
border-color: $border-green;
}
.note {
color: $text-green;
}
}
}
}

5
src/oauth.ts

@ -5,10 +5,9 @@ const authorizeUrl = `${UTTERANCES_API}/authorize`; @@ -5,10 +5,9 @@ const authorizeUrl = `${UTTERANCES_API}/authorize`;
const tokenUrl = `${UTTERANCES_API}/token`;
// tslint:disable-next-line:variable-name
const redirect_uri = `${location.origin}/authorized.html`;
const scope = 'public_repo';
class Token {
private readonly storageKey = 'OAUTH_TOKEN';
private readonly storageKey = 'OAUTH_TOKEN2';
private token: string | null = null;
constructor() {
@ -37,7 +36,7 @@ class Token { @@ -37,7 +36,7 @@ class Token {
export const token = new Token();
export function login() {
window.open(`${authorizeUrl}?${param({ scope, redirect_uri })}`);
window.open(`${authorizeUrl}?${param({ redirect_uri })}`);
return new Promise(resolve => (window as any).notifyAuthorized = resolve)
.then(() => fetch(tokenUrl, { mode: 'cors', credentials: 'include' }))
.then(response => {

23
src/repo-config.ts

@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
import { loadJsonFile } from './github';
type Partial<T> = {
[P in keyof T]?: T[P];
};
export interface RepoConfig {
readonly origins: string[];
}
type RawRepoConfig = Partial<RepoConfig>;
function normalizeConfig(filename: string, rawConfig: RawRepoConfig): RepoConfig {
if (!Array.isArray(rawConfig.origins)) {
throw new Error(`${filename}: origins must be an array`);
}
return rawConfig as RepoConfig;
}
export function loadRepoConfig(path: string) {
return loadJsonFile<RawRepoConfig>(path)
.then<RepoConfig>(config => normalizeConfig(path, config));
}

2
src/utterances-api.ts

@ -1,2 +1,2 @@ @@ -1,2 +1,2 @@
// export const UTTERANCES_API = 'http://localhost:5000';
export const UTTERANCES_API = 'https://utterances-oauth.azurewebsites.net';
export const UTTERANCES_API = 'https://utterances-oauth2.azurewebsites.net';

4
src/utterances.html

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<meta name="description" content="A lightweight commenting system using GitHub issues.">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="utterances.css">
<link rel="stylesheet" href="utterances.scss">
<script>
if (!window.Promise || !window.fetch) {
document.write(
@ -17,6 +17,6 @@ @@ -17,6 +17,6 @@
</script>
</head>
<body>
<script src="utterances.js"></script>
<script src="utterances.ts"></script>
</body>
</html>

5
src/utterances.scss

@ -5,8 +5,13 @@ body { @@ -5,8 +5,13 @@ body {
@import "primer-base/index";
@import "primer-markdown/index";
@import "primer-alerts/index";
@import "pygments-vs";
@import "util";
@import "buttons";
@import "timeline";
@import "timeline-comment";
.flash-not-installed {
margin-bottom: $spacer-3;
}

22
src/utterances.ts

@ -15,7 +15,6 @@ import { login } from './oauth'; @@ -15,7 +15,6 @@ import { login } from './oauth';
import { TimelineComponent } from './timeline-component';
import { NewCommentComponent } from './new-comment-component';
import { setHostOrigin, publishResize } from './bus';
import { RepoConfig, loadRepoConfig } from './repo-config';
setRepoContext(page);
@ -26,13 +25,10 @@ function loadIssue(): Promise<Issue | null> { @@ -26,13 +25,10 @@ function loadIssue(): Promise<Issue | null> {
return loadIssueByTerm(page.issueTerm as string);
}
Promise.all([loadRepoConfig(page.configPath), loadIssue(), loadUser()])
.then(([repoConfig, issue, user]) => bootstrap(repoConfig, issue, user));
Promise.all([loadIssue(), loadUser()])
.then(([issue, user]) => bootstrap(issue, user));
function bootstrap(config: RepoConfig, issue: Issue | null, user: User | null) {
if (config.origins.indexOf(page.origin) === -1) {
throw new Error(`The origins specified in ${page.configPath} do not include ${page.origin}`);
}
function bootstrap(issue: Issue | null, user: User | null) {
setHostOrigin(page.origin);
const timeline = new TimelineComponent(user, issue);
@ -80,3 +76,15 @@ function bootstrap(config: RepoConfig, issue: Issue | null, user: User | null) { @@ -80,3 +76,15 @@ function bootstrap(config: RepoConfig, issue: Issue | null, user: User | null) {
timeline.element.appendChild(newCommentComponent.element);
publishResize();
}
addEventListener('not-installed', function handleNotInstalled() {
removeEventListener('not-installed', handleNotInstalled);
document.querySelector('.timeline')!.insertAdjacentHTML('afterbegin', `
<div class="flash flash-error flash-not-installed">
Error: utterances is not installed on <code>${page.owner}/${page.repo}</code>.
If you are the owner of this repo,
<a href="https://github.com/apps/utterances" target="_blank"><strong>install the app</strong></a>.
Read more about this change in
<a href="https://github.com/utterance/utterances/issues#3" target="_blank">the PR</a>.
</div>`);
});

7
tsconfig.json

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"module": "commonjs",
"lib": [
"dom",
"es2017"
],
"strictNullChecks": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"forceConsistentCasingInFileNames": true,
"removeComments": true,
"outDir": "output"
"removeComments": true
}
}

5
tslint.json

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
"array-type": ["array-simple"],
"arrow-parens": false,
"max-classes-per-file": [false],
"prefer-for-of": false
"prefer-for-of": false,
"no-implicit-dependencies": false
}
}
}

3
utterances.json

@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
{
"origins": ["https://utteranc.es", "http://localhost:9000", "http://localhost:8000"]
}

4241
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save