Skip to content
Browse files

Merge pull request #1800 from lift/migration-script

Migration script/docs

Few things here:

 - Quick migration script that highlights things that
   aren't marked as deprecated in Lift 2.6 but behave
   significantly differently in Lift 3.0, as well as giving
   some instructions on how to port.
 - Fix up CSS selector transform docs, since they are
   relevant to the above migration (from bind to CSS
   selector transforms, specifically).
 - Add a quick LiftScreen migration doc for 2.6 to 3.0.
  • Loading branch information...
2 parents 4b0c2d2 + 3faec80 commit be37ed500c78ba4d8dc2d9096b165ca648d43ad6 @Shadowfiend Shadowfiend committed on GitHub Jun 17, 2016
Showing with 238 additions and 30 deletions.
  1. +33 −30 docs/css-selectors.adoc
  2. +167 −0 docs/migration/2.6-to-3.0-lift-screen.adoc
  3. +38 −0 scripts/check-2.6-to-3.0-migration.sh
View
63 docs/css-selectors.adoc
@@ -24,13 +24,14 @@ transforms it according to a set of rules, producing a final `NodeSeq` with all
of the transformations applied. This means a CSS Selector Transform is
ultimately simply a function with signature `(NodeSeq)=>NodeSeq`. CSS Selector
Transforms consist of three main components:
+
- The selector
- The subnode modification rule
- The transformation function
-///
- Nice to have: graphic that shows a selector transform pointing to each
-///
+////////////////////////////////////////////////////////////////////////////
+// Nice to have: graphic that shows a selector transform pointing to each //
+////////////////////////////////////////////////////////////////////////////
The details of each are provided below, but first let's look at some simple
examples of transforms that you can write with links. For all of these examples,
@@ -154,6 +155,7 @@ Benedict Cumberbatch
====
These examples show a few options:
+
- You can select by element name or by class name. More available selectors are
in the section below on <<available-selectors>>.
- You can set the body of an element, an attribute of an element, or even
@@ -184,8 +186,8 @@ Name selector: `@field-name`::
`<input name="username">`.
Element selector: `element-name`::
- The element selector matches any element of type `element-name`. For example,
- you can use `input` to match an element `<input type="text">`.
+ The element selector matches any element with node name `element-name`. For
+ example, you can use `input` to match an element `<input type="text">`.
Attribute selector: `an-attribute=a-value`::
The attribute selector matches any element whose attribute named
@@ -196,7 +198,7 @@ Universal selector: `*`::
The universal selector matches any element.
Root selector: `^`::
- The root selector matches elements at the root level of the NodeSeq being
+ The root selector matches elements at the root level of the `NodeSeq` being
transformed. For example, you can use `^` to match both the `header`
and `ul` elements in the HTML `<header id="page-header">...</header><ul
ng-model="user">...</ul>`.
@@ -206,8 +208,8 @@ Root selector: `^`::
In addition to the above base selectors, a few selectors are provided that are
useful shortcuts for special attributes:
-Data name attribute selector: `;name-data`::
- The data name attribute selector matches any element that has `name-data` as
+Data name attribute selector: `;custom-name`::
+ The data name attribute selector matches any element that has `custom-name` as
the value of its `data-name` attribute. For example, you can use `;user-info`
to match an element `<ul data-name="user-info">...</ul>`.
@@ -229,7 +231,7 @@ Set children rule: `*`::
example, `^ *` will set the children of all root elements to the results of
the transformation.
-Append to children rule: `*<` or `*+`::
+Append to children rule: `\*<` or `*+`::
The transformation result will be appended to the children of the matched
element(s). For example, `^ *+` will append the results of the transformation
to the end of the content of all root elements.
@@ -348,12 +350,12 @@ box by Lift:
fact, there is a `ClearNodes` function defined in `net.liftweb.util` that does
exactly this.]. Because CSS Selector Transforms are themselves
`NodeSeq=>NodeSeq` functions, you can nest them this way. For example, you
- can say `".user" #> { ".name *" #> user.name }`. With the markup
- `<li class="user"><p class="name">Person</p></li>`, this will first select
- the `li`, then pass it to the second transform which will select the `p`
- and set its value to the user's name. Then the second transform will return
- the `li` with the user's name set up, and the top-level transform will replace
- the original, unbound `li` with the new one.
+ can say `".user" #> { ".name *" #> user.name }`. Given the markup `<li
+ class="user"><p class="name">Person</p></li>`, this will first select the
+ `li`, then pass it to the second transform which will select the `p` and set
+ its value to the user's name. Then the second transform will return the `li`
+ with the user's name set up, and the top-level transform will replace the
+ original, unbound `li` with the new one.
`CanBind[Iterable[T]]`::
This is defined for most `T` values that `CanBind` is also defined for, and
@@ -377,10 +379,11 @@ Lift's selectors are not identical to CSS selectors. They're designed for speed
rather than for being featureful, and designed in the context of a full-featured
language rather than a limited language like CSS. One key difference is in how
you combine them. In CSS, you can use `>` to select direct children, `+` for
-direct siblings, etc. Lift only provides one combinator, the space: ` `. It
-works just like in CSS, applying to all descendants. So you can set up a selector
-`.user-form input [value]` and it will for setting the `href` attribute of all
-`input` elements that have some ancestorwith class `user-form` .
+direct siblings, etc. Lift only provides one combinator, the space. It works
+just like in CSS, checking all descendants of the elements matched by the
+select to the left against the selector on the right. So you can set up a
+selector `.user-form input [value]` and it will set the `href` attribute of all
+`input` elements that have some ancestor with class `user-form`.
Notably, you cannot select `form.user input [href]`, because you cannot check
multiple selectors on a single element. In practice, this is rarely needed for
@@ -425,19 +428,19 @@ should be applied and then applying them. So, you can do:
```
Beware, however, as `&` is not the same as `andThen`. To do this trickery, Lift
-will only transform a part of a node once, and it won't revisit it. Two
-transformations that apply to the same attribute for the same element, for
-example, will not both be applied. Additionally, if your transformation applies
-to the body of an element, like `a *`, the new children of the element will
-_not_ be transformed. Additionally, if you replace the element itself, e.g.
-with the selector `a`, none of the other transforms for that element will run.
+will only transform a part of a node once, and it won't revisit it. Specifically,
+two transformations that apply directly to the same element (not its descendants
+or attributes). Additionally, if your transformation applies to the body of an
+element, like `a *`, the new children of the element will _not_ be transformed.
+Additionally, if you replace the element itself, e.g. with the selector `a`,
+none of the other transforms for that element will run.
Thus, you will occasionally find yourself using `&` together with `andThen`; in
general you should default to `&` and switch to `andThen` when you need to in
order to apply a transform to the results of the previous one.
-== Macros and Strings
-
-Lift's CSS Selector Transforms can be used in two modes. Most basically, you
-can create a `String` with the appropriate selector and then specify the
-transformation you want to apply to matching blocks
+//== Macros and Strings
+//
+//Lift's CSS Selector Transforms can be used in two modes. Most basically, you
+//can create a `String` with the appropriate selector and then specify the
+//transformation you want to apply to matching blocks
View
167 docs/migration/2.6-to-3.0-lift-screen.adoc
@@ -0,0 +1,167 @@
+:idprefix:
+:idseparator: -
+:toc: right
+:toclevels: 2
+
+= Migrating `LiftScreen` from Lift 2.6 to Lift 3.0
+
+The 2.x series of Lift brought a lot of change and innovation. In particular,
+while it started with an approach based on the `bind` helper that transformed
+namespaced XHTML elements into the values that the developer wanted to display,
+it progressed to an HTML5-based approach built around CSS selector transforms.
+As of Lift 3.0, CSS selector transforms are the only supported transforms, so
+as to keep the core of the framework relatively lean and encourage proper HTML
+usage.
+
+One of the Lift components that leveraged the `bind`-style transforms heavily
+was `LiftScreen`. As of Lift 3.0, it's been replaced with what in Lift 2.6 was
+named `CssBoundLiftScreen`, which is a version of `LiftScreen` that uses CSS
+selector transforms instead of `bind`-style transforms. Following is a
+breakdown of the things you need to do if you were using `LiftScreen` and want
+to upgrade to Lift 3.0.
+
+== `formName`
+
+In Lift 3.0, you need to provide a `formName` to your screen. For the most
+straightforward compatibility with the current form implementation, you should
+be able to simply set it to "":
+
+[.lift-30]
+```scala
+ val formName = ""
+```
+
+// Something more about what formName is for would be good here.
+
+== Bind Points
+
+In the old `LiftScreen`, bind points were elements with the namespace `prefix`
+and various names, e.g. `wizard:fields` for the container of all fields. Lift
+3.0 instead looks for certain CSS classes in elements. Here's a mapping from
+old `wizard:*` elements to CSS classes:
+
+.Lift 2.6 wizard element to Lift 3.0 CSS class mapping
+|=========================
+| Lift 2.6 Element | Lift 3.0 CSS Class
+
+| `wizard:screen_info` | `screenInfo`
+
+| `wizard:screen_number` | `screenNumber`
+
+| `wizard:total_screens` | `totalScreens`
+
+| `wizard:wizard_top` | `wizardTop`
+
+| `wizard:screen_top` | `screenTop`
+
+| `wizard:errors` | `globalErrors`
+
+| `wizard:item` (within `errors`) | `error`
+
+| `wizard:fields` | `fields`
+
+| `wizard:line` | `fieldContainer`
+
+| `wizard:label` | `label`
+
+| `wizard:for` | unneeded (label is automatically given a `for` attribute)
+
+| `wizard:help` | `help`
+
+| `wizard:field_errors` | `errors`
+
+| `wizard:error` | `error`
+
+| `wizard:form` | `value`
+
+| `wizard:prev` | `prev`
+
+| `wizard:cancel` | `cancel`
+
+| `wizard:next` | `next`
+
+| `wizard:wizard_bottom` | `wizardBottom`
+
+| `wizard:screen_bottom` | `screenBottom`
+
+| `wizard:bind` | unnecessary (contents are put into the elements with appropriate classes)
+|=========================
+
+Generally speaking, you can annotate the container element or the element that
+will have a given value directly with the class of the content it should
+contain, rather than needing an extra container with the class like the old
+`wizard:*` elements. For example, where before you had:
+
+[.lift-26]
+.Lift 2.6 global error markup
+```html
+<wizard:errors>
+ <div>
+ <ul>
+ <wizard:item>
+ <li><wizard:bind></wizard:bind></li>
+ </wizard:item>
+ </ul>
+ </div>
+</wizard:errors>
+```
+
+In Lift 3.0, you can remove all the `wizard:*` elements and instead put the
+classes directly on the remaining elements:
+
+[.lift-30]
+.Lift 3.0 global error markup
+```html
+<div class="globalErrors">
+ <ul>
+ <li class="error">
+ placeholder text, will be replaced by the error message
+ </li>
+ </ul>
+</div>
+```
+
+In fact, you can even eliminate the top-level `div`, if you'd like, by putting
+the `globalErrors` class on the `ul`:
+
+[.lift-30]
+```html
+<ul class="globalErrors">
+ <li class="error">
+ placeholder text, will be replaced by the error message
+ </li>
+</ul>
+```
+
+If you don't like these class names, you can customize them by overriding the
+`cssClassBinding` that you want to use in your `LiftScreen` subclass and
+returning a new instance of `CssClassBinding` with the appropriate CSS classes
+set up:
+
+[.lift-30]
+.Dasherize class names
+```scala
+ protected override lazy val cssClassBinding = new CssClassBinding {
+ override val screenInfo = "screen-info"
+ override val screenNumber = "screen-number"
+ override val totalScreens = "total-screens"
+
+ override val wizardTop = "wizard-top"
+ override val screenTop = "screen-top"
+ override val wizardBottom = "wizard-bottom"
+ override val screenBottom = "screen-bottom"
+
+ override val globalErrors = "global-errors"
+ override val fieldContainer = "field-container"
+
+ }
+```
+
+Above, we create a new version of `CssClassBinding` that uses dashes instead of
+camel-case between words.
+
+== Further Help
+
+That's it! If you run into any issues porting your screen over to Lift 3.0's
+`LiftScreen`, please ask on the Lift mailing list and you should find willing
+helpers.
View
38 scripts/check-2.6-to-3.0-migration.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+LIFT_SCREEN_TEMPLATE=`find ./ -name "wizard-all.html"`
+LIFT_SCREEN_EXTENDS=`grep -E "extends +LiftScreen"`
+LIFT_SCREEN_WITH=`grep -E "with +LiftScreen"`
+
+if [[ -n "$LIFT_SCREEN_TEMPLATE" ]]; then
+ echo "You're likely using an outdated base LiftScreen template at:"
+ echo "$LIFT_SCREEN_TEMPLATE"
+ echo "Assuming you haven't changed it, you can replace it with the lift_basic version for"
+ echo "exactly the same result:"
+ echo "https://github.com/lift/lift_30_sbt/blob/master/lift_basic/src/main/webapp/templates-hidden/wizard-all.html"
+ echo "----------------------------------------------------------------------------------"
+fi
+
+if [[ -n $LIFT_SCREEN_EXTENDS ]] || [[ -n $LIFT_SCREEN_WITH ]]; then
+ echo "You're extending LiftScreen. LiftScreen as of Lift 3.0 is the equivalent of 2.6's"
+ echo "CssBoundLiftScreen. This means it binds using CSS selector transforms instead of"
+ echo "the Lift 2.x series's \`bind\` function, which no longer exists. See this document"
+ echo "for porting instructions:"
+ echo "https://github.com/lift/framework/docs/migration/2.6-to-3.0-lift-screen.adoc"
+ echo "Here are the uses of LiftScreen we found:"
+ [[ -n $LIFT_SCREEN_EXTENDS ]] && echo "$LIFT_SCREEN_EXTENDS"
+ [[ -n $LIFT_SCREEN_WITH ]] && echo "$LIFT_SCREEN_WITH"
+ echo "----------------------------------------------------------------------------------"
+fi
+
+BIND_USES=`grep -E "bind\("`
+
+if [[ -n $BIND_USES ]]; then
+ echo "You seem to be using Lift's bind helpers. These have been removed from Lift 3.0,"
+ echo "superseded by Lift's CSS selector transforms. You can port your application to CSS"
+ echo "selector transforms piecewise while still on Lift 2.6, as they are supported in"
+ echo "both versions. For a primer on CSS selector transforms, look at this document:"
+ echo "https://github.com/lift/framework/blob/master/docs/css-selectors.adoc"
+ echo ""
+ echo "If you find yourself with additional questions, please ask on the Lift mailing list"
+ echo "and you should find willing helpers."
+fi

0 comments on commit be37ed5

Please sign in to comment.
Something went wrong with that request. Please try again.