Newbie Guide: How to Patch Styles and Themes

From Dreamwidth Notes
Jump to: navigation, search
Needs Update: This page has been found in need of an update. Information may be wrong or outdated!
Note: This supposes you already know how to make and commit changes in your dev environment. If you don't you should check other Getting Started articles first.

How do I file a new bug?

Open a new issue. Make sure to link to the dreamscapes entry/entries and to specify the default theme if it's a bug for a new style.


Where are style files?

  • core1.s2 and core2.s2 are in ~/dw/styles/
  • themes.s2 and layout.s2 files are in ~/dw/styles/STYLENAME/ and ~/dw/ext/dw-nonfree/styles/STYLENAME/
  • STYLENAME.pm style files are in ~/dw/cgi-bin/LJ/S2Theme/ and ~/dw/ext/dw-nonfree/cgi-bin/LJ/S2Theme/
  • S2Theme.pm is in ~/dw/cgi-bin/LJ/ and ~/dw/ext/dw-nonfree/cgi-bin/LJ/
N.B. this filed is called S2Theme_local.pm in nonfree.
  • s2layers-core2base.dat is in ~/dw/styles/
  • s2layers.dat is in ~/dw/styles/ and ~/dw/ext/dw-nonfree/styles/


Checking usage rights

Before you patch any style or theme, make sure Dreamwidth is allowed to use it as well as the images it contains if there are any:

  • We must have the submitter's Contributor Licensing Agreement before we can use their submission. If it's from someone who already has live styles or themes on the site, we already do. If the submission entry has the '-needs cla' tag, we don't. Otherwise, check the comments to see if they've already been asked about it.
  • If design and images have been made entirely from scratch by the designer who submitted the style or theme, they need to explicitly state they made them themselves in their submission entry.
  • If design or images haven't been made entirely from scratch by the designer who submitted the style or theme, they must mention where they came from and how they're licensed. We can only use designs and images if commercial use is allowed, use in website templates is allowed and storage on one own's server is allowed. You must also check if they may only be used as-is or if any kind of transformation (also called 'remix') is allowed, and how crediting must be done.

When in doubt, comment on the bug.


Dw-free or dw-nonfree?

Dreamwidth may be allowed to use designs and images on dreamwidth.org but may not be allowed to redistribute or sublicense them to other sites. If that's the case, elements need to go to dw-nonfree:

  • Styles go to dw-nonfree if Dreamwidth can use them but can't redistribute/sublicense them.
  • Themes go to dw-nonfree if they contain images Dreamwidth can use but can't redistribute/sublicense.
  • Themes go to dw-nonfree if the base style is already in dw-nonfree. This is the case for Transmogrified and Sunday Morning themes.

Adding a new style

Edit s2layers-core2base.dat or s2layers.dat

  • If this is a child of Tabula Rasa, add the following to s2layers-core2base.dat:
stylename/layout             layout(core2base/layout)    core2
stylename/themes             theme+                      stylename/layout
  • Otherwise, add:
stylename/layout       layout          core2
stylename/themes       theme+          stylename/layout


This page explains in detail how to make a style based on Tabula Rasa.

Edit S2Theme.pm

FIXME: still called _local in nonfree.

Scroll down to %default_themes and add the style and default theme:

layoutname => 'stylename/defaulttheme',


Create STYLENAME.pm

  • Create STYLENAME.pm in ~/dw/cgi-bin/LJ/S2Theme/ or ~/dw/ext/dw-nonfree/cgi-bin/LJ/S2Theme/.
  • Add:
package LJ::S2Theme::layoutname;
use base qw( LJ::S2Theme );
use strict;
 
sub layouts { ( "1" => "one-column", "1s" => "one-column-split", "2l" => "two-columns-left", "2r" => "two-columns-right", "3" => "three-columns-sides", "3r" => "three-columns-right", "3l" => "three-columns-left" ) }
sub layout_prop { "layout_type" }
 
1;
  • Remove layout options which don't apply to the style.
  • If the style has new Customize properties which can be sorted into existing categories (such as Page, Header, Module, Entry, etc.) you can add them to these categories using sub xxx_props:
sub module_props {
    my $self = shift;
    my @props = qw(
        new_property 1
        new_property 2
        new_property 3
        new_property 4
        new_property 5
    );
    return $self->_append_props( "module_props", @props );
}
  • Existing categories can be found in ~/dw/cgi-bin/LJ/S2Theme.pm
  • Note that, in Customize, they will be put after default properties, in the order you've listed them in in layout.s2.


Create the STYLENAME directory

Create a directory with the name of the style in ~/dw/styles/ or ~/dw/ext/dw-nonfree/styles/.


Create layout.s2

  • In the directory you've just created, create a file named layout.s2. Add:
layerinfo type = "layout";
layerinfo name = "stylename";
layerinfo redist_uniq = "stylename/layout";
layerinfo author_name = "someuser";
layerinfo lang = "en";
 
set layout_authors = [ { "name" => "someuser", "type" => "user" } ];
  • Make sure to respect the designer's wishes concerning capitalization and that layerinfo author_name and layout_authors match.
  • If the designer doesn't want their name to be displayed as a username or isn't a user, use this instead:
set layout_authors = [ { "name" => "someuser" } ];
  • If there are resources to credit, add them with:
set layout_resources = [ { "name" => "Name", "url" => "http://URL" } ];
  • Add the style code using headers for options (presentation, colors, fonts, images, modules, text, other) and for the stylesheet:
##===============================
## Stylesheet
##===============================
  • Then add all the CSS using:
    • function print_stylesheet () { } if the style is a child of Tabula Rasa.
    • function Page::print_default_stylesheet { } if the style isn't a child if Tabula Rasa.


Special case: custom properties

  • If the style has custom properties, first try to see if you can find existing ones in Core2 which would fit just as well.
  • If there aren't, make sure their names follow existing patterns: a) the property type (color, font, image, ...) b) the major area it applies to (header, entry, module,...) c) the precise element it applies to (text, link, background) and finally d) anything which might precise it further (alt, hover, active,...). The goal is to try to make it precise enough that anybody reading the code will know what it does without having to read the description.

Here are some examples:

color_header_navlinks_link_visited

color_module_link_background_hover

font_entry_datetime

A few exceptions to this rule:
  • image props mention whether they're background images or other sorts of images first ( e.g. image_background_entry_title, image_decoration_module_footer)
  • some custom properties can apply to an element wherever it may be displayed. In this case try to name this element as precisely as possible (e.g. font_titles for any H1, H2, H3, H4 headings or calendar_entryday_background if it applies to both the archive page calendar and the module calendar).
  • Sort them into existing groups (presentation, colors, fonts, images, modules, text, other) by appending _child to the group name. For example:
propgroup images_child {
    property string image_module_list { des = "Module list image"; }
}
  • Finally add a corresponding header (presentation, etc.).


Special case: custom module positions

  • If a module has more or fewer available positions than other modules, you can customize the sections it can be set to by using _override. For example:
property string module_navlinks_section_override {
    values = "none|(none)|header|Header|one|Group One|two|Group Two";
    grouped = 1;
}
 
set grouped_property_override = { "module_navlinks_section" => "module_navlinks_section_override" };
 
set module_navlinks_section = "header";
  • Don't forget to make sure it's printed correctly when set to every position, possibly by editing function Page::print() { }.


Special case: custom functions

  • If there is any function to be added, add a 'functions' header then briefly explain why each function had to be edited in a comment (e.g. to add an extra DIV, to add a new section for modules).


Create themes.s2

  • Still in the directory you've made, create a file named themes.s2.


Adding a new color theme

Themes go into the themes.s2 file corresponding to the style your theme is for. Once you've found it follow these steps.

Add theme info

  • First, make sure to add the theme code in the right place: themes should be alphabetically sorted.
  • Then add the following lines with the correct information at the beginning of the theme. Note that blank spaces aren't allowed in #NEWLAYER and redist_uniq.
#NEWLAYER: stylename/themename
layerinfo type = "theme";
layerinfo name = "Theme Name";
layerinfo redist_uniq = "stylename/themename";
layerinfo author_name = "someuser";


Add designer credit

  • If the color theme author is not the style author, add this below the theme info, separated by a blank line:
set theme_authors = [ { "name" => "someuser", "type" => "user" } ];
  • Make sure to respect the designer's wishes concerning capitalization and that layerinfo author_name and theme_authors match.
  • If the designer doesn't want their name to be displayed as a username or isn't a user, use this instead:
set theme_authors = [ { "name" => "someuser" } ];


Add resource credit

  • If there are resources to credit, add them with:
set layout_resources = [ { "name" => "Name", "url" => "http://URL" } ];
  • If there were already resources credited in the style, you need to add them again or they'll be lost.


Add styling properties

  • Add the theme properties (colors, fonts, etc.) by sorting them by category then alphabetically within each category. Possible categories are: Presentation, Page Colors, Entry Colors, Module Colors, Fonts and Images, in this order.
  • Add headers to separate each category:
##===============================
## Page Colors
##===============================
  • In most cases, that's all there is to a theme and you can skip the next two sections.


Special case: images

  • Images go into ~/dw/htdocs/img/styles/ or ~/dw/ext/htdocs/img/styles/.
  • Check the /commons folder to see if they're already used in another style. Otherwise, create a folder named after the style and put them there. If necessary, edit their names to respect the following rules:
    • If there's only one image per theme, just name if after the theme: themename.xxx
    • If there are several images per theme, name them like this: themename_imagename.xxx. However, if the image isn't specific to one theme, simply use imagename.xxx.
  • In the theme, use folder_name/name.xxx as the image URL.


Special case: theme-specific CSS

  • If there's theme-specific CSS, add it in this function, after you've added all the properties:
##===============================
## Stylesheet
##===============================

function Page::print_theme_stylesheet() {
"""
CSS HERE
""";
}

Check and format your files

General rules

  • No tabs or trailing spaces.
  • No empty properties.
  • No hardcoded colors, fonts or text except shadows, :before/:after characters, colors in print_theme_stylesheet() if the designer has used a non-safe combination (color_page_text on color_entry_background instead of color_entry_text on color_entry_background ) or colors which aren't used elsewhere.
  • No redundant code.
  • Use shorthand for color codes whenever possible: #555 instead of #555555 and #abc instead of #aabbcc.
  • Fonts should be capitalized, and single-quoted if there are several words: 'News Gothic MT' instead of news gothic mt.
  • Each theme must be separated by two blank lines. Leave one blank line after the last theme in the file.


Format CSS

If there's CSS in your files you want it to be easily readable and editable while still as compact as possible.

  • Selectors should be listed in the order they're displayed in the source (as often as possible). Properties should be indented and alphabetized.
  • Leading zeros should be removed from decimals: .5em instead of 0.5em.
  • Selectors should be grouped whenever possible (although you sometimes need to favor what's comprehensible over what's economical).
    border: 1px solid $*color_module_border;
    border-top: none;
    list-style: square inside url($*image_list_bullet);
    margin: 2em .5em 1em;

instead of:

    border-bottom: 1px solid $*color_module_border;
    border-left: 1px solid $*color_module_border;
    border-right: 1px solid $*color_module_border;
    list-style-image: url($*image_list_bullet);
    list-style-position: inside;
    list-style-type: square;
    margin-bottom: 1em;
    margin-left: .5em;
    margin-right: .5em;
    margin-top: 2em;
  • Remove gratuitous specificity such as div.entry instead of .entry. Inserting .DIV and .SPAN when they're not needed makes it harder to override selectors and can cause conflicts or bugs down the line. Compare:
.entry-content {
background: blue;
}
 
div.entry-content {
background: red;
}
 
.entry .entry-content {
background: green;
}
 
div.entry div.entry-content {
background: yellow;
}


  • On the other hand, !important are to be avoided whenever possible. In this case, adding specificity to your selector is a good idea.
  • In styles only, add style name and style author at the top of the stylesheet and use comment headers to separate sections:
/* Style Name
/* by style author
******************************/
 
/* Modules
******************************/
 
.module {
    margin: 2em .5em;
    padding: 2em;
}


Test, test and test

  • On your test account, check colors on all pages. Don't forget hover and visited links, comment subjects, bottom links, reply boxes and drop-down menus on comment pages, pagination links, contextual pop-ups, the navigation strip, blockquotes in entries and comments if these have been customized. Also make sure make sure everything is correctly listed and named in Customize.
Tip: it is generally a good idea to set up a test account for this purpose with entries with metadata, links, large images, long subjects, short content, non-square icons as well as entries with lots of comments, collapsed comments, etc.
  • For styles, you need to do even more thorough checking and anticipate on what users and other designers could change: the style must not only work with the original set of themes but also with dark on light themes, backgrounds where the original designer didn't set one, etc. It must work with all types of supported page set-ups, on all pages, with all sorts of entries and comments, and do so in various screen resolutions and font sizes. It must also work on community journals.
N.B. Also see the list of required features in [info]dreamscapes.


Preview pictures

Preview pics go into ~/dw/htdocs/img/customize/previews/STYLENAME/ or ~/dw/ext/dw-nonfree/htdocs/img/customize/previews/STYLENAME/. If you can't do them it's no big deal: simply mention it on the bug so that someone can do them for you or ask for help at [info]dreamscapes.


Requirements

  • Previews pics should be 150x114 pixels exactly, saved as color-indexed .PNGs without any color profile.
  • Preview pictures are screenshots of the Recent Pages of your test account in a big enough font size (16px for example). They generally show one or two dummy entries with dummy titles and a generic Dreamwidth icon (or the no-userpic default graphic), few sidebar modules and no footer modules. The navigation strip shouldn't be visible.
N.B. In Mozilla Firefox, you can use Dummy Lipsum to generate dummy text and CheckFox to uncheck several modules at once.


How to take a screenshot

  • It is best if you take your screenshot when your browser window is set to 1280x973 pixels as this will resize to 150x114 nicely. If you have a smaller resolution you can of course set it to whatever fits your screen and will be easily resizable to 150x114.
  • In Google Chrome:
    • Window Resizer will make your browser window a specified size. Especially useful, if you set "screen type" to "mobile device" then the content window is made to the specified size.
    • Screen Capture will take screen shots of the contents of a browser window. A bit buggy but does the job.


How to use ImageMagick to resize and sharpen

  • Once your screenshot is already the right aspect ratio, this command will resize it, sharpen it and convert it to the right format:
convert -resize '150x114' -sharpen 25 +dither -type Palette $inputfilename png8:$outputfilename


  • You can also make this into a script:
 #!/bin/bash
 for f in *.png; do
      convert -resize '150' -sharpen 25 +dither -type Palette "$f" png8:"$f"
 done


  • This version also checks if any of the files have already been done (so doesn't do them again) and prints out the names of the files it resizes:
 #!/bin/bash
 
 echo "  Creating Dreamwidth previews..."
 
 for f in *.png; do
 
     w=$(identify -format "%w" "$f")
     h=$(identify -format "%h" "$f")
     t=$(identify -format "%r" "$f")
     c=$(identify -format "%k" "$f")
 
     if [ $w -ne 150 ] || [ $h -ne 114 ] || [ $t != "PseudoClassRGB" ] || [ $c -gt 256 ]; then 
         echo "    * $f"
         convert -resize '150' -sharpen 25 +dither -type Palette "$f" png8:"$f"
     fi
 
 done
 
 echo "  ... done"

How to crop, resize, and optimize via the commandline

This script will take screengrabs of any aspect ratio, and resize and crop them to the appropriate dimensions for previews. It will also palettize them, and run optimizations to get smaller files. It will /not/ crop out menus and browser borders, so taking screengrabs with an extension such as ScreenCapture or FireShot is recommended to save time cropping out extra stuff. It's also better to have an image longer than it is wide, so any cropping comes from the bottom of the image, and not the sides (which would crop layout elements) It can be run locally if you have Linux, and requires the imagemagick package (frequently installed by default), as well as pngcrush and pngnq. The DreamHack server has all three packages already installed.

Installing the script

1) Navigate to the folder where bash scripts live.

a. On Linux, check your distribution's docs for where this is. If you use a shell other than bash, this script won't work for you.

b. On a Dreamhack account, navigate to the top-level /bin folder (note: this is NOT /dw/bin).

2) Make a new blank file with the name of what you want the script command to be.

3) Add the text of the script (below) to the new file and save.

   #!/bin/bash
   for f in *.png; do
       convert -resize 150x114^ -gravity north -extent 150x114 -sharpen 25 +dither -type Palette "$f" png8:"out.png" &&
           pngnq -n 256 -s 1 -f out.png &&
           pngcrush -c 3 -bit_depth 8 -rem alla -brute out-nq8.png "$f" >/dev/null &&
           rm out.png out-nq8.png
   done


4) Modify permissions to make the script executable.

a. In a GUI file manager, right-click -> properties should have a permissions tab. Either check 'Allow executing file as a program' (common on Ubuntu-derived distributions), or, if given a (R)ead/(W)rite/e(X)ecute grid, all users should have read and execute permissions.

b. On the commandline, make sure you're within the folder with the file, then run 'chmod 755 yourfilename'.


Using the script

1) On the commandline, navigate to the folder where your original image files are.

2) Call the script by simply typing its name on the commandline and hitting enter. It will act on all pngs in the given folder.

NOTE: this script modifies the original files. If for some reason you want to keep the full-sized versions, make copies before running the script.


References