diff --git a/src/documentation.html b/src/documentation.html index c84752b..91d4568 100644 --- a/src/documentation.html +++ b/src/documentation.html @@ -1,7 +1,129 @@
-TODO: Write documentation +
+

Reading Railroad Diagrams

- +

The images generated by Regexper are commonly referred to as "Railroad Diagrams". These diagram are a straight-forward way to illustrate what can sometimes become very complicated processing in a regular expression, with nested looping and optional elements. The easiest way to read these diagrams to to start at the left and follow the lines to the right. If you encounter a branch, then there is the option of following one of multiple paths (and those paths can loop back to earlier parts of the diagram). In order for a string to successfully match the regular expression in a diagram, you must be able to fulfill each part of the diagram as you move from left to right and proceed through the entire diagram to the end.

+ +
+ +

As an example, this expression will match "Lions and tigers and bears. Oh my!" or the more grammatically correct "Lions, tigers, and bears. Oh my!" (with or without an Oxford comma). The diagram first matches the string "Lions"; you cannot proceed without that in your input. Then there is a choice between a comma or the string " and". No matter what choice you make, the input string must then contain " tigers" followed by an optional comma (your path can either go through the comma or around it). Finally the string must end with " and bears. Oh my!".

+ +
+

Basic parts of these diagrams

+ +

The simplest pieces of these diagrams to understand are the parts that match some specific bit of text without an options. They are: Literals, Escape sequences, and "Any charater".

+ +
+

Literals

+ +
+ +

Literals match an exact string of text. They're displayed in a light blue box, and the contents are quoted (to make it easier to see any leading or trailing whitespace).

+
+ +
+

Escape sequences

+ +
+ +

Escape sequences are displayed in a green box and contain a description of the type of character(s) they will match.

+
+ +
+

"Any character"

+ +
+ +

"Any character" is similar to an escape sequence. It matches any single character.

+
+
+ +
+

Character Sets

+ +
+ +

Character sets will match or not match a collection of individual characters. They are shown as a box containing literals and escape sequences. The label at the top indicates that the character set will match "One of" the contained items or "None of" the contained items.

+
+ +
+

Subexpressions

+ +
+ +

Subexpressions are indicated by a dotted outline around the items that are in the expression. Captured subexpressions are labeled with the group number they will be captured under. Positive and negative lookahead are labeled as such.

+
+ +
+

Alternation

+ +
+ +

Alternation provides choices for the regular experssion. It is indicated by the path for the expression fanning out into a number of choices.

+
+ +
+

Quantifiers

+ +

Quantifiers indicate if part of the expression should be repeated or optional. They are displayed similarly to Alternation, by the path through the diagram branching (and possibly looping back on itself). Unless indicated by an arrow on the path, the preferred path is to continue going straight.

+ +
+

Zero-or-more

+ +
+
Greedy quantifier
+
+ +
+
Non-greedy quantifier
+
+ +

The zero-or-more quantifier matches any number of repetitions of the pattern.

+
+ +
+

Required

+ +
+
Greedy quantifier
+
+ +
+
Non-greedy quantifier
+
+ +

The required quantifier matches one or more repetitions of the pattern. Note that it does not have the path that allows the pattern to be skipped like the zero-or-more quantifier.

+
+ +
+

Optional

+ +
+
Greedy quantifier
+
+ +
+
Non-greedy quantifier
+
+ +

The optional quantifier matches the pattern at most once. Note that it does not have the path that allows the pattern to loop back on itself like the zero-or-more or required quantifiers.

+
+ +
+

Range

+ +
+
Greedy quantifier
+
+ +
+
Non-greedy quantifier
+
+ +

The ranged quantifier specifies a number of times the pattern may be repeated. The two examples provided here both have a range of "{5,10}", the label for the looping branch indicates the number of times that branch may be followed. The values are one less than specified in the expression since the pattern would have to be matched once before repeating it is an option. So, for these examples, the pattern would be matched once and then the loop would be followed 4 to 9 times, for a total of 5 to 10 matches of the pattern.

+
+
+
diff --git a/src/js/main.js b/src/js/main.js index 5f491a8..d077ea0 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -14,11 +14,30 @@ import _ from 'lodash'; }); } - _.each(document.querySelectorAll('svg[data-expr]'), element => { - var parser = new Parser(); + _.each(document.querySelectorAll('figure[data-expr]'), element => { + var parser = new Parser(), + svg; - parser.parse(element.getAttribute('data-expr')) - .invoke('render', element, document.querySelector('#svg-styles').innerHTML) - .done(); + element.className = _.compact([element.className, 'loading']).join(' '); + element.innerHTML = [ + '', + '
', + '
', + '
', + '
', + element.innerHTML + ].join(''); + + svg = element.querySelector('svg'); + + setTimeout(() => { + parser.parse(element.getAttribute('data-expr')) + .invoke('render', svg, document.querySelector('#svg-styles').innerHTML) + .finally(() => { + element.className = _.without(element.className.split(' '), 'loading').join(' '); + element.removeChild(element.querySelector('.spinner')); + }) + .done(); + }, 1); }); }()); diff --git a/src/sass/main.scss b/src/sass/main.scss index fe55f28..af112d1 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -101,28 +101,143 @@ header { } } -.copy { - background-color: $tan; - padding: rhythm(1/2); +.spinner { + margin: 0 auto; + width: rhythm(2); + height: rhythm(2); + position: relative; + text-align: center; + + @include animation(rotate 3.0s infinite linear); + + div { + width: 40%; + height: 40%; + display: inline-block; + position: absolute; + border: 3px solid $green; + @include border-radius(50%); + + @include animation(bounce 2.0s infinite ease-in-out); + } + + :first-child { + top: 0; + } + + :last-child { + bottom: 0px; + @include animation-delay(-1.0s); + } } -.changelog { - dt { - font-weight: bold; - } +@include keyframes(rotate) { + 100% { @include transform(rotate(360deg)); } +} - dd { - &::before { - content: '\00BB'; - font-weight: bold; - margin-right: rhythm(1/2); - } - } +@include keyframes(bounce) { + 0%, 100% { @include transform(scale(0.0)); } + 50% { @include transform(scale(1.0)); } } #content { padding: rhythm(1); + .copy { + background-color: $tan; + padding: rhythm(1/2); + } + + .changelog { + dt { + font-weight: bold; + } + + dd { + &::before { + content: '\00BB'; + font-weight: bold; + margin-right: rhythm(1/2); + } + } + } + + .documentation { + h1 { + @include adjust-font-size-to($base-font-size * 2); + font-weight: bold; + } + + h2 { + @include adjust-font-size-to($base-font-size); + font-weight: bold; + } + + h3 { + @include adjust-font-size-to($base-font-size); + + &::before { + content: '\00BB'; + font-weight: bold; + margin-right: rhythm(1/4); + } + } + + h1, h2, h3 { + clear: both; + } + + h2, h3 { + margin-bottom: rhythm(1); + } + + section, div, p { + margin: rhythm(1) 0; + } + + figure { + line-height: 0; + background: $white; + margin: rhythm(1/4); + @include box-shadow; + + &.shift-right { + float: right; + margin-left: rhythm(1/2); + } + + &.shift-left { + float: left; + margin-right: rhythm(1/2); + } + + &.loading { + min-width: 100px; + + .spinner { + left: 50%; + margin-left: -24px; + } + + svg { + position: absolute; + top: -10000px; + } + } + + figcaption { + @include adjust-font-size-to($base-font-size); + background: $green; + font-weight: bold; + padding: 0 rhythm(1/4); + } + } + + section, div { + overflow: hidden; + } + } + .application { position: relative; @include clearfix; @@ -177,48 +292,9 @@ header { padding: rhythm(1/2) 0; display: none; - .spinner { - margin: 0 auto; - width: rhythm(2); - height: rhythm(2); - position: relative; - text-align: center; - - @include animation(rotate 3.0s infinite linear); - - div { - width: 40%; - height: 40%; - display: inline-block; - position: absolute; - border: 3px solid $green; - @include border-radius(50%); - - @include animation(bounce 2.0s infinite ease-in-out); - } - - :first-child { - top: 0; - } - - :last-child { - bottom: 0px; - @include animation-delay(-1.0s); - } - } - body.is-loading & { display: block; } - - @include keyframes(rotate) { - 100% { @include transform(rotate(360deg)); } - } - - @include keyframes(bounce) { - 0%, 100% { @include transform(scale(0.0)); } - 50% { @include transform(scale(1.0)); } - } } #progress {