FEATURE: Handle oneboxes for complex GitHub URLs (#18474)

GitHub PR URLs can link to a commit of the PR, a comment or a review
discussion.
This commit is contained in:
Bianca Nenciu 2022-10-06 20:26:04 +03:00 committed by GitHub
parent e83d35d6f3
commit 73e9875a1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 327 additions and 27 deletions

View File

@ -442,8 +442,8 @@ pre.onebox code {
.github-icon-container { .github-icon-container {
display: flex; display: flex;
align-items: flex-start; align-items: center;
margin-right: 5px; margin-right: 10px;
} }
.github-icon { .github-icon {
@ -526,8 +526,8 @@ pre.onebox code {
.github-icon-container { .github-icon-container {
display: flex; display: flex;
align-items: flex-start; align-items: center;
margin-right: 5px; margin-right: 10px;
} }
.github-icon { .github-icon {

View File

@ -39,8 +39,40 @@ module Onebox
result['body'], result['excerpt'] = compute_body(result['body']) result['body'], result['excerpt'] = compute_body(result['body'])
if result['commit'] = load_commit(link)
result['body'], result['excerpt'] = compute_body(result['commit']['body'])
elsif result['comment'] = load_comment(link)
result['body'], result['excerpt'] = compute_body(result['comment']['body'])
elsif result['discussion'] = load_review(link)
result['body'], result['excerpt'] = compute_body(result['discussion']['body'])
else
result['pr'] = true
end
result result
end end
def load_commit(link)
if commit_match = link.match(/commits\/(\h+)/)
load_json("https://api.github.com/repos/#{match[:owner]}/#{match[:repository]}/commits/#{commit_match[1]}")
end
end
def load_comment(link)
if comment_match = link.match(/#issuecomment-(\d+)/)
load_json("https://api.github.com/repos/#{match[:owner]}/#{match[:repository]}/issues/comments/#{comment_match[1]}")
end
end
def load_review(link)
if review_match = link.match(/#discussion_r(\d+)/)
load_json("https://api.github.com/repos/#{match[:owner]}/#{match[:repository]}/pulls/comments/#{review_match[1]}")
end
end
def load_json(url)
::MultiJson.load(URI.parse(url).open(read_timeout: timeout))
end
end end
end end
end end

View File

@ -14,7 +14,7 @@ module Onebox
'iframe' => %w[allowfullscreen frameborder height scrolling src width data-original-href data-unsanitized-src], 'iframe' => %w[allowfullscreen frameborder height scrolling src width data-original-href data-unsanitized-src],
'source' => %w[src type], 'source' => %w[src type],
'video' => %w[controls height loop width autoplay muted poster controlslist playsinline], 'video' => %w[controls height loop width autoplay muted poster controlslist playsinline],
'path' => %w[d], 'path' => %w[d fill-rule],
'svg' => ['aria-hidden', 'width', 'height', 'viewbox'], 'svg' => ['aria-hidden', 'width', 'height', 'viewbox'],
'div' => [:data], # any data-* attributes, 'div' => [:data], # any data-* attributes,
'span' => [:data], # any data-* attributes 'span' => [:data], # any data-* attributes

View File

@ -1,36 +1,100 @@
<div class="github-row"> <div class="github-row">
<div class="github-icon-container" title="Pull Request"> {{#commit}}
<svg width="60" height="60" class="github-icon" viewBox="0 0 12 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg> <div class="github-icon-container" title="Commit">
</div> <svg width="60" height="60" class="github-icon" viewBox="0 0 16 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M10.5 7.75a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0zm1.43.75a4.002 4.002 0 01-7.86 0H.75a.75.75 0 110-1.5h3.32a4.001 4.001 0 017.86 0h3.32a.75.75 0 110 1.5h-3.32z"></path></svg>
</div>
{{/commit}}
{{#comment}}
<div class="github-icon-container" title="Comment">
<svg width="60" height="60" class="github-icon" viewBox="0 0 16 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 2.75a.25.25 0 01.25-.25h8.5a.25.25 0 01.25.25v5.5a.25.25 0 01-.25.25h-3.5a.75.75 0 00-.53.22L3.5 11.44V9.25a.75.75 0 00-.75-.75h-1a.25.25 0 01-.25-.25v-5.5zM1.75 1A1.75 1.75 0 000 2.75v5.5C0 9.216.784 10 1.75 10H2v1.543a1.457 1.457 0 002.487 1.03L7.061 10h3.189A1.75 1.75 0 0012 8.25v-5.5A1.75 1.75 0 0010.25 1h-8.5zM14.5 4.75a.25.25 0 00-.25-.25h-.5a.75.75 0 110-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0114.25 12H14v1.543a1.457 1.457 0 01-2.487 1.03L9.22 12.28a.75.75 0 111.06-1.06l2.22 2.22v-2.19a.75.75 0 01.75-.75h1a.25.25 0 00.25-.25v-5.5z"></path></svg>
</div>
{{/comment}}
{{#discussion}}
<div class="github-icon-container" title="Discussion">
<svg width="60" height="60" class="github-icon" viewBox="0 0 16 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"></path></svg>
</div>
{{/discussion}}
{{#pr}}
<div class="github-icon-container" title="Pull Request">
<svg width="60" height="60" class="github-icon" viewBox="0 0 12 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"></path></svg>
</div>
{{/pr}}
<div class="github-info-container"> <div class="github-info-container">
<h4> {{#commit}}
<a href="{{html_url}}" target="_blank" rel="noopener">{{title}}</a> <h4>
</h4> <a href="{{link}}" target="_blank" rel="noopener">{{commit.message}}</a>
</h4>
<span>
Commit by
<a href="{{author.html_url}}" target="_blank" rel="noopener">
<img alt="{{author.login}}" src="{{author.avatar_url}}" class="onebox-avatar-inline" width="20" height="20">
{{author.login}}
</a>
in
<a href="{{link}}" target="_blank" rel="noopener">{{title}}</a>
</span>
{{/commit}}
{{#comment}}
<h4>
Comment by
<a href="{{user.html_url}}" target="_blank" rel="noopener">
<img alt="{{user.login}}" src="{{user.avatar_url}}" class="onebox-avatar-inline" width="20" height="20">
{{user.login}}
</a>
to
<a href="{{link}}" target="_blank" rel="noopener">{{title}}</a>
</h4>
{{/comment}}
{{#discussion}}
<h4>
Review by
<a href="{{user.html_url}}" target="_blank" rel="noopener">
<img alt="{{user.login}}" src="{{user.avatar_url}}" class="onebox-avatar-inline" width="20" height="20">
{{user.login}}
</a>
in
<a href="{{link}}" target="_blank" rel="noopener">{{title}}</a>
</h4>
{{/discussion}}
{{#pr}}
<h4>
<a href="{{link}}" target="_blank" rel="noopener">{{title}}</a>
</h4>
{{/pr}}
<div class="branches"> <div class="branches">
<code>{{base.label}}</code> ← <code>{{head.label}}</code> <code>{{base.label}}</code> ← <code>{{head.label}}</code>
</div> </div>
<div class="github-info"> {{#pr}}
<div class="date"> <div class="github-info">
opened <span class="discourse-local-date" data-format="ll" data-date="{{created_at_date}}" data-time="{{created_at_time}}" data-timezone="UTC">{{created_at}}</span> <div class="date">
</div> opened <span class="discourse-local-date" data-format="ll" data-date="{{created_at_date}}" data-time="{{created_at_time}}" data-timezone="UTC">{{created_at}}</span>
</div>
<div class="user"> <div class="user">
<a href="{{user.html_url}}" target="_blank" rel="noopener"> <a href="{{user.html_url}}" target="_blank" rel="noopener">
<img alt="{{user.login}}" src="{{user.avatar_url}}" class="onebox-avatar-inline" width="20" height="20"> <img alt="{{user.login}}" src="{{user.avatar_url}}" class="onebox-avatar-inline" width="20" height="20">
{{user.login}} {{user.login}}
</a> </a>
</div> </div>
<div class="lines" title="{{commits}} commits changed {{changed_files}} files with {{additions}} additions and {{deletions}} deletions"> <div class="lines" title="{{commits}} commits changed {{changed_files}} files with {{additions}} additions and {{deletions}} deletions">
<a href="{{html_url}}/files" target="_blank" rel="noopener"> <a href="{{html_url}}/files" target="_blank" rel="noopener">
<span class="added">+{{additions}}</span> <span class="added">+{{additions}}</span>
<span class="removed">-{{deletions}}</span> <span class="removed">-{{deletions}}</span>
</a> </a>
</div>
</div> </div>
</div> {{/pr}}
</div> </div>
</div> </div>

View File

@ -0,0 +1,44 @@
{
"url": "https://api.github.com/repos/discourse/discourse/issues/comments/21597425",
"html_url": "https://github.com/discourse/discourse/pull/1253#issuecomment-21597425",
"issue_url": "https://api.github.com/repos/discourse/discourse/issues/1253",
"id": 21597425,
"node_id": "MDEyOklzc3VlQ29tbWVudDIxNTk3NDI1",
"user": {
"login": "discoursebot",
"id": 3698800,
"node_id": "MDQ6VXNlcjM2OTg4MDA=",
"avatar_url": "https://avatars.githubusercontent.com/u/3698800?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/discoursebot",
"html_url": "https://github.com/discoursebot",
"followers_url": "https://api.github.com/users/discoursebot/followers",
"following_url": "https://api.github.com/users/discoursebot/following{/other_user}",
"gists_url": "https://api.github.com/users/discoursebot/gists{/gist_id}",
"starred_url": "https://api.github.com/users/discoursebot/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/discoursebot/subscriptions",
"organizations_url": "https://api.github.com/users/discoursebot/orgs",
"repos_url": "https://api.github.com/users/discoursebot/repos",
"events_url": "https://api.github.com/users/discoursebot/events{/privacy}",
"received_events_url": "https://api.github.com/users/discoursebot/received_events",
"type": "User",
"site_admin": false
},
"created_at": "2013-07-26T02:05:57Z",
"updated_at": "2013-07-26T02:05:57Z",
"author_association": "NONE",
"body": "You've signed the CLA, jamesaanderson. Thank you! This pull request is ready for review.\n",
"reactions": {
"url": "https://api.github.com/repos/discourse/discourse/issues/comments/21597425/reactions",
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"hooray": 0,
"confused": 0,
"heart": 0,
"rocket": 0,
"eyes": 0
},
"performed_via_github_app": null
}

View File

@ -0,0 +1,134 @@
{
"sha": "d7d3be1130c665cc7fab9f05dbf32335229137a6",
"node_id": "MDY6Q29tbWl0NzU2OTU3ODpkN2QzYmUxMTMwYzY2NWNjN2ZhYjlmMDVkYmYzMjMzNTIyOTEzN2E2",
"commit": {
"author": {
"name": "James Anderson",
"email": "me@jamesaanderson.com",
"date": "2013-07-26T02:03:23Z"
},
"committer": {
"name": "James Anderson",
"email": "me@jamesaanderson.com",
"date": "2013-07-26T02:03:23Z"
},
"message": "Add audio onebox\nhttp://meta.discourse.org/t/audio-html5-tag/8168",
"tree": {
"sha": "20c3841a2f4d2153d880b266cc9307296d8e07c6",
"url": "https://api.github.com/repos/discourse/discourse/git/trees/20c3841a2f4d2153d880b266cc9307296d8e07c6"
},
"url": "https://api.github.com/repos/discourse/discourse/git/commits/d7d3be1130c665cc7fab9f05dbf32335229137a6",
"comment_count": 0,
"verification": {
"verified": false,
"reason": "unsigned",
"signature": null,
"payload": null
}
},
"url": "https://api.github.com/repos/discourse/discourse/commits/d7d3be1130c665cc7fab9f05dbf32335229137a6",
"html_url": "https://github.com/discourse/discourse/commit/d7d3be1130c665cc7fab9f05dbf32335229137a6",
"comments_url": "https://api.github.com/repos/discourse/discourse/commits/d7d3be1130c665cc7fab9f05dbf32335229137a6/comments",
"author": {
"login": "jamesaanderson",
"id": 2722987,
"node_id": "MDQ6VXNlcjI3MjI5ODc=",
"avatar_url": "https://avatars.githubusercontent.com/u/2722987?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jamesaanderson",
"html_url": "https://github.com/jamesaanderson",
"followers_url": "https://api.github.com/users/jamesaanderson/followers",
"following_url": "https://api.github.com/users/jamesaanderson/following{/other_user}",
"gists_url": "https://api.github.com/users/jamesaanderson/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jamesaanderson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jamesaanderson/subscriptions",
"organizations_url": "https://api.github.com/users/jamesaanderson/orgs",
"repos_url": "https://api.github.com/users/jamesaanderson/repos",
"events_url": "https://api.github.com/users/jamesaanderson/events{/privacy}",
"received_events_url": "https://api.github.com/users/jamesaanderson/received_events",
"type": "User",
"site_admin": false
},
"committer": {
"login": "jamesaanderson",
"id": 2722987,
"node_id": "MDQ6VXNlcjI3MjI5ODc=",
"avatar_url": "https://avatars.githubusercontent.com/u/2722987?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jamesaanderson",
"html_url": "https://github.com/jamesaanderson",
"followers_url": "https://api.github.com/users/jamesaanderson/followers",
"following_url": "https://api.github.com/users/jamesaanderson/following{/other_user}",
"gists_url": "https://api.github.com/users/jamesaanderson/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jamesaanderson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jamesaanderson/subscriptions",
"organizations_url": "https://api.github.com/users/jamesaanderson/orgs",
"repos_url": "https://api.github.com/users/jamesaanderson/repos",
"events_url": "https://api.github.com/users/jamesaanderson/events{/privacy}",
"received_events_url": "https://api.github.com/users/jamesaanderson/received_events",
"type": "User",
"site_admin": false
},
"parents": [
{
"sha": "9c617d051e08a4a0335d8375e91d87a58c7e720e",
"url": "https://api.github.com/repos/discourse/discourse/commits/9c617d051e08a4a0335d8375e91d87a58c7e720e",
"html_url": "https://github.com/discourse/discourse/commit/9c617d051e08a4a0335d8375e91d87a58c7e720e"
}
],
"stats": {
"total": 20,
"additions": 19,
"deletions": 1
},
"files": [
{
"sha": "4bf610116998b798fd7255aaf835ce2ffc3d0dc7",
"filename": "app/assets/stylesheets/application/compose.css.scss",
"status": "modified",
"additions": 3,
"deletions": 0,
"changes": 3,
"blob_url": "https://github.com/discourse/discourse/blob/d7d3be1130c665cc7fab9f05dbf32335229137a6/app%2Fassets%2Fstylesheets%2Fapplication%2Fcompose.css.scss",
"raw_url": "https://github.com/discourse/discourse/raw/d7d3be1130c665cc7fab9f05dbf32335229137a6/app%2Fassets%2Fstylesheets%2Fapplication%2Fcompose.css.scss",
"contents_url": "https://api.github.com/repos/discourse/discourse/contents/app%2Fassets%2Fstylesheets%2Fapplication%2Fcompose.css.scss?ref=d7d3be1130c665cc7fab9f05dbf32335229137a6",
"patch": "@@ -299,6 +299,9 @@\n webkit-border-radius: 4px;\n ms-border-radius: 4px;\n }\n+ audio {\n+ max-width: 100%;\n+ }\n }\n #wmd-preview {\n border: 1px dashed $gray;"
},
{
"sha": "f925244a588046d6caf2bc807c719a59569ad3c2",
"filename": "app/assets/stylesheets/application/topic-post.css.scss",
"status": "modified",
"additions": 3,
"deletions": 0,
"changes": 3,
"blob_url": "https://github.com/discourse/discourse/blob/d7d3be1130c665cc7fab9f05dbf32335229137a6/app%2Fassets%2Fstylesheets%2Fapplication%2Ftopic-post.css.scss",
"raw_url": "https://github.com/discourse/discourse/raw/d7d3be1130c665cc7fab9f05dbf32335229137a6/app%2Fassets%2Fstylesheets%2Fapplication%2Ftopic-post.css.scss",
"contents_url": "https://api.github.com/repos/discourse/discourse/contents/app%2Fassets%2Fstylesheets%2Fapplication%2Ftopic-post.css.scss?ref=d7d3be1130c665cc7fab9f05dbf32335229137a6",
"patch": "@@ -515,6 +515,9 @@\n img {\n max-width: 100%;\n }\n+ audio {\n+ max-width: 100%;\n+ }\n .topic-body {\n position: relative;\n .contents {"
},
{
"sha": "c2fda69aa041b7075287c5144fd74bd746d27aaf",
"filename": "lib/oneboxer/audio_onebox.rb",
"status": "added",
"additions": 12,
"deletions": 0,
"changes": 12,
"blob_url": "https://github.com/discourse/discourse/blob/d7d3be1130c665cc7fab9f05dbf32335229137a6/lib%2Foneboxer%2Faudio_onebox.rb",
"raw_url": "https://github.com/discourse/discourse/raw/d7d3be1130c665cc7fab9f05dbf32335229137a6/lib%2Foneboxer%2Faudio_onebox.rb",
"contents_url": "https://api.github.com/repos/discourse/discourse/contents/lib%2Foneboxer%2Faudio_onebox.rb?ref=d7d3be1130c665cc7fab9f05dbf32335229137a6",
"patch": "@@ -0,0 +1,12 @@\n+require_dependency 'oneboxer/base_onebox'\n+\n+module Oneboxer\n+ class AudioOnebox < BaseOnebox\n+\n+ matcher /^https?:\\/\\/.*\\.mp3$/\n+\n+ def onebox\n+ \"<audio controls><source src='#{@url}'><a href='#{@url}'>#{@url}</a></audio>\"\n+ end\n+ end\n+end"
},
{
"sha": "e3924069face09f9f716afd09b166af83da496a9",
"filename": "lib/oneboxer/video_onebox.rb",
"status": "modified",
"additions": 1,
"deletions": 1,
"changes": 2,
"blob_url": "https://github.com/discourse/discourse/blob/d7d3be1130c665cc7fab9f05dbf32335229137a6/lib%2Foneboxer%2Fvideo_onebox.rb",
"raw_url": "https://github.com/discourse/discourse/raw/d7d3be1130c665cc7fab9f05dbf32335229137a6/lib%2Foneboxer%2Fvideo_onebox.rb",
"contents_url": "https://api.github.com/repos/discourse/discourse/contents/lib%2Foneboxer%2Fvideo_onebox.rb?ref=d7d3be1130c665cc7fab9f05dbf32335229137a6",
"patch": "@@ -3,7 +3,7 @@\n module Oneboxer\n class VideoOnebox < BaseOnebox\n \n- matcher /^https?:\\/\\/.*\\.(mov|mp4|ogg)$/\n+ matcher /^https?:\\/\\/.*\\.(mov|mp4)$/\n \n def onebox\n \"<video width='100%' height='100%' controls><source src='#{@url}'><a href='#{@url}'>#{@url}</a></video>\""
}
]
}

View File

@ -49,4 +49,30 @@ RSpec.describe Onebox::Engine::GithubPullRequestOnebox do
expect(html).not_to include("test comment") expect(html).not_to include("test comment")
end end
end end
context "with commit links" do
before do
@link = "https://github.com/discourse/discourse/pull/1253/commits/d7d3be1130c665cc7fab9f05dbf32335229137a6"
@uri = "https://api.github.com/repos/discourse/discourse/commits/d7d3be1130c665cc7fab9f05dbf32335229137a6"
stub_request(:get, @uri).to_return(status: 200, body: onebox_response(described_class.onebox_name + "_commit"))
end
it "includes commit name" do
expect(html).to include("Add audio onebox")
end
end
context "with comment links" do
before do
@link = "https://github.com/discourse/discourse/pull/1253/#issuecomment-21597425"
@uri = "https://api.github.com/repos/discourse/discourse/issues/comments/21597425"
stub_request(:get, @uri).to_return(status: 200, body: onebox_response(described_class.onebox_name + "_comment"))
end
it "includes comment" do
expect(html).to include("You&#39;ve signed the CLA")
end
end
end end