[deploy] Add Wikipedia liquid tag (#7193)

This commit is contained in:
Maja Komel 2020-04-22 17:54:56 +02:00 committed by GitHub
parent 844c20b560
commit 4499e5eb6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 398 additions and 0 deletions

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" stroke-miterlimit="10" style="shape-rendering:geometricPrecision; fill-rule:evenodd">
<path d="M 120.85,29.21 C 120.85,29.62 120.72,29.99 120.47,30.33 C 120.21,30.66 119.94,30.83 119.63,30.83 C 117.14,31.07 115.09,31.87 113.51,33.24 C 111.92,34.6 110.29,37.21 108.6,41.05 L 82.8,99.19 C 82.63,99.73 82.16,100 81.38,100 C 80.77,100 80.3,99.73 79.96,99.19 L 65.49,68.93 L 48.85,99.19 C 48.51,99.73 48.04,100 47.43,100 C 46.69,100 46.2,99.73 45.96,99.19 L 20.61,41.05 C 19.03,37.44 17.36,34.92 15.6,33.49 C 13.85,32.06 11.4,31.17 8.27,30.83 C 8,30.83 7.74,30.69 7.51,30.4 C 7.27,30.12 7.15,29.79 7.15,29.42 C 7.15,28.47 7.42,28 7.96,28 C 10.22,28 12.58,28.1 15.05,28.3 C 17.34,28.51 19.5,28.61 21.52,28.61 C 23.58,28.61 26.01,28.51 28.81,28.3 C 31.74,28.1 34.34,28 36.6,28 C 37.14,28 37.41,28.47 37.41,29.42 C 37.41,30.36 37.24,30.83 36.91,30.83 C 34.65,31 32.87,31.58 31.57,32.55 C 30.27,33.53 29.62,34.81 29.62,36.4 C 29.62,37.21 29.89,38.22 30.43,39.43 L 51.38,86.74 L 63.27,64.28 L 52.19,41.05 C 50.2,36.91 48.56,34.23 47.28,33.03 C 46,31.84 44.06,31.1 41.46,30.83 C 41.22,30.83 41,30.69 40.78,30.4 C 40.56,30.12 40.45,29.79 40.45,29.42 C 40.45,28.47 40.68,28 41.16,28 C 43.42,28 45.49,28.1 47.38,28.3 C 49.2,28.51 51.14,28.61 53.2,28.61 C 55.22,28.61 57.36,28.51 59.62,28.3 C 61.95,28.1 64.24,28 66.5,28 C 67.04,28 67.31,28.47 67.31,29.42 C 67.31,30.36 67.15,30.83 66.81,30.83 C 62.29,31.14 60.03,32.42 60.03,34.68 C 60.03,35.69 60.55,37.26 61.6,39.38 L 68.93,54.26 L 76.22,40.65 C 77.23,38.73 77.74,37.11 77.74,35.79 C 77.74,32.69 75.48,31.04 70.96,30.83 C 70.55,30.83 70.35,30.36 70.35,29.42 C 70.35,29.08 70.45,28.76 70.65,28.46 C 70.86,28.15 71.06,28 71.26,28 C 72.88,28 74.87,28.1 77.23,28.3 C 79.49,28.51 81.35,28.61 82.8,28.61 C 83.84,28.61 85.38,28.52 87.4,28.35 C 89.96,28.12 92.11,28 93.83,28 C 94.23,28 94.43,28.4 94.43,29.21 C 94.43,30.29 94.06,30.83 93.32,30.83 C 90.69,31.1 88.57,31.83 86.97,33.01 C 85.37,34.19 83.37,36.87 80.98,41.05 L 71.26,59.02 L 84.42,85.83 L 103.85,40.65 C 104.52,39 104.86,37.48 104.86,36.1 C 104.86,32.79 102.6,31.04 98.08,30.83 C 97.67,30.83 97.47,30.36 97.47,29.42 C 97.47,28.47 97.77,28 98.38,28 C 100.03,28 101.99,28.1 104.25,28.3 C 106.34,28.51 108.1,28.61 109.51,28.61 C 111,28.61 112.72,28.51 114.67,28.3 C 116.7,28.1 118.52,28 120.14,28 C 120.61,28 120.85,28.4 120.85,29.21 z" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -13,3 +13,4 @@
@import 'PollTag';
@import 'ClassifiedListingTag';
@import 'StackexchangeTag';
@import 'WikipediaTag';

View file

@ -0,0 +1,62 @@
@import 'variables';
.ltag__wikipedia--container {
border: 1px solid $light-medium-gray;
border-radius: 3px;
box-shadow: $shadow;
margin: 1.1em auto 1.3em;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol' !important;
overflow: hidden;
max-width: 620px;
padding: 0.8em 0.5em 0;
a {
color: #0366d6 !important;
color: var(--theme-anchor-color, #0366d6) !important;
}
.ltag__wikipedia--header {
font-weight: 400;
font-size: 1.2em;
line-height: 1.3em;
margin: 0em 0px 0.5em;
.ltag__wikipedia--logo {
width: 1.15em;
max-width: 1.1em;
display: inline-block;
left: 0px;
margin-right: 0.3em;
vertical-align: -0.18em;
filter: invert(0);
filter: var(--theme-social-icon-invert, invert(0));
}
}
.ltag__wikipedia--extract {
font-weight: 400;
margin: 0;
margin-left: 0.15em;
font-size: 0.75em;
line-height: 1.5em;
padding-bottom: 1em;
}
.ltag__wikipedia--btn--container {
padding: 0.1em 0 1.15em;
z-index: 100;
text-align: center;
position: relative;
box-shadow: 0px 0px 60px 42px #fff;
box-shadow: 0px 0px 60px 42px var(--theme-container-background, #fff);
}
.ltag__wikipedia--btn {
color: #0366d6;
background-color: #f1f8ff;
border-radius: 3px;
line-height: 20px;
padding: 0.25em 1.2em;
opacity: 0.9;
font-weight: bold;
border: 1px solid #0366d6;
font-size: 0.75em;
&:hover {
opacity: 1;
}
}
}

View file

@ -0,0 +1,102 @@
class WikipediaTag < LiquidTagBase
PARTIAL = "liquids/wikipedia".freeze
WIKI_REGEXP = %r{^https?://([a-z-]+)\.wikipedia.org/wiki/([\S]+)$}.freeze
def initialize(tag_name, input, tokens)
super
@data = get_data(input.strip)
end
def render(_context)
ActionController::Base.new.render_to_string(
partial: PARTIAL,
locals: {
title: @data[:title],
extract: @data[:extract],
url: @data[:url]
},
)
end
private
def valid_url?(input)
input.match?(WIKI_REGEXP)
end
def get_data(input)
url = ActionController::Base.helpers.strip_tags(input).strip
raise StandardError, "Invalid Wikipedia URL" unless valid_url?(url)
uri = URI.parse(url)
lang = uri.host.split(".", 2).first
title = uri.path.split("/").last
anchor = uri.fragment
if anchor
parse_page_with_anchor(url, lang, title, anchor)
else
parse_page(url, lang, title)
end
end
def parse_page_with_anchor(url, lang, title, anchor)
api_url = "https://#{lang}.wikipedia.org/api/rest_v1/page/mobile-sections/#{title}"
response = HTTParty.get(api_url, headers: { 'user-agent': URL.url("/contact") })
handle_response_error(response, url)
text, section_title = get_section_contents(response, anchor, url)
title = "#{response['lead']['normalizedtitle']} - #{section_title}"
{
title: title,
url: url,
extract: text_clean_up(text)
}
end
def parse_page(url, lang, title)
api_url = "https://#{lang}.wikipedia.org/api/rest_v1/page/summary/#{title}"
response = HTTParty.get(api_url, headers: { 'user-agent': URL.url("/contact") })
handle_response_error(response, url)
{
title: response["title"],
url: url,
extract: response["extract_html"]
}
end
def handle_response_error(response, input)
return if response.code == 200
raise StandardError, "Couldn't find the Wikipedia article - #{input}: #{response['detail']}"
end
def get_section_contents(response, anchor, input)
text = title = ""
response["remaining"]["sections"].each do |section|
if section["anchor"] == CGI.unescape(anchor)
text = section["text"]
title = section["line"]
end
end
return [text, title] if title.present?
raise StandardError, "Couldn't find the section of the Wikipedia article - #{input}"
end
def text_clean_up(text)
doc = Nokogiri::HTML(text)
path_expression = "//div[contains(@class, 'noprint') or contains(@class, 'hatnote')] |
//span[@class='mw-ref'] |
//figure |
//sup"
doc.xpath(path_expression).each(&:remove)
doc.xpath("//a").each { |x| x.replace Nokogiri::XML::Text.new(x.inner_html, x.document) }
doc.to_html
end
end
Liquid::Template.register_tag("wikipedia", WikipediaTag)

View file

@ -0,0 +1,12 @@
<div class="ltag__wikipedia--container">
<div class="ltag__wikipedia--header">
<img src="<%= ActionController::Base.helpers.asset_path("wikipedia-logo.svg") %>" class="ltag__wikipedia--logo" alt="Wikipedia Logo" aria-label="Wikipedia Logo">
<a href="<%= url %>" target="_blank" rel="noopener noreferrer"><%= title %></a>
</div>
<div class="ltag__wikipedia--extract"><%= (HTML_Truncator.truncate extract, 150).html_safe %></div>
<div class="ltag__wikipedia--btn--container">
<button class="ltag__wikipedia--btn" type="button">
<a href="<%= url %>" target="_blank" rel="noopener noreferrer">View on Wikipedia</a>
</button>
</div>
</div>

View file

@ -332,6 +332,13 @@
</ul>
<pre>{% stackexchange <span style="color: aquamarine;">170185</span> <span style="color: orange;">diy</span> %}</pre>
</p>
<h3><strong>Wikipedia Embed</strong></h3>
<p>Enter the full URL of the Wikipedia article you want to embed, with or without the anchor.</p>
<p>
<code>{% wikipedia https://en.wikipedia.org/wiki/Wikipedia %}</code>
<br/>
<code>{% wikipedia https://en.wikipedia.org/wiki/Wikipedia#Diversity %}</code>
</p>
<h3><strong>Asciinema Embed</strong></h3>
<p>All you need is the Asciinema id:</p>
<code>{% asciinema 239367 %}</code>

View file

@ -53,6 +53,7 @@ Here is a bunch of liquid tags supported on DEV:
{% spotify spotify:episode:5V4XZWqZQJvbddd31n56mf %}
{% blogcast 1234 %}
{% kotlin https://pl.kotl.in/owreUFFUG %}
{% wikipedia https://en.wikipedia.org/wiki/Wikipedia %}
```
## How liquid tags are developed

View file

@ -0,0 +1,37 @@
require "rails_helper"
RSpec.describe WikipediaTag, type: :liquid_tag, vcr: true do
describe "#id" do
let(:valid_url) { "https://en.wikipedia.org/wiki/Wikipedia" }
let(:valid_section_url) { "https://en.wikipedia.org/wiki/Wikipedia#Diversity" }
let(:invalid_url) { "https://123.wikipedia.org/wiki/Wiki" }
def generate_new_liquid(url)
Liquid::Template.register_tag("wikipedia", WikipediaTag)
Liquid::Template.parse("{% wikipedia #{url} %}")
end
it "renders wikipedia excerpt html" do
VCR.use_cassette("wikipedia_tag") do
liquid = generate_new_liquid(valid_url)
expect(liquid.render).to include("ltag__wikipedia")
expect(liquid.render).to include("<b>Wikipedia</b> is a multilingual online encyclopedia")
end
end
it "renders wikipedia article section html" do
VCR.use_cassette("wikipedia_section_tag") do
liquid = generate_new_liquid(valid_section_url)
expect(liquid.render).to include("ltag__wikipedia")
expect(liquid.render).to include("Several studies have shown that most of the Wikipedia contributors are male.")
end
end
it "rejects invalid url" do
expect do
liquid = generate_new_liquid(invalid_url)
liquid.render
end.to raise_error(StandardError)
end
end
end

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,86 @@
---
http_interactions:
- request:
method: get
uri: https://en.wikipedia.org/api/rest_v1/page/summary/Wikipedia
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Content-Type:
- application/json; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Summary/1.4.2"
Cache-Control:
- s-maxage=1209600, max-age=300
Content-Language:
- en
Vary:
- Accept-Encoding
Content-Location:
- https://en.wikipedia.org/api/rest_v1/page/summary/Wikipedia
Access-Control-Allow-Origin:
- "*"
Access-Control-Allow-Methods:
- GET,HEAD
Access-Control-Allow-Headers:
- accept, content-type, content-length, cache-control, accept-language, api-user-agent,
if-match, if-modified-since, if-none-match, dnt, accept-encoding
Access-Control-Expose-Headers:
- etag
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
Referrer-Policy:
- origin-when-cross-origin
X-Xss-Protection:
- 1; mode=block
Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
X-Content-Security-Policy:
- default-src 'none'; frame-ancestors 'none'
X-Webkit-Csp:
- default-src 'none'; frame-ancestors 'none'
X-Request-Id:
- 7bc92964-a2bd-4f08-b9b6-7f718282848d
Server:
- restbase1016
Date:
- Mon, 13 Apr 2020 17:02:54 GMT
Etag:
- W/"949289700/5ae95970-7cf7-11ea-86c0-dbb91750f4b9"
Age:
- '58602'
X-Cache:
- cp3062 hit, cp3060 hit/430
X-Cache-Status:
- hit-front
Server-Timing:
- cache;desc="hit-front"
Strict-Transport-Security:
- max-age=106384710; includeSubDomains; preload
X-Client-Ip:
- 77.13.172.109
Accept-Ranges:
- bytes
Content-Length:
- '893'
Connection:
- keep-alive
body:
encoding: ASCII-8BIT
string: !binary |-
eyJ0eXBlIjoic3RhbmRhcmQiLCJ0aXRsZSI6Ildpa2lwZWRpYSIsImRpc3BsYXl0aXRsZSI6Ildpa2lwZWRpYSIsIm5hbWVzcGFjZSI6eyJpZCI6MCwidGV4dCI6IiJ9LCJ3aWtpYmFzZV9pdGVtIjoiUTUyIiwidGl0bGVzIjp7ImNhbm9uaWNhbCI6Ildpa2lwZWRpYSIsIm5vcm1hbGl6ZWQiOiJXaWtpcGVkaWEiLCJkaXNwbGF5IjoiV2lraXBlZGlhIn0sInBhZ2VpZCI6NTA0MzczNCwidGh1bWJuYWlsIjp7InNvdXJjZSI6Imh0dHBzOi8vdXBsb2FkLndpa2ltZWRpYS5vcmcvd2lraXBlZGlhL2VuL3RodW1iLzgvODAvV2lraXBlZGlhLWxvZ28tdjIuc3ZnLzMyMHB4LVdpa2lwZWRpYS1sb2dvLXYyLnN2Zy5wbmciLCJ3aWR0aCI6MzIwLCJoZWlnaHQiOjI5Mn0sIm9yaWdpbmFsaW1hZ2UiOnsic291cmNlIjoiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvZW4vOC84MC9XaWtpcGVkaWEtbG9nby12Mi5zdmciLCJ3aWR0aCI6MTAzLCJoZWlnaHQiOjk0fSwibGFuZyI6ImVuIiwiZGlyIjoibHRyIiwicmV2aXNpb24iOiI5NDkyODk3MDAiLCJ0aWQiOiI1YWU5NTk3MC03Y2Y3LTExZWEtODZjMC1kYmI5MTc1MGY0YjkiLCJ0aW1lc3RhbXAiOiIyMDIwLTA0LTA1VDE3OjAzOjU4WiIsImRlc2NyaXB0aW9uIjoiRnJlZSBvbmxpbmUgZW5jeWNsb3BlZGlhIHRoYXQgYW55b25lIGNhbiBlZGl0IiwiZGVzY3JpcHRpb25fc291cmNlIjoibG9jYWwiLCJjb250ZW50X3VybHMiOnsiZGVza3RvcCI6eyJwYWdlIjoiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2lraXBlZGlhIiwicmV2aXNpb25zIjoiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2lraXBlZGlhP2FjdGlvbj1oaXN0b3J5IiwiZWRpdCI6Imh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dpa2lwZWRpYT9hY3Rpb249ZWRpdCIsInRhbGsiOiJodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UYWxrOldpa2lwZWRpYSJ9LCJtb2JpbGUiOnsicGFnZSI6Imh0dHBzOi8vZW4ubS53aWtpcGVkaWEub3JnL3dpa2kvV2lraXBlZGlhIiwicmV2aXNpb25zIjoiaHR0cHM6Ly9lbi5tLndpa2lwZWRpYS5vcmcvd2lraS9TcGVjaWFsOkhpc3RvcnkvV2lraXBlZGlhIiwiZWRpdCI6Imh0dHBzOi8vZW4ubS53aWtpcGVkaWEub3JnL3dpa2kvV2lraXBlZGlhP2FjdGlvbj1lZGl0IiwidGFsayI6Imh0dHBzOi8vZW4ubS53aWtpcGVkaWEub3JnL3dpa2kvVGFsazpXaWtpcGVkaWEifX0sImFwaV91cmxzIjp7InN1bW1hcnkiOiJodHRwczovL2VuLndpa2lwZWRpYS5vcmcvYXBpL3Jlc3RfdjEvcGFnZS9zdW1tYXJ5L1dpa2lwZWRpYSIsIm1ldGFkYXRhIjoiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL2FwaS9yZXN0X3YxL3BhZ2UvbWV0YWRhdGEvV2lraXBlZGlhIiwicmVmZXJlbmNlcyI6Imh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy9hcGkvcmVzdF92MS9wYWdlL3JlZmVyZW5jZXMvV2lraXBlZGlhIiwibWVkaWEiOiJodHRwczovL2VuLndpa2lwZWRpYS5vcmcvYXBpL3Jlc3RfdjEvcGFnZS9tZWRpYS9XaWtpcGVkaWEiLCJlZGl0X2h0bWwiOiJodHRwczovL2VuLndpa2lwZWRpYS5vcmcvYXBpL3Jlc3RfdjEvcGFnZS9odG1sL1dpa2lwZWRpYSIsInRhbGtfcGFnZV9odG1sIjoiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL2FwaS9yZXN0X3YxL3BhZ2UvaHRtbC9UYWxrOldpa2lwZWRpYSJ9LCJleHRyYWN0IjoiV2lraXBlZGlhIGlzIGEgbXVsdGlsaW5ndWFsIG9ubGluZSBlbmN5Y2xvcGVkaWEgY3JlYXRlZCBhbmQgbWFpbnRhaW5lZCBhcyBhbiBvcGVuIGNvbGxhYm9yYXRpb24gcHJvamVjdCBieSBhIGNvbW11bml0eSBvZiB2b2x1bnRlZXIgZWRpdG9ycyB1c2luZyBhIHdpa2ktYmFzZWQgZWRpdGluZyBzeXN0ZW0uIEl0IGlzIHRoZSBsYXJnZXN0IGFuZCBtb3N0IHBvcHVsYXIgZ2VuZXJhbCByZWZlcmVuY2Ugd29yayBvbiB0aGUgV29ybGQgV2lkZSBXZWIsIGFuZCBpcyBvbmUgb2YgdGhlIDIwIG1vc3QgcG9wdWxhciB3ZWJzaXRlcyByYW5rZWQgYnkgQWxleGEsIGFzIG9mIE1hcmNowqAyMDIwLiBJdCBmZWF0dXJlcyBleGNsdXNpdmVseSBmcmVlIGNvbnRlbnQgYW5kIG5vIGNvbW1lcmNpYWwgYWRzLCBhbmQgaXMgb3duZWQgYW5kIHN1cHBvcnRlZCBieSB0aGUgV2lraW1lZGlhIEZvdW5kYXRpb24sIGEgbm9uLXByb2ZpdCBvcmdhbml6YXRpb24gZnVuZGVkIHByaW1hcmlseSB0aHJvdWdoIGRvbmF0aW9ucy4iLCJleHRyYWN0X2h0bWwiOiI8cD48Yj5XaWtpcGVkaWE8L2I+IGlzIGEgbXVsdGlsaW5ndWFsIG9ubGluZSBlbmN5Y2xvcGVkaWEgY3JlYXRlZCBhbmQgbWFpbnRhaW5lZCBhcyBhbiBvcGVuIGNvbGxhYm9yYXRpb24gcHJvamVjdCBieSBhIGNvbW11bml0eSBvZiB2b2x1bnRlZXIgZWRpdG9ycyB1c2luZyBhIHdpa2ktYmFzZWQgZWRpdGluZyBzeXN0ZW0uIEl0IGlzIHRoZSBsYXJnZXN0IGFuZCBtb3N0IHBvcHVsYXIgZ2VuZXJhbCByZWZlcmVuY2Ugd29yayBvbiB0aGUgV29ybGQgV2lkZSBXZWIsIGFuZCBpcyBvbmUgb2YgdGhlIDIwIG1vc3QgcG9wdWxhciB3ZWJzaXRlcyByYW5rZWQgYnkgQWxleGEsIGFzIG9mIE1hcmNowqAyMDIwLiBJdCBmZWF0dXJlcyBleGNsdXNpdmVseSBmcmVlIGNvbnRlbnQgYW5kIG5vIGNvbW1lcmNpYWwgYWRzLCBhbmQgaXMgb3duZWQgYW5kIHN1cHBvcnRlZCBieSB0aGUgV2lraW1lZGlhIEZvdW5kYXRpb24sIGEgbm9uLXByb2ZpdCBvcmdhbml6YXRpb24gZnVuZGVkIHByaW1hcmlseSB0aHJvdWdoIGRvbmF0aW9ucy48L3A+In0=
http_version: null
recorded_at: Tue, 14 Apr 2020 09:19:35 GMT
recorded_with: VCR 5.1.0