diff --git a/app/liquid_tags/codepen_tag.rb b/app/liquid_tags/codepen_tag.rb index bd5535799..13035d75e 100644 --- a/app/liquid_tags/codepen_tag.rb +++ b/app/liquid_tags/codepen_tag.rb @@ -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) \ No newline at end of file diff --git a/app/views/pages/_editor_guide_text.html.erb b/app/views/pages/_editor_guide_text.html.erb index b7dee3de6..b4e834127 100644 --- a/app/views/pages/_editor_guide_text.html.erb +++ b/app/views/pages/_editor_guide_text.html.erb @@ -283,6 +283,36 @@
Add default-tab parameter to your CodePen embed tag. Defaults to result.
{% codepen https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result %}
+
+ 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.
+{% codepen https://codepen.io/propjockey/pen/preview/dyVMgBg %}
+ Add height parameter to your CodePen embed tag and to the resulting iframe itself. Defaults to 600
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 %}
+ 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.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148 %}
+ 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.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg editable=true %}
+ Add multiple parameters to your CodePen embed tag.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 default-tab=css,result editable=true %}
+ {% codepen https://codepen.io/twhite96/pen/XKqrJX default-tab=js,result %}
+
+ previewChange 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.
+{% codepen https://codepen.io/propjockey/pen/preview/dyVMgBg %}
+ heightAdd height parameter to your CodePen embed tag and to the resulting iframe itself. Defaults to 600
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 %}
+ theme-idAdd theme-id parameter to your CodePen embed tag. The pen and theme-id must be from a codepen pro user to have an effect.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg theme-id=40148 %}
+ editable=trueAdd 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.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg editable=true %}
+ multiple-paramsAdd multiple parameters to your CodePen embed tag.
+{% codepen https://codepen.io/propjockey/pen/dyVMgBg height=300 default-tab=css,result editable=true %}
+ To create a runnable kotlin snippet, create a Kotlin Snippet at https://play.kotlinlang.org
diff --git a/spec/liquid_tags/codepen_tag_spec.rb b/spec/liquid_tags/codepen_tag_spec.rb index 04f4e8511..87f610f20 100644 --- a/spec/liquid_tags/codepen_tag_spec.rb +++ b/spec/liquid_tags/codepen_tag_spec.rb @@ -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("