Support for runnable kotlin snippets #3776 (#3801)

This commit is contained in:
Jean-Michel Fayard 2019-08-29 22:06:17 +02:00 committed by Mac Siri
parent 880655b388
commit 4af02c8a48
6 changed files with 118 additions and 0 deletions

View file

@ -0,0 +1,55 @@
class KotlinTag < LiquidTagBase
PARTIAL = "liquids/kotlin".freeze
def initialize(tag_name, link, tokens)
super
stripped_link = ActionController::Base.helpers.strip_tags(link)
the_link = stripped_link.split(" ").first
@embedded_url = KotlinTag.embedded_url(the_link)
end
def render(_context)
ActionController::Base.new.render_to_string(
partial: PARTIAL,
locals: {
url: @embedded_url
}
)
end
def self.embedded_url(link)
"https://play.kotlinlang.org/embed?" + URI.encode_www_form(parse_link(link))
end
def self.parse_link(link)
begin
url = URI(link)
rescue
raise_error
end
hostname_ok = url.hostname == "pl.kotl.in"
short = url.path.delete("/")
raise_error unless hostname_ok && valid_param?(short)
parse_params(url, short)
end
def self.parse_params(url, short)
query = url.query.nil? ? [] : URI.decode_www_form(url.query)
result = { short: short }
%i[from to theme readOnly].each do |param|
value = query.assoc(param.id2name)&.last
result[param] = valid_param?(value) ? value : ""
end
result
end
def self.valid_param?(value)
!value&.match(/^[a-zA-Z0-9]+$/)&.nil?
end
def raise_error
raise StandardError, "Invalid Kotlin Playground URL"
end
end
Liquid::Template.register_tag("kotlin", KotlinTag)

View file

@ -0,0 +1,6 @@
<iframe
src="<%= url %>"
allowtransparency="true"
scrolling="no"
frameborder="0"
></iframe>

View file

@ -178,6 +178,10 @@
<code>{% codepen https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result %}</code>
</dd>
</dl>
<h3><strong>Kotlin Playground</strong></h3>
<p>To create a runnable kotlin snippet, create a Kotlin Snippet at <a href="https://play.kotlinlang.org">https://play.kotlinlang.org</a></p>
<p>Go to <code>Share</code> dialog and copy the full <code>link</code> from the <code>Medium</code> tab. Use it as follows:</p>
<code>{% kotlin https://pl.kotl.in/owreUFFUG?theme=darcula&from=3&to=6&readOnly=true %}</code>
<h3><strong>RunKit Embed</strong></h3>
<p>Put executable code within a runkit liquid block, as follows:</p>
<pre>{% runkit<br>// hidden setup JavaScript code goes in this preamble area<br>const hiddenVar = 42<br>%}<br>// visible, reader-editable JavaScript code goes here<br>console.log(hiddenVar)<br>{% endrunkit %} <br></pre>

View file

@ -40,4 +40,5 @@ Here is a bunch of liquid tags supported on DEV:
{% soundcloud https://soundcloud.com/user-261265215/dev-to-review-episode-1 %}
{% spotify spotify:episode:5V4XZWqZQJvbddd31n56mf %}
{% blogcast 1234 %}
{% kotlin https://pl.kotl.in/owreUFFUG %}
```

View file

@ -0,0 +1,46 @@
require "rails_helper"
RSpec.describe KotlinTag, type: :liquid_template do
describe "#link" do
input = "https://pl.kotl.in/owreUFFUG?theme=darcula&from=3&to=6&readOnly=true"
expected = "https://play.kotlinlang.org/embed?short=owreUFFUG&from=3&to=6&theme=darcula&readOnly=true"
def generate_new_liquid(link)
Liquid::Template.register_tag("kotlin", KotlinTag)
Liquid::Template.parse("{% kotlin #{link} %}")
end
it "accepts only Kotlin Playground links" do
badurl = "https://example.com"
expect do
generate_new_liquid(badurl)
end.to raise_error(StandardError)
badurl = "not even an URL"
expect do
generate_new_liquid(badurl)
end.to raise_error(StandardError)
end
def check(url, expected)
expect(KotlinTag.parse_link(url)).to eq(expected)
end
it "parses URL correctly" do
check("https://pl.kotl.in/owreUFFUG", from: nil, readOnly: nil, short: "owreUFFUG", theme: nil, to: nil)
check("https://pl.kotl.in/owreUFFUG?theme=dracula&from=3&to=6&readOnly=true", from: "3", readOnly: "true", short: "owreUFFUG", theme: "dracula", to: "6")
check("https://pl.kotl.in/owreUFFUG?theme=dracula&readOnly=true", from: nil, readOnly: "true", short: "owreUFFUG", theme: "dracula", to: nil)
check("https://pl.kotl.in/owreUFFUG?from=3&to=6", from: "3", readOnly: nil, short: "owreUFFUG", theme: nil, to: "6")
end
it "produces a correct final URL" do
expect(KotlinTag.embedded_url(input)).to eq(expected)
end
it "renders correctly a Kotlin Playground link" do
liquid = generate_new_liquid(input)
rendered_kotlin_iframe = liquid.render
Approvals.verify(rendered_kotlin_iframe, name: "kotlin_liquid_tag", format: :html)
end
end
end

View file

@ -0,0 +1,6 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<iframe src="https://play.kotlinlang.org/embed?short=owreUFFUG&amp;from&amp;to&amp;theme=darcula&amp;readOnly" allowtransparency="true" scrolling="no" frameborder="0"></iframe>
</body>
</html>