Skip to content

Conversation

@donocode
Copy link
Contributor

@donocode donocode commented Nov 16, 2017

Replaces links with an embedded gist and also injects the stylesheet as a link. Only replaces links that are on their own line and in a comment body of a pr or issue.

Fixes #494

@sindresorhus sindresorhus changed the title Replace gist links with embedded gist Replace Gist links with embedded Gist Nov 17, 2017
import select from 'select-dom';

const gistRegex = /gist\.github\.com\/\w*?\/\w*/;
const isGist = link => gistRegex.test(link.href);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checks the current location. Do you mean to recreate the host or path check?

Copy link
Member

@sindresorhus sindresorhus Nov 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind. I misread the code.


const createGistElement = gistData => {
const el = document.createElement('div');
const style = `<link rel="stylesheet" href="https://assets-cdn.github.com/assets/gist-embed-3cc724162479db25e452fdf621f2349adef3e742b53552c2a93f82d28156cb96.css" />`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" />">

const createGistElement = gistData => {
const el = document.createElement('div');
const style = `<link rel="stylesheet" href="https://assets-cdn.github.com/assets/gist-embed-3cc724162479db25e452fdf621f2349adef3e742b53552c2a93f82d28156cb96.css" />`;
el.innerHTML = style + gistData.div;
Copy link
Member

@sindresorhus sindresorhus Nov 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do any sanitizing here? Probably better not to use .innerHTML too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data from the gist is sanitised already, are we planning in case a gist response is somehow compromised?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. I just asked in case anyone could think of a case. I guess it's fine then.

.all('.js-comment-body p a[href^="https://gist.github.com"]:only-child')
.filter(isGist);

gistLinks.forEach(async link => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a for-of loop

const gistEl = createGistElement(gistData);
const linkParent = link.parentNode;
linkParent.parentNode.replaceChild(gistEl, linkParent);
} catch (e) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eerr

const isGist = link => gistRegex.test(link.href);

const getJsonUrl = href => `${href}.json`.replace(/\.jso?n?\.json$/, '.json');
const getGistData = href => fetch(getJsonUrl(href)).then(response => response.json());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use async/await.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⬆️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More context: #814

const gistRegex = /gist\.github\.com\/\w*?\/\w*/;
const isGist = link => gistRegex.test(link.href);

const getJsonUrl = href => `${href}.json`.replace(/\.jso?n?\.json$/, '.json');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand what /\.jso?n?\.json$/ is doing. Like, why are we only replacing names that end with .js or .json? Can you show me an example URL? I think this would be clearer regardless /\.(js|json)\.json$/.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is for if the person links specifically the json or js version, so it won't create a link like https://gist.github.com/user/gist.js.json, it's probably unlikely for someone to be linking it but just in case

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense. I still would like to use /\.(js|json)\.json$/ as it's more readable.

Can you also add a short comment above it to explain what it's doing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think .js and .json links should be embedded, they are technically not the same content (web page vs embed code)

const getGistData = href => fetch(getJsonUrl(href)).then(response => response.json());

const createGistElement = gistData => {
const el = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to use a variable here. Just return it directly.

@sindresorhus
Copy link
Member

@sindresorhus
Copy link
Member

Why are we injecting the Gist instead of just loading the Gist embed in an iframe?

@donocode
Copy link
Contributor Author

donocode commented Dec 1, 2017

I'll get to this as soon as I can, I haven't forgotten about it!

@donocode
Copy link
Contributor Author

donocode commented Dec 6, 2017

I took a look at an iframe solution, my main worry is the height as is always the case with iframes, it's difficult to set the height of the iframe to be correct for the height of the content. I can deal with this if required but do you think we are gaining from this?

@donocode
Copy link
Contributor Author

donocode commented Dec 6, 2017

It seems the linter does not like await in for of loops although (as far as I'm aware) that is correct usage.

@@ -1,30 +1,29 @@
import { h } from 'dom-chef';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed? I think it’s required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch, my brain was still in iframe refactor mode when I deleted it

@fregante
Copy link
Member

fregante commented Dec 7, 2017

The linter complains because the loop stops at every await, which means that gists are loaded sequentially rather than in parallel. If you want to use await but load in parallel, extract the loop content into an async function and call it normally from inside the loop, don’t await the call.

@fregante
Copy link
Member

fregante commented Dec 7, 2017

@sindresorhus is there an iframe version? My understanding is that this is the preferred injection method. Their official embed code is a script tag with document.write

@fregante
Copy link
Member

fregante commented Dec 7, 2017

@sindresorhus this is the closest I got with an iframe, but it's sadly blocked by GH's CSP

<iframe srcdoc="&lt;script src=&quot;https://gist.github.com/jgierer12/06a8e3913ce4ae608c010b6f47efd257.js&quot;&gt;&lt;/script&gt;">

But you're right, the current solution of injecting the code directly inline isn't working right because of conflicting styles.

Inline Correct

However the Shadow DOM seems to work correctly and is quite easy to implement it:

link.attachShadow({mode: 'open'}).append(gistEl);

CSP also applies so it still requires the manual fetch

@fregante
Copy link
Member

fregante commented Dec 7, 2017

This is mergeable for me, but:

  • some gists may be long or have multiple files
    GitHub limits their embeds to 12 lines + scroll: gh

  • there's no clear indicator of what file belongs to what gist like for the regular github.com auto-embeds:

  • there's no loading indicator, the content just pops into place at some point in whatever loading order

@fregante fregante dismissed sindresorhus’s stale review December 7, 2017 16:20

Comments were addressed

@donocode
Copy link
Contributor Author

Thanks for the help with this @bfred-it

);

async function embedGist(link) {
const response = await fetch(link.href + '.json');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use template literal here.

@sindresorhus
Copy link
Member

Looks great now :)

Last thing, can you mention it in the "new feature" highlight in the readme and link to a screenshot showing it in action? https://github.com/sindresorhus/refined-github#new-features

@donocode
Copy link
Contributor Author

@donocode
Copy link
Contributor Author

embed-gist

@donocode
Copy link
Contributor Author

That's all complete now @sindresorhus

@sindresorhus sindresorhus merged commit e338b9e into refined-github:master Dec 12, 2017
@sindresorhus
Copy link
Member

Yay. Thanks for contributing this and for your patience through the review rounds :)

@sindresorhus
Copy link
Member

I opened a new issue for the things @bfred-it mentioned: #870

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants