From ff7db9081e2f60c135fd5d5ff99deef2f2bb412b Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:18:35 -0800 Subject: [PATCH 1/7] AO3-7210: Migrated skins-creating.html help file to localized help controller view --- app/controllers/help_controller.rb | 3 + app/views/help/skins_creating.html.erb | 216 +++++++++++++++++++++++++ app/views/skins/_form.html.erb | 2 +- config/config.yml | 2 +- config/locales/views/en.yml | 67 ++++++++ config/routes.rb | 2 + public/help/skins-creating.html | 204 ----------------------- 7 files changed, 290 insertions(+), 206 deletions(-) create mode 100644 app/views/help/skins_creating.html.erb delete mode 100644 public/help/skins-creating.html diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index ddb6d67a53a..c5d742e71bf 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -7,4 +7,7 @@ def first_login def preferences_locale end + + def skins_creating + end end diff --git a/app/views/help/skins_creating.html.erb b/app/views/help/skins_creating.html.erb new file mode 100644 index 00000000000..1b04ecbcfb4 --- /dev/null +++ b/app/views/help/skins_creating.html.erb @@ -0,0 +1,216 @@ +
+
<%= t(".intro.header") %>
+
+

<%= t(".intro.description") %>

+
+ +
<%= t(".allowed_properties") %>
+
+

background, border, column, cue, flex, font, layer-background, + layout-grid, list-style, margin, marker, outline, overflow, padding, + page-break, pause, scrollbar, text, transform, transition

+
+
<%= t(".allowed_specific_properties") %>
+
+

-replace, -use-link-source, accelerator, accent-color, align-content, + align-items, align-self, alignment-adjust, alignment-baseline, + appearance, azimuth, baseline-shift, behavior, binding, bookmark-label, + bookmark-level, bookmark-target, bottom, box-align, box-direction, + box-flex, box-flex-group, box-lines, box-orient, box-pack, box-shadow, + box-sizing, caption-side, clear, clip, color, color-profile, + color-scheme, content, counter-increment, counter-reset, crop, cue, + cue-after, cue-before, cursor, direction, display, dominant-baseline, + drop-initial-after-adjust, drop-initial-after-align, + drop-initial-before-adjust, drop-initial-before-align, + drop-initial-size, drop-initial-value, elevation, empty-cells, filter, + fit, fit-position, float, float-offset, font, font-effect, + font-emphasize, font-emphasize-position, font-emphasize-style, + font-family, font-size, font-size-adjust, font-smooth, font-stretch, + font-style, font-variant, font-weight, grid-columns, grid-rows, + hanging-punctuation, height, hyphenate-after, hyphenate-before, + hyphenate-character, hyphenate-lines, hyphenate-resource, hyphens, + icon, image-orientation, image-resolution, ime-mode, include-source, + inline-box-align, justify-content, layout-flow, left, letter-spacing, + line-break, line-height, line-stacking, line-stacking-ruby, + line-stacking-shift, line-stacking-strategy, mark, mark-after, + mark-before, marks, marquee-direction, marquee-play-count, + marquee-speed, marquee-style, max-height, max-width, min-height, + min-width, move-to, nav-down, nav-index, nav-left, nav-right, nav-up, + opacity, order, orphans, page, page-policy, phonemes, pitch, + pitch-range, play-during, position, presentation-level, + punctuation-trim, quotes, rendering-intent, resize, rest, rest-after, + rest-before, richness, right, rotation, rotation-point, ruby-align, + ruby-overhang, ruby-position, ruby-span, size, speak, speak-header, + speak-numeral, speak-punctuation, speech-rate, stress, string-set, + tab-side, table-layout, target, target-name, target-new, + target-position, top, unicode-bibi, unicode-bidi, user-select, + vertical-align, visibility, voice-balance, voice-duration, + voice-family, voice-pitch, voice-pitch-range, voice-rate, voice-stress, + voice-volume, volume, white-space, white-space-collapse, widows, width, + word-break, word-spacing, word-wrap, writing-mode, z-index

+
+ +
<%= t(".skin_examples.header") %>
+
+

<%= t( + ".skin_examples.description_html", + public_skins_link: link_to(t(".skin_examples.public_skins"), skins_path) + ) %>

+
+ +
<%= t(".one_declaration_per_ruleset.header") %>
+
+

<%= t( + ".one_declaration_per_ruleset.description.one_declaration_html", + background_code: tag.code("background") + ) %>
+

+        .my-class {
+          background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%);
+          background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
+          background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
+        }
+      
+ <%= t(".one_declaration_per_ruleset.description.split_rulesets") %> +
+        .my-class { background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); }
+        .my-class { background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
+        .my-class { background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
+      
+

+
+ +
<%= t(".font_family.header") %>
+
+

<%= t( + ".font_family.description.separate_properties_html", + font_code: tag.code("font") + ) %> + font-size: 1.1em; font-weight: bold; font-family: Cambria, Constantia, Palatino, Georgia, serif;

+

<%= t( + ".font_family.description.font_names_html", + font_family_code: tag.code("font-family"), + web_safe_fonts_link: + link_to( + t(".font_family.description.web_safe_fonts"), + "https://www.w3schools.com/cssref/css_fonts_fallbacks.asp" + ) + ) %>

+

<%= t( + ".font_family.description.no_font_face_html", + cannot_bold: tag.strong(t(".font_family.description.cannot")), + font_face_code: tag.code("@font-face") + ) %>

+
+ +
<%= t(".custom_properties.header") %>
+
+

<%= t(".custom_properties.description.names") %>

+

<%= t( + ".custom_properties.description.accepting_properties_html", + font_family_code: tag.code("font-family"), + content_code: tag.code("content"), + var_code: tag.code("var()") + ) %>

+

<%= t(".custom_properties.description.availability_html", var_code: tag.code("var()")) %>

+
+ +
<%= t(".external_urls.header") %>
+
+

<%= t( + ".external_urls.description_html", + example_url_code: tag.code("url('https://example.com/my_awesome_image.jpg')") + ) %>

+
+ +
<%= t(".allowed_keywords.header") %>
+
+

<%= t( + ".allowed_keywords.description_html", + absolute_code: tag.code("absolute"), + bottom_code: tag.code("bottom"), + center_code: tag.code("center"), + underline_code: tag.code("underline") + ) %>

+
+ +
<%= t(".numeric_values.header") %>
+
+

<%= t( + ".numeric_values.description.precision_html", + various_units_link: + link_to( + t(".numeric_values.description.various_units"), + "https://w3schools.com/css/css_units.asp" + ) + ) %>
cm, em, ex, in, mm, pc, pt, px

+

<%= t(".numeric_values.description.em_unit_html", em_code: tag.code("em")) %>

+
+ +
<%= t(".colors.header") %>
+
+

<%= t( + ".colors.description_html", + black_hex_code: tag.code("#000000"), + black_rgb_code: tag.code("rgb(0,0,0)"), + black_rgba_code: tag.code("rgba(0,0,0,0)"), + common_color_names_link: + link_to( + t(".colors.common_color_names"), + "https://www.w3schools.com/colors/colors_names.asp" + ) + ) %>

+
+ +
<%= t(".scale.header") %>
+
+

<%= t( + ".scale.description_html", + transform_code: tag.code("transform"), + scale_numeric_value_code: tag.code("scale(#{t('.scale.numeric_value')})") + ) %>

+
+ +
<%= t(".comments.header") %>
+
+

<%= t(".comments.description") %>

+
+ +
<%= t(".css_basics.header") %>
+
+

<%= t( + ".css_basics.description.line_of_css_html", + example_css_code: tag.code("selector {property: value;}") + ) %>

+

<%= t( + ".css_basics.description.css_selectors_and_rules_html", + selector_bold: tag.strong(t(".css_basics.description.selector")), + body_tag_code: tag.code("body"), + h1_tag_code: tag.code("h1"), + property_bold: tag.strong("property"), + value_bold: tag.strong(t(".css_basics.description.value")) + ) %>

+

<%= t(".css_basics.description.examples_header") %>

+

+ +

<%= t(".css_basics.description.css_tutorials") %>

+

+
+ +
diff --git a/app/views/skins/_form.html.erb b/app/views/skins/_form.html.erb index 5db4940da76..27e3284570c 100755 --- a/app/views/skins/_form.html.erb +++ b/app/views/skins/_form.html.erb @@ -34,7 +34,7 @@
<%= ts('CSS') %> -

<%= f.label :css, ts('CSS') %> <%= link_to_help 'skins-creating' %>

+

<%= f.label :css, ts('CSS') %> <%= link_to_help_modal(help_skins_creating_path, t(".skins_creating_help_title")) %>

<%= f.text_area :css, :cols => 70, :class => 'large observe_textlength' %> <%= live_validation_for_field("skin_css", maximum_length: ArchiveConfig.CONTENT_MAX_DISPLAYED) %> diff --git a/config/config.yml b/config/config.yml index 2c04187451e..447e6004ba7 100644 --- a/config/config.yml +++ b/config/config.yml @@ -361,7 +361,7 @@ BANNED_MULTIMEDIA_SRCS: [] # Allowed CSS # # *** IMPORTANT: if you edit these values please also update the -# skins-creating.html file in public/help *** +# skins-creating.html.erb file in app/views/help *** # # the following properties and keywords will be ADDED to the default set allowed # in user-submitted CSS code, along with: diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml index 7a83d4b3831..8def73c71dc 100644 --- a/config/locales/views/en.yml +++ b/config/locales/views/en.yml @@ -1085,6 +1085,72 @@ en: description: This preference allows you to select your preferred language for email messages that the Archive sends to you. The templates for these messages are currently being updated and translated by our volunteers. This is a work in progress; not all messages will be available in languages other than English at this time. If the template for that email has not yet been translated to your language, it will be sent in English. header: Set preferred locale page_heading: Locale Preferences + skins_creating: + allowed_keywords: + description_html: We allow all standard CSS keyword values (e.g., %{absolute_code}, %{bottom_code}, %{center_code}, %{underline_code}, etc.). + header: Keywords + allowed_properties: We allow the following properties including all their variations (and shorthand values) + allowed_specific_properties: We also allow the following specific properties + colors: + common_color_names: the set of commonly-supported color names + description_html: You can specify colors using hex values (eg, %{black_hex_code} is black in hex) or with RGB or RGBA values (e.g., %{black_rgb_code} and %{black_rgba_code} both give you black). This may be safer since not all browsers will necessarily support all color names. However, color names are more readable and easier to remember, so we also allow color names. (We suggest you stick to %{common_color_names_link}.) + header: Colors + comments: + description: Comments are stripped from CSS. + header: Comments + css_basics: + description: + background_color_example_html: 'Inside any tags with the id "header", set the background color to purple: %{background_color_css_code}' + blink_example_html: 'Inside any tags with the class "meta", make the text blink: (we do not advise this) %{blink_css_code}' + css_getting_started_tutorial: Getting Started (CSS Tutorial) from MDN + css_intro_tutorial: CSS introduction tutorial + css_selectors_and_rules_html: The %{selector_bold} is either the name of an HTML tag (like %{body_tag_code} or %{h1_tag_code}), or it can be an id or class that has been set on a tag. The %{property_bold} is what you want to change in the contents of that tag (for instance the font size), and the %{value_bold} is what you want to set it to. + css_tutorials: 'Some useful CSS tutorials for more information:' + examples_header: 'Examples:' + font_size_example_html: 'Inside the "body" tag, set the font size slightly larger than the baseline: %{font_size_css_code}' + line_of_css_html: 'A line of CSS code looks pretty much like this: %{example_css_code}' + selector: selector + value: value + header: 'If you are new to CSS, here are the basics:' + custom_properties: + description: + accepting_properties_html: All properties except %{font_family_code} and %{content_code} accept the %{var_code} function as a value. We don't allow fallbacks. + availability_html: Custom properties and the %{var_code} function are only available for site skins, and won't work on work skins. + names: Custom property names can contain any combination of lowercase letters (a-z) in the English alphabet, numerals zero to nine (0-9), dashes (-), and underscores (_). They can't contain single (') or double (") quotation marks, or URLs. Any uppercase letters (A-Z) will be converted to lowercase. + header: Custom Properties (Variables) + external_urls: + description_html: We allow external image URLs (specified as %{example_url_code}) in JPG, GIF, and PNG formats. Please note, however, that skins using external images will not be approved for public use. + header: URLs + font_family: + description: + cannot: cannot + font_names_html: In the %{font_family_code} property, we allow you to specify any font with an alphanumeric name. You can (but don't have to) specify the name with single or double quotes around it, just make sure the quotes match. (e.g., 'Gill Sans' and "Gill Sans" are both fine; 'Gill Sans" won't work.) Keep in mind that a font has to be installed on the user's operating system to work. It's a good idea when specifying fonts to use fallbacks in case your first-choice font isn't available. See %{web_safe_fonts_link}. + no_font_face_html: We %{cannot_bold} allow the %{font_face_code} attribute. Sorry! If you have an uncommon font that you want to use in a skin you would like to share, we suggest adding a comment in the skin's "Description" field with a pointer to a place for users to download the font themselves, and using web-safe fonts as fallbacks. + separate_properties_html: Unfortunately, you cannot use the %{font_code} shorthand in your CSS. All font properties have to be specified separately, e.g., + web_safe_fonts: a set of web-safe fonts with fallbacks + header: Font and Font Family + intro: + description: 'Note that for security reasons, you can only use a limited set of CSS code: all other declarations and comments will be removed!' + header: You can create new skins for the Archive using our wizard, or by writing your own CSS (cascading style sheets) code + numeric_values: + description: + em_unit_html: 'PS: we highly encourage learning about and using %{em_code}, which lets you set things relative to the viewer''s current font size! It will make your layouts much more flexible and responsive to different browser/font settings.' + precision_html: 'You can specify numeric values up to two decimal places, either as percentages or in %{various_units_link}:' + various_units: various units + header: Numeric Values + one_declaration_per_ruleset: + description: + one_declaration_html: The CSS parser we use retains only one declaration for each property, meaning that rulesets like the following will have all but the last %{background_code} declaration removed (so your gradient would only show up in WebKit browsers). + split_rulesets: 'To avoid losing declarations with repeated properties, split each one into its own ruleset, like so:' + header: Use only one declaration per property per ruleset + scale: + description_html: You can specify scale (for the %{transform_code} property) as %{scale_numeric_value_code} where the numeric value can be specified up to two decimal places. + header: Scale + numeric_value: numeric value + skin_examples: + description_html: "%{public_skins_link} are visible and you can read their code and copy them to edit for your own use." + header: Look at other public skins for examples + public_skins: All approved public skins home: about: ao3: @@ -2259,6 +2325,7 @@ en: icon: Upload a preview (png, jpeg or gif) public: Apply to make public skin_type: Type + skins_creating_help_title: Creating skins title: Title revert_skin_form: revert_to_default: Revert to Default Skin diff --git a/config/routes.rb b/config/routes.rb index d41f9761074..17390e6ae89 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -636,12 +636,14 @@ %w[ first_login preferences_locale + skins_creating ].each do |action| get "/help/#{action}", to: "help##{action}" end # Redirects for moved help files get "/first_login_help", to: redirect("/help/first_login") + get "/help/skins-creating.html", to: redirect("/help/skins_creating") get 'search' => 'works#search' post 'support' => 'feedbacks#create', as: 'feedbacks' diff --git a/public/help/skins-creating.html b/public/help/skins-creating.html deleted file mode 100644 index fe670c918ec..00000000000 --- a/public/help/skins-creating.html +++ /dev/null @@ -1,204 +0,0 @@ -

-
You can create new skins for the Archive using our wizard, or by writing your own CSS (cascading style sheets) code
-
-

- Note that for security reasons, you can only use a limited set of CSS code: all other declarations and comments will be removed! -

-
- -
We allow the following properties including all their variations (and shorthand values)
-
-

- - background, border, column, cue, flex, font, layer-background, - layout-grid, list-style, margin, marker, outline, overflow, padding, - page-break, pause, scrollbar, text, transform, transition - -

-
-
We also allow the following specific properties
-
-

- - -replace, -use-link-source, accelerator, accent-color, align-content, - align-items, align-self, alignment-adjust, alignment-baseline, - appearance, azimuth, baseline-shift, behavior, binding, bookmark-label, - bookmark-level, bookmark-target, bottom, box-align, box-direction, - box-flex, box-flex-group, box-lines, box-orient, box-pack, box-shadow, - box-sizing, caption-side, clear, clip, color, color-profile, - color-scheme, content, counter-increment, counter-reset, crop, cue, - cue-after, cue-before, cursor, direction, display, dominant-baseline, - drop-initial-after-adjust, drop-initial-after-align, - drop-initial-before-adjust, drop-initial-before-align, - drop-initial-size, drop-initial-value, elevation, empty-cells, filter, - fit, fit-position, float, float-offset, font, font-effect, - font-emphasize, font-emphasize-position, font-emphasize-style, - font-family, font-size, font-size-adjust, font-smooth, font-stretch, - font-style, font-variant, font-weight, grid-columns, grid-rows, - hanging-punctuation, height, hyphenate-after, hyphenate-before, - hyphenate-character, hyphenate-lines, hyphenate-resource, hyphens, icon, - image-orientation, image-resolution, ime-mode, include-source, - inline-box-align, justify-content, layout-flow, left, letter-spacing, - line-break, line-height, line-stacking, line-stacking-ruby, - line-stacking-shift, line-stacking-strategy, mark, mark-after, - mark-before, marks, marquee-direction, marquee-play-count, - marquee-speed, marquee-style, max-height, max-width, min-height, - min-width, move-to, nav-down, nav-index, nav-left, nav-right, nav-up, - opacity, order, orphans, page, page-policy, phonemes, pitch, - pitch-range, play-during, position, presentation-level, - punctuation-trim, quotes, rendering-intent, resize, rest, rest-after, - rest-before, richness, right, rotation, rotation-point, ruby-align, - ruby-overhang, ruby-position, ruby-span, size, speak, speak-header, - speak-numeral, speak-punctuation, speech-rate, stress, string-set, - tab-side, table-layout, target, target-name, target-new, - target-position, top, unicode-bibi, unicode-bidi, user-select, - vertical-align, visibility, voice-balance, voice-duration, voice-family, - voice-pitch, voice-pitch-range, voice-rate, voice-stress, voice-volume, - volume, white-space, white-space-collapse, widows, width, word-break, - word-spacing, word-wrap, writing-mode, z-index - -

-
- -
Look at other public skins for examples
-
-

- All approved public skins are visible and you can read their code and copy them to edit for - your own use. -

-
- -
Use only one declaration per property per ruleset
-
-

- The CSS parser we use retains only one declaration for each property, meaning that rulesets like
-

-        .my-class {
-          background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%);
-          background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
-          background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
-        }
-      
- will have all but the last background declaration removed (so your gradient would only show up in WebKit browsers). To avoid losing declarations with repeated properties, split each one into its own ruleset, like so: -
-        .my-class { background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); }
-        .my-class { background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
-        .my-class { background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
-      
-

-
- -
Font and Font Family
-
-

- Unfortunately, you cannot use the font shorthand in your CSS. All font properties have to be specified separately, e.g., - font-size: 1.1em; font-weight: bold; font-family: Cambria, Constantia, Palatino, Georgia, serif; -

-

- In the font-family property, we allow you to specify any font with an alphanumeric name. - You can (but don't have to) specify the name with single or double quotes - around it, just make sure the quotes match. (e.g., 'Gill Sans' and "Gill Sans" are both fine; 'Gill Sans" won't work.) - Keep in mind that a font has to be installed on the user's operating system to work. It's a good idea when specifying fonts to use - fallbacks in case your first-choice font isn't available. - See a set of web-safe fonts with fallbacks. -

-

- We cannot allow the @font-face attribute. Sorry! If you have an uncommon font that you want to - use in a skin you would like to share, we suggest adding a comment in the skin's "Description" field with a pointer to a place for users - to download the font themselves, and using web-safe fonts as fallbacks. -

-
- -
Custom Properties (Variables)
-
-

- Custom property names can contain any combination of lowercase letters (a-z) in the English alphabet, numerals zero to nine (0-9), dashes (-), and underscores (_). They can't contain single (') or double (") quotation marks, or URLs. Any uppercase letters (A-Z) will be converted to lowercase. -

-

- All properties except font-family and content accept the var() function as a value. We don't allow fallbacks. -

-

- Custom properties and the var() function are only available for site skins, and won't work on work skins. -

-
- -
URLs
-
-

- We allow external image URLs (specified as url('https://example.com/my_awesome_image.jpg')) in JPG, GIF, and PNG formats. - Please note, however, that skins using external images will not be approved for public use. -

-
- -
Keywords
-
-

- We allow all standard CSS keyword values (e.g., absolute, bottom, center, underline, etc.). -

-
- -
Numeric Values
-
-

- You can specify numeric values up to two decimal places, either as percentages or in various units:
- cm, em, ex, in, mm, pc, pt, px -

-

- PS: we highly encourage learning about and using em, which lets you set things relative to the viewer's current font size! - It will make your layouts much more flexible and responsive to different browser/font settings. -

-
- -
Colors
-
-

- You can specify colors using hex values (eg, #000000 is black in hex) or with RGB or RGBA values (e.g., rgb(0,0,0) and rgba(0,0,0,0) both give you black). - This may be safer since not all browsers will necessarily support all color names. However, color names are more - readable and easier to remember, so we also allow color names. (We suggest you stick to - the set of commonly-supported color names.) -

-
- -
Scale
-
-

- You can specify scale (for the transform property) as scale(numeric value) where the numeric value can be - specified up to two decimal places. -

-
- -
Comments
-
-

Comments are stripped from CSS.

-
- -
If you are new to CSS, here are the basics:
-
-

- A line of CSS code looks pretty much like this: selector {property: value;} -

-

- The selector is either the name of an HTML tag (like body or h1), - or it can be an id or class that has been set on a tag. - The property is what you want to change in the contents of that tag (for instance the font size), - and the value is what you want to set it to. -

-

- Examples: -

    -
  • Inside the "body" tag, set the font size slightly larger than the baseline: body {font-size: 1.1em;}
  • -
  • Inside any tags with the id "header", set the background color to purple: #header {background-color: purple}
  • -
  • Inside any tags with the class "meta", make the text blink: (we do not advise this) .meta {font-style: blink}
  • -
-

- -

- Some useful CSS tutorials for more information: -

-

-
- -
From 6237fd5827b1907f12973b27fc8609fe94ba6512 Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:01:08 -0800 Subject: [PATCH 2/7] fix app/views/skins/_form.html.erb for lint --- app/views/skins/_form.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/skins/_form.html.erb b/app/views/skins/_form.html.erb index 27e3284570c..65ec30160da 100755 --- a/app/views/skins/_form.html.erb +++ b/app/views/skins/_form.html.erb @@ -34,7 +34,7 @@
<%= ts('CSS') %> -

<%= f.label :css, ts('CSS') %> <%= link_to_help_modal(help_skins_creating_path, t(".skins_creating_help_title")) %>

+

<%= f.label :css, ts("CSS") %> <%= link_to_help_modal(help_skins_creating_path, t(".skins_creating_help_title")) %>

<%= f.text_area :css, :cols => 70, :class => 'large observe_textlength' %> <%= live_validation_for_field("skin_css", maximum_length: ArchiveConfig.CONTENT_MAX_DISPLAYED) %> From b3aa2c7998d441e847ecf86324081d0c718f633d Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:05:06 -0800 Subject: [PATCH 3/7] fix app/views/skins/_form.html.erb for lint again --- app/views/skins/_form.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/skins/_form.html.erb b/app/views/skins/_form.html.erb index 65ec30160da..22c6684ca52 100755 --- a/app/views/skins/_form.html.erb +++ b/app/views/skins/_form.html.erb @@ -34,7 +34,7 @@

<%= ts('CSS') %> -

<%= f.label :css, ts("CSS") %> <%= link_to_help_modal(help_skins_creating_path, t(".skins_creating_help_title")) %>

+

<%= f.label :css, t(".css") %> <%= link_to_help_modal(help_skins_creating_path, t(".skins_creating_help_title")) %>

<%= f.text_area :css, :cols => 70, :class => 'large observe_textlength' %> <%= live_validation_for_field("skin_css", maximum_length: ArchiveConfig.CONTENT_MAX_DISPLAYED) %> From 7020232dd21aabbffe0d05e05b9bc0ef79d8bb43 Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:21:08 -0800 Subject: [PATCH 4/7] added css translation --- config/locales/views/en.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml index 8def73c71dc..803aa582f31 100644 --- a/config/locales/views/en.yml +++ b/config/locales/views/en.yml @@ -2327,6 +2327,7 @@ en: skin_type: Type skins_creating_help_title: Creating skins title: Title + css: CSS revert_skin_form: revert_to_default: Revert to Default Skin wizard_form: From c4864d44e8e862ee5acba3e4a9d0721baf10b625 Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:31:10 -0800 Subject: [PATCH 5/7] normalize --- config/locales/views/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml index 803aa582f31..f4e962178eb 100644 --- a/config/locales/views/en.yml +++ b/config/locales/views/en.yml @@ -2321,13 +2321,13 @@ en: confirm_delete: confirm_html: Are you sure you want to delete the skin "%{skin_title}"? form: + css: CSS description: Description icon: Upload a preview (png, jpeg or gif) public: Apply to make public skin_type: Type skins_creating_help_title: Creating skins title: Title - css: CSS revert_skin_form: revert_to_default: Revert to Default Skin wizard_form: From 8835f7c49c7ace54ea6a80305038e62c80d52253 Mon Sep 17 00:00:00 2001 From: Hunter Smith <1946720+hunternet93@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:11:58 -0800 Subject: [PATCH 6/7] reverted .one_declaration_per_ruleset.description changes to match source exactly --- app/views/help/skins_creating.html.erb | 11 +++++------ config/locales/views/en.yml | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/views/help/skins_creating.html.erb b/app/views/help/skins_creating.html.erb index 1b04ecbcfb4..5f77c33439f 100644 --- a/app/views/help/skins_creating.html.erb +++ b/app/views/help/skins_creating.html.erb @@ -61,17 +61,16 @@

<%= t(".one_declaration_per_ruleset.header") %>

<%= t( - ".one_declaration_per_ruleset.description.one_declaration_html", - background_code: tag.code("background") - ) %>
-

+             ".one_declaration_per_ruleset.description_html",
+             repeated_declarations_css_code: tag.code(tag.pre(%{
         .my-class {
           background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%);
           background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
           background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);
         }
-      
- <%= t(".one_declaration_per_ruleset.description.split_rulesets") %> + })), + background_code: tag.code("background") + ) %>
         .my-class { background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); }
         .my-class { background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml
index f4e962178eb..ed22b869996 100644
--- a/config/locales/views/en.yml
+++ b/config/locales/views/en.yml
@@ -1139,9 +1139,7 @@ en:
           various_units: various units
         header: Numeric Values
       one_declaration_per_ruleset:
-        description:
-          one_declaration_html: The CSS parser we use retains only one declaration for each property, meaning that rulesets like the following will have all but the last %{background_code} declaration removed (so your gradient would only show up in WebKit browsers).
-          split_rulesets: 'To avoid losing declarations with repeated properties, split each one into its own ruleset, like so:'
+        description_html: 'The CSS parser we use retains only one declaration for each property, meaning that rulesets like %{repeated_declarations_css_code} will have all but the last %{background_code} declaration removed (so your gradient would only show up in WebKit browsers). To avoid losing declarations with repeated properties, split each one into its own ruleset, like so:'
         header: Use only one declaration per property per ruleset
       scale:
         description_html: You can specify scale (for the %{transform_code} property) as %{scale_numeric_value_code} where the numeric value can be specified up to two decimal places.

From 7a9394dfd9730faffb70e6817b93b855250b2905 Mon Sep 17 00:00:00 2001
From: Hunter Smith <1946720+hunternet93@users.noreply.github.com>
Date: Sun, 1 Feb 2026 19:09:19 -0800
Subject: [PATCH 7/7] Updates per review

---
 app/views/help/skins_creating.html.erb | 214 +++++++++++++------------
 config/config.yml                      |   2 +-
 config/locales/views/en.yml            |   8 +-
 3 files changed, 118 insertions(+), 106 deletions(-)

diff --git a/app/views/help/skins_creating.html.erb b/app/views/help/skins_creating.html.erb
index 5f77c33439f..2375ad9da14 100644
--- a/app/views/help/skins_creating.html.erb
+++ b/app/views/help/skins_creating.html.erb
@@ -6,13 +6,19 @@
 
   
<%= t(".allowed_properties") %>
-

background, border, column, cue, flex, font, layer-background, +

+ + background, border, column, cue, flex, font, layer-background, layout-grid, list-style, margin, marker, outline, overflow, padding, - page-break, pause, scrollbar, text, transform, transition

+ page-break, pause, scrollbar, text, transform, transition + +

<%= t(".allowed_specific_properties") %>
-

-replace, -use-link-source, accelerator, accent-color, align-content, +

+ + -replace, -use-link-source, accelerator, accent-color, align-content, align-items, align-self, alignment-adjust, alignment-baseline, appearance, azimuth, baseline-shift, behavior, binding, bookmark-label, bookmark-level, bookmark-target, bottom, box-align, box-direction, @@ -47,30 +53,31 @@ vertical-align, visibility, voice-balance, voice-duration, voice-family, voice-pitch, voice-pitch-range, voice-rate, voice-stress, voice-volume, volume, white-space, white-space-collapse, widows, width, - word-break, word-spacing, word-wrap, writing-mode, z-index

+ word-break, word-spacing, word-wrap, writing-mode, z-index + +

<%= t(".skin_examples.header") %>
-

<%= t( - ".skin_examples.description_html", - public_skins_link: link_to(t(".skin_examples.public_skins"), skins_path) - ) %>

+

+ <%= t(".skin_examples.description_html", + public_skins_link: link_to(t(".skin_examples.public_skins"), skins_path)) %> +

<%= t(".one_declaration_per_ruleset.header") %>
-

<%= t( - ".one_declaration_per_ruleset.description_html", - repeated_declarations_css_code: tag.code(tag.pre(%{ +

+ <%= t(".one_declaration_per_ruleset.description_html", + repeated_declarations_css_code: tag.br + tag.code(tag.pre(%{ .my-class { background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); } })), - background_code: tag.code("background") - ) %> + background_code: tag.code("background")) %>

         .my-class { background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); }
         .my-class { background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); }
@@ -81,93 +88,95 @@
 
   
<%= t(".font_family.header") %>
-

<%= t( - ".font_family.description.separate_properties_html", - font_code: tag.code("font") - ) %> - font-size: 1.1em; font-weight: bold; font-family: Cambria, Constantia, Palatino, Georgia, serif;

-

<%= t( - ".font_family.description.font_names_html", - font_family_code: tag.code("font-family"), - web_safe_fonts_link: - link_to( - t(".font_family.description.web_safe_fonts"), - "https://www.w3schools.com/cssref/css_fonts_fallbacks.asp" - ) - ) %>

-

<%= t( - ".font_family.description.no_font_face_html", - cannot_bold: tag.strong(t(".font_family.description.cannot")), - font_face_code: tag.code("@font-face") - ) %>

+

+ <%= t(".font_family.description.separate_properties_html", + font_code: tag.code("font"), + font_properties_css_code: tag.code("font-size: 1.1em; font-weight: bold; font-family: Cambria, Constantia, Palatino, Georgia, serif;")) %> +

+

+ <%= t(".font_family.description.font_names_html", + font_family_code: tag.code("font-family"), + web_safe_fonts_link: + link_to(t(".font_family.description.web_safe_fonts"), + "https://www.w3schools.com/cssref/css_fonts_fallbacks.asp")) %> +

+

+ <%= t(".font_family.description.no_font_face_html", + cannot_bold: tag.strong(t(".font_family.description.cannot")), + font_face_code: tag.code("@font-face")) %> +

<%= t(".custom_properties.header") %>

<%= t(".custom_properties.description.names") %>

-

<%= t( - ".custom_properties.description.accepting_properties_html", - font_family_code: tag.code("font-family"), - content_code: tag.code("content"), - var_code: tag.code("var()") - ) %>

+

+ <%= t(".custom_properties.description.accepting_properties_html", + font_family_code: tag.code("font-family"), + content_code: tag.code("content"), + var_code: tag.code("var()")) %> +

<%= t(".custom_properties.description.availability_html", var_code: tag.code("var()")) %>

<%= t(".external_urls.header") %>
-

<%= t( - ".external_urls.description_html", - example_url_code: tag.code("url('https://example.com/my_awesome_image.jpg')") - ) %>

+

+ <%= t(".external_urls.description_html", + example_url_code: tag.code("url('https://example.com/my_awesome_image.jpg')")) %> +

<%= t(".allowed_keywords.header") %>
-

<%= t( - ".allowed_keywords.description_html", - absolute_code: tag.code("absolute"), - bottom_code: tag.code("bottom"), - center_code: tag.code("center"), - underline_code: tag.code("underline") - ) %>

+

+ <%= t(".allowed_keywords.description_html", + absolute_code: tag.code("absolute"), + bottom_code: tag.code("bottom"), + center_code: tag.code("center"), + underline_code: tag.code("underline")) %> +

<%= t(".numeric_values.header") %>
-

<%= t( - ".numeric_values.description.precision_html", - various_units_link: - link_to( - t(".numeric_values.description.various_units"), - "https://w3schools.com/css/css_units.asp" - ) - ) %>
cm, em, ex, in, mm, pc, pt, px

+

+ <%= t(".numeric_values.description.precision_html", + various_units_link: + link_to(t(".numeric_values.description.various_units"), + "https://w3schools.com/css/css_units.asp"), + units_list_code: tag.br + tag.code(t(".numeric_values.description.units_list", + cm_code: "cm", + em_code: "em", + ex_code: "ex", + in_code: "in", + mm_code: "mm", + pc_code: "pc", + pt_code: "pt", + px_code: "px"))) %> +

<%= t(".numeric_values.description.em_unit_html", em_code: tag.code("em")) %>

<%= t(".colors.header") %>
-

<%= t( - ".colors.description_html", - black_hex_code: tag.code("#000000"), - black_rgb_code: tag.code("rgb(0,0,0)"), - black_rgba_code: tag.code("rgba(0,0,0,0)"), - common_color_names_link: - link_to( - t(".colors.common_color_names"), - "https://www.w3schools.com/colors/colors_names.asp" - ) - ) %>

+

+ <%= t(".colors.description_html", + black_hex_code: tag.code("#000000"), + black_rgb_code: tag.code("rgb(0,0,0)"), + black_rgba_code: tag.code("rgba(0,0,0,0)"), + common_color_names_link: link_to(t(".colors.common_color_names"), + "https://www.w3schools.com/colors/colors_names.asp")) %> +

<%= t(".scale.header") %>
-

<%= t( - ".scale.description_html", - transform_code: tag.code("transform"), - scale_numeric_value_code: tag.code("scale(#{t('.scale.numeric_value')})") - ) %>

+

+ <%= t(".scale.description_html", + transform_code: tag.code("transform"), + scale_numeric_value_code: tag.code("scale(#{t('.scale.numeric_value')})")) %> +

<%= t(".comments.header") %>
@@ -177,39 +186,40 @@
<%= t(".css_basics.header") %>
-

<%= t( - ".css_basics.description.line_of_css_html", - example_css_code: tag.code("selector {property: value;}") - ) %>

-

<%= t( - ".css_basics.description.css_selectors_and_rules_html", - selector_bold: tag.strong(t(".css_basics.description.selector")), - body_tag_code: tag.code("body"), - h1_tag_code: tag.code("h1"), - property_bold: tag.strong("property"), - value_bold: tag.strong(t(".css_basics.description.value")) - ) %>

-

<%= t(".css_basics.description.examples_header") %>

    -
  • <%= t( - ".css_basics.description.font_size_example_html", - font_size_css_code: tag.code("body {font-size: 1.1em;}") - ) %>
  • -
  • <%= t( - ".css_basics.description.background_color_example_html", - background_color_css_code: tag.code("#header {background-color: purple}") - ) %>
  • -
  • <%= t( - ".css_basics.description.blink_example_html", - blink_css_code: tag.code(".meta {font-style: blink}") - ) %>
  • +

    + <%= t(".css_basics.description.line_of_css_html", + example_css_code: tag.code("#{t('.css_basics.description.selector')} {#{t('.css_basics.description.property')}: #{t('.css_basics.description.value')};}")) %> +

    +

    + <%= t(".css_basics.description.css_selectors_and_rules_html", + selector_bold: tag.strong(t(".css_basics.description.selector")), + body_tag_code: tag.code("body"), + h1_tag_code: tag.code("h1"), + property_bold: tag.strong(t(".css_basics.description.property")), + value_bold: tag.strong(t(".css_basics.description.value"))) %> +

    +

    + <%= t(".css_basics.description.examples_header") %> +

    +
      +
    • + <%= t(".css_basics.description.font_size_example_html", + font_size_css_code: tag.code("body {font-size: 1.1em;}")) %> +
    • +
    • + <%= t(".css_basics.description.background_color_example_html", + background_color_css_code: tag.code("#header {background-color: purple}")) %> +
    • +
    • + <%= t(".css_basics.description.blink_example_html", + blink_css_code: tag.code(".meta {font-style: blink}")) %> +
    -

    <%= t(".css_basics.description.css_tutorials") %>

    -

diff --git a/config/config.yml b/config/config.yml index 447e6004ba7..9815631c2a8 100644 --- a/config/config.yml +++ b/config/config.yml @@ -361,7 +361,7 @@ BANNED_MULTIMEDIA_SRCS: [] # Allowed CSS # # *** IMPORTANT: if you edit these values please also update the -# skins-creating.html.erb file in app/views/help *** +# skins_creating.html.erb file in app/views/help *** # # the following properties and keywords will be ADDED to the default set allowed # in user-submitted CSS code, along with: diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml index ed22b869996..c7f401ad26d 100644 --- a/config/locales/views/en.yml +++ b/config/locales/views/en.yml @@ -1109,6 +1109,7 @@ en: examples_header: 'Examples:' font_size_example_html: 'Inside the "body" tag, set the font size slightly larger than the baseline: %{font_size_css_code}' line_of_css_html: 'A line of CSS code looks pretty much like this: %{example_css_code}' + property: property selector: selector value: value header: 'If you are new to CSS, here are the basics:' @@ -1126,7 +1127,7 @@ en: cannot: cannot font_names_html: In the %{font_family_code} property, we allow you to specify any font with an alphanumeric name. You can (but don't have to) specify the name with single or double quotes around it, just make sure the quotes match. (e.g., 'Gill Sans' and "Gill Sans" are both fine; 'Gill Sans" won't work.) Keep in mind that a font has to be installed on the user's operating system to work. It's a good idea when specifying fonts to use fallbacks in case your first-choice font isn't available. See %{web_safe_fonts_link}. no_font_face_html: We %{cannot_bold} allow the %{font_face_code} attribute. Sorry! If you have an uncommon font that you want to use in a skin you would like to share, we suggest adding a comment in the skin's "Description" field with a pointer to a place for users to download the font themselves, and using web-safe fonts as fallbacks. - separate_properties_html: Unfortunately, you cannot use the %{font_code} shorthand in your CSS. All font properties have to be specified separately, e.g., + separate_properties_html: Unfortunately, you cannot use the %{font_code} shorthand in your CSS. All font properties have to be specified separately, e.g., %{font_properties_css_code} web_safe_fonts: a set of web-safe fonts with fallbacks header: Font and Font Family intro: @@ -1135,7 +1136,8 @@ en: numeric_values: description: em_unit_html: 'PS: we highly encourage learning about and using %{em_code}, which lets you set things relative to the viewer''s current font size! It will make your layouts much more flexible and responsive to different browser/font settings.' - precision_html: 'You can specify numeric values up to two decimal places, either as percentages or in %{various_units_link}:' + precision_html: 'You can specify numeric values up to two decimal places, either as percentages or in %{various_units_link}: %{units_list_code}' + units_list: "%{cm_code}, %{em_code}, %{ex_code}, %{in_code}, %{mm_code}, %{pc_code}, %{pt_code}, %{px_code}" various_units: various units header: Numeric Values one_declaration_per_ruleset: @@ -2324,7 +2326,7 @@ en: icon: Upload a preview (png, jpeg or gif) public: Apply to make public skin_type: Type - skins_creating_help_title: Creating skins + skins_creating_help_title: Skins creating title: Title revert_skin_form: revert_to_default: Revert to Default Skin