Adding documentation

This commit is contained in:
Jeff Avallone 2014-12-21 18:02:18 -05:00
parent a65820b4d5
commit 4bec717f84
3 changed files with 277 additions and 60 deletions

View File

@ -1,7 +1,129 @@
<div class="copy documentation">
TODO: Write documentation
<section>
<h1>Reading Railroad Diagrams</h1>
<svg data-expr="test?" xmlns="http://www.w3.org/2000/svg" version="1.1"></svg>
<p>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.</p>
<figure class="shift-right" data-expr="Lions(?: and|,) tigers,? and bears\. Oh my!"></figure>
<p>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!".</p>
<section>
<h2>Basic parts of these diagrams</h2>
<p>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".</p>
<div>
<h3>Literals</h3>
<figure class="shift-left" data-expr="A literal example"></figure>
<p>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).</p>
</div>
<div>
<h3>Escape sequences</h3>
<figure class="shift-left" data-expr="\w\x7f\u00bb\1\0"></figure>
<p>Escape sequences are displayed in a green box and contain a description of the type of character(s) they will match.</p>
</div>
<div>
<h3>"Any character"</h3>
<figure class="shift-left" data-expr="."></figure>
<p>"Any character" is similar to an escape sequence. It matches any single character.</p>
</div>
</section>
<section>
<h2>Character Sets</h2>
<figure class="shift-left" data-expr="[#a-z\n][^$0-9\b]"></figure>
<p>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.</p>
</section>
<section>
<h2>Subexpressions</h2>
<figure class="shift-left" data-expr="(example\s)(?=content)"></figure>
<p>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.</p>
</section>
<section>
<h2>Alternation</h2>
<figure class="shift-left" data-expr="one\s|two\W|three\t|four\n"></figure>
<p>Alternation provides choices for the regular experssion. It is indicated by the path for the expression fanning out into a number of choices.</p>
</section>
<section>
<h2>Quantifiers</h2>
<p>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.</p>
<div>
<h3>Zero-or-more</h3>
<figure class="shift-left" data-expr="(?:greedy)*">
<figcaption>Greedy quantifier</figcaption>
</figure>
<figure class="shift-left" data-expr="(?:non-greedy)*?">
<figcaption>Non-greedy quantifier</figcaption>
</figure>
<p>The zero-or-more quantifier matches any number of repetitions of the pattern.</p>
</div>
<div>
<h3>Required</h3>
<figure class="shift-left" data-expr="(?:greedy)+">
<figcaption>Greedy quantifier</figcaption>
</figure>
<figure class="shift-left" data-expr="(?:non-greedy)+?">
<figcaption>Non-greedy quantifier</figcaption>
</figure>
<p>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.</p>
</div>
<div>
<h3>Optional</h3>
<figure class="shift-left" data-expr="(?:greedy)?">
<figcaption>Greedy quantifier</figcaption>
</figure>
<figure class="shift-left" data-expr="(?:non-greedy)??">
<figcaption>Non-greedy quantifier</figcaption>
</figure>
<p>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.</p>
</div>
<div>
<h3>Range</h3>
<figure class="shift-left" data-expr="(?:greedy){5,10}">
<figcaption>Greedy quantifier</figcaption>
</figure>
<figure class="shift-left" data-expr="(?:non-greedy){5,10}?">
<figcaption>Non-greedy quantifier</figcaption>
</figure>
<p>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.</p>
</div>
</section>
</section>
</div>
<script src="/js/main.js" async defer></script>

View File

@ -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 = [
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"></svg>',
'<div class="spinner">',
'<div></div>',
'<div></div>',
'</div>',
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);
});
}());

View File

@ -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 {