Finishes adding all the codepen embed options available (#16102)

Co-authored-by: JaneOri <7545075+James0x57@users.noreply.github.com>
Co-authored-by: Michael Kohl <me@citizen428.net>
This commit is contained in:
Jane ♥ 2022-01-18 20:23:15 -06:00 committed by GitHub
parent b4b12a993a
commit d5348995c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 193 additions and 5 deletions

View file

@ -1,12 +1,15 @@
class CodepenTag < LiquidTagBase
PARTIAL = "liquids/codepen".freeze
REGISTRY_REGEXP =
%r{\A(http|https)://(codepen\.io|codepen\.io/team)/[a-zA-Z0-9_\-]{1,30}/pen/([a-zA-Z0-9]{5,32})/{0,1}\z}
%r{\A(http|https)://(codepen\.io|codepen\.io/team)/[a-zA-Z0-9_\-]{1,30}/(pen|embed)(/preview)?/([a-zA-Z0-9]{5,32})/{0,1}\z}
def initialize(_tag_name, link, _parse_context)
super
link = CGI.unescape_html(link)
@link = parse_link(link)
@build_options = parse_options(link)
valid_options = parse_options(link)
@build_options = valid_options.gsub(/height=\d{3,4}&(amp;)?/, '')
@height = (valid_options[/height=(\d{3,4})/, 1] || '600').to_i
end
def render(_context)
@ -14,7 +17,7 @@ class CodepenTag < LiquidTagBase
partial: PARTIAL,
locals: {
link: @link,
height: 600,
height: @height,
build_options: @build_options
},
)
@ -23,7 +26,10 @@ class CodepenTag < LiquidTagBase
private
def valid_option(option)
option.match(/(default-tab=\w+(,\w+)?)/)
option.match(/(default-tab=\w+(,\w+)?)/) ||
option.match(/(theme-id=\d{1,7})/) ||
option.match(/(editable=true)/) ||
option.match(/(height=\d{3,4})/)
end
def parse_options(input)
@ -60,4 +66,4 @@ end
Liquid::Template.register_tag("codepen", CodepenTag)
UnifiedEmbed.register(CodepenTag, regexp: CodepenTag::REGISTRY_REGEXP)
UnifiedEmbed.register(CodepenTag, regexp: CodepenTag::REGISTRY_REGEXP)

View file

@ -283,6 +283,36 @@
<p>Add default-tab parameter to your CodePen embed tag. Defaults to <i>result</i>.</p>
<pre>{% codepen https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result %}</pre>
</dd>
<dt><strong>preview</strong></dt>
<dd>
<p>Change the codepen URL path from /pen/ to /pen/preview/ (or to /embed/preview/) to use codepen's Click-to-Load preview embed feature in the resulting iframe.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/preview/dyVMgBg %}</pre>
</dd>
<dt><strong>height</strong></dt>
<dd>
<p>Add height parameter to your CodePen embed tag and to the resulting iframe itself. Defaults to <i>600</i></p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 %}</pre>
</dd>
<dt><strong>theme-id</strong></dt>
<dd>
<p>Add theme-id parameter to your CodePen embed tag. The pen and theme-id must be from a codepen pro user to have an effect.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148 %}</pre>
</dd>
<dt><strong>editable=true</strong></dt>
<dd>
<p>Add editable=true parameter to your CodePen embed tag. Editable Embeds require more resources than non-editable Embeds. The pen must be from a codepen pro user to have an effect.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg editable=true %}</pre>
</dd>
<dt><strong>multiple-params</strong></dt>
<dd>
<p>Add multiple parameters to your CodePen embed tag.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 default-tab=css,result editable=true %}</pre>
</dd>
</dl>
<%= render partial: "editor_guide_h3", locals: { id: "kotlin-playground", title: "Kotlin Playground" } %>

View file

@ -145,6 +145,36 @@
Add default-tab parameter to your CodePen embed tag. Default to <i>result</i><br>
<code>{% codepen https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result %}</code>
</dd>
<dt><code>preview</code></dt>
<dd>
<p>Change the codepen URL path from /pen/ to /pen/preview/ (or to /embed/preview/) to use codepen's Click-to-Load preview embed feature in the resulting iframe.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/preview/dyVMgBg %}</pre>
</dd>
<dt><code>height</code></dt>
<dd>
<p>Add height parameter to your CodePen embed tag and to the resulting iframe itself. Defaults to <i>600</i></p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 %}</pre>
</dd>
<dt><code>theme-id</code></dt>
<dd>
<p>Add theme-id parameter to your CodePen embed tag. The pen and theme-id must be from a codepen pro user to have an effect.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148 %}</pre>
</dd>
<dt><code>editable=true</code></dt>
<dd>
<p>Add editable=true parameter to your CodePen embed tag. Editable Embeds require more resources than non-editable Embeds. The pen must be from a codepen pro user to have an effect.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg editable=true %}</pre>
</dd>
<dt><code>multiple-params</code></dt>
<dd>
<p>Add multiple parameters to your CodePen embed tag.</p>
<pre>{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 default-tab=css,result editable=true %}</pre>
</dd>
</dl>
<h3>Kotlin Playground</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>

View file

@ -7,6 +7,21 @@ RSpec.describe CodepenTag, type: :liquid_tag do
let(:codepen_team_private_link) { "https://codepen.io/team/codepen/pen/fb02c34281cb08966ec44b4e1ae22bc3" }
let(:codepen_team_link) { "https://codepen.io/team/keyframers/pen/ZMRMEw" }
let(:codepen_link_with_default_tab) { "https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result" }
let(:codepen_link_with_theme_id) { "https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148" }
let(:codepen_link_with_preview_indicator) { "https://codepen.io/propjockey/pen/preview/dyVMgBg" }
let(:codepen_link_with_embed_path) { "https://codepen.io/propjockey/embed/dyVMgBg" }
let(:codepen_link_with_embed_preview_path) { "https://codepen.io/propjockey/embed/preview/dyVMgBg" }
let(:codepen_link_with_height_param) { "https://codepen.io/propjockey/pen/dyVMgBg height=300" }
let(:codepen_link_with_editable_true) { "https://codepen.io/propjockey/pen/dyVMgBg editable=true" }
let(:codepen_link_with_multiple_params) do
"https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148 default-tab=js,result height=250 editable=true"
end
let(:codepen_link_with_preview_and_params) do
"https://codepen.io/propjockey/pen/preview/dyVMgBg theme-id=40148 default-tab=js,result"
end
let(:codepen_link_with_embed_path_and_params) do
"https://codepen.io/propjockey/embed/dyVMgBg theme-id=40148 default-tab=js,result"
end
xss_links = %w(
//evil.com/?codepen.io
@ -84,6 +99,113 @@ RSpec.describe CodepenTag, type: :liquid_tag do
end.not_to raise_error
end
it "accepts codepen link with a theme-id parameter" do
expect do
generate_new_liquid(codepen_link_with_theme_id)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_theme_id)
expect(liquid.render).to include("<iframe")
.and include('src="https://codepen.io/propjockey/embed/dyVMgBg?height=600&theme-id=40148')
end
it "accepts codepen link with pen/preview in the url" do
expect do
generate_new_liquid(codepen_link_with_preview_indicator)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_preview_indicator)
expect(liquid.render).to include("<iframe")
.and include('src="https://codepen.io/propjockey/embed/preview/dyVMgBg')
end
it "accepts codepen link with embed path in the url" do
expect do
generate_new_liquid(codepen_link_with_embed_path)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_embed_path)
expect(liquid.render).to include("<iframe")
.and include('src="https://codepen.io/propjockey/embed/dyVMgBg')
end
it "accepts codepen link with embed/preview in the url" do
expect do
generate_new_liquid(codepen_link_with_embed_preview_path)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_embed_preview_path)
expect(liquid.render).to include("<iframe")
.and include('src="https://codepen.io/propjockey/embed/preview/dyVMgBg')
end
it "accepts codepen link with a height parameter" do
expect do
generate_new_liquid(codepen_link_with_height_param)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_height_param)
expect(liquid.render).to include("<iframe")
.and include('height="300"')
.and include('src="https://codepen.io/propjockey/embed/dyVMgBg?height=300')
end
it "accepts codepen link with a editable=true parameter" do
expect do
generate_new_liquid(codepen_link_with_editable_true)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_editable_true)
expect(liquid.render).to include("<iframe")
.and include('src="https://codepen.io/propjockey/embed/dyVMgBg?height=600&editable=true')
end
it "accepts codepen link with multiple params" do
expect do
generate_new_liquid(codepen_link_with_multiple_params)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_multiple_params)
expect(liquid.render).to include("<iframe")
.and include('height="250"')
.and include(
'src="https://codepen.io/propjockey/embed/dyVMgBg?height=250&theme-id=40148&amp;default-tab=js,result&amp;editable=true',
)
end
it "accepts codepen link with preview and params" do
expect do
generate_new_liquid(codepen_link_with_preview_and_params)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_preview_and_params)
expect(liquid.render).to include("<iframe")
.and include(
'src="https://codepen.io/propjockey/embed/preview/dyVMgBg?height=600&theme-id=40148&amp;default-tab=js,result',
)
end
it "accepts codepen link with embed and params" do
expect do
generate_new_liquid(codepen_link_with_embed_path_and_params)
end.not_to raise_error
liquid = generate_new_liquid(codepen_link_with_embed_path_and_params)
expect(liquid.render).to include("<iframe")
.and include(
'src="https://codepen.io/propjockey/embed/dyVMgBg?height=600&theme-id=40148&amp;default-tab=js,result',
)
end
it "rejects XSS attempts" do
xss_links.each do |link|
expect { generate_new_liquid(link) }.to raise_error(StandardError)