Switching template rendering to use Handlebars

- Extracting the IE8 notice and SVG templates out into partials
- Moving changelog details into a data file
This commit is contained in:
Jeff Avallone 2015-10-31 13:12:14 -04:00
parent c90d09a1e0
commit dc72b2d4e4
19 changed files with 436 additions and 340 deletions

View File

@ -5,18 +5,14 @@ var path = require('path'),
buildPath = _.bind(path.join, path, buildRoot); buildPath = _.bind(path.join, path, buildRoot);
module.exports = { module.exports = {
titles: {
'_': 'Regexper',
'changelog.html': 'Regexper - Changelog',
'documentation.html': 'Regexper - Documentation',
'404.html': 'Regexper - Page Not Found'
},
buildRoot: buildRoot, buildRoot: buildRoot,
buildPath: buildPath, buildPath: buildPath,
templateFile: './template.html',
globs: { globs: {
other: './src/**/*.!(html|scss|js|peg)', other: './src/**/*.!(hbs|scss|js|peg)',
html: './src/**/*.html', templates: './src/**/*.hbs',
data: ['./lib/data/**/*.json', './lib/data/**/*.js'],
helpers: './lib/helpers/**/*.js',
partials: './lib/partials/**/*.hbs',
sass: './src/**/*.scss', sass: './src/**/*.scss',
js: ['./src/**/*.js', './src/**/*.peg'], js: ['./src/**/*.js', './src/**/*.peg'],
spec: './spec/**/*_spec.js' spec: './spec/**/*_spec.js'

View File

@ -1,4 +1,5 @@
var gulp = require('gulp'), var gulp = require('gulp'),
_ = require('lodash'),
notify = require('gulp-notify'), notify = require('gulp-notify'),
plumber = require('gulp-plumber'), plumber = require('gulp-plumber'),
config = require('./config'); config = require('./config');
@ -11,7 +12,13 @@ function errorHandler() {
gulp.task('default', ['server', 'docs'], function() { gulp.task('default', ['server', 'docs'], function() {
gulp.watch(config.globs.other, ['static']); gulp.watch(config.globs.other, ['static']);
gulp.watch([config.globs.html, config.templateFile, config.globs.sass], ['markup']); gulp.watch(_.flatten([
config.globs.templates,
config.globs.data,
config.globs.helpers,
config.globs.partials,
config.globs.sass
]), ['markup']);
gulp.watch(config.globs.js, ['browserify', 'docs']); gulp.watch(config.globs.js, ['browserify', 'docs']);
}); });
@ -53,23 +60,21 @@ gulp.task('static', function() {
}); });
gulp.task('markup', ['styles'], function() { gulp.task('markup', ['styles'], function() {
var wrap = require('gulp-wrap'), var hb = require('gulp-hb'),
path = require('path'), frontMatter = require('gulp-front-matter'),
fs = require('fs'); rename = require('gulp-rename');
return gulp.src(config.globs.html, { base: './src' }) return gulp.src(config.globs.templates)
.pipe(errorHandler()) .pipe(errorHandler())
.pipe(wrap({ src: config.templateFile }, { .pipe(frontMatter())
date: new Date().toISOString(), .pipe(hb({
title: function() { data: config.globs.data,
var root = path.join(this.file.cwd, this.file.base), helpers: config.globs.helpers,
file = path.relative(root, this.file.history[0]); partials: config.globs.partials,
bustCache: true,
return config.titles[file] || config.titles['_']; }))
}, .pipe(rename(function(path) {
svgStyles: fs.readFileSync(path.join(config.compass.css, 'svg.css'), { path.extname = '.html';
encoding: 'utf-8'
})
})) }))
.pipe(gulp.dest(config.buildRoot)); .pipe(gulp.dest(config.buildRoot));
}); });

93
lib/data/changelog.json Normal file
View File

@ -0,0 +1,93 @@
[
{
"label": "September 17, 2015 Release",
"changes": [
"Fixing styling of labels on repetitions",
"Fixing issue with vertical centering of alternation expressions that include empty expressions (see <a href=\"https://github.com/javallone/regexper-static/pull/16\">GitHub issue</a>)"
]
},
{
"label": "September 2, 2015 Release",
"changes": [
"Merging fix for error reporting from (see <a href=\"https://github.com/javallone/regexper-static/pull/15\">GitHub pull request</a>)"
]
},
{
"label": "July 5, 2015 Release",
"changes": [
"Updating Creative Commons license badge URL so it isn't pointing to a redirecting URL anymore"
]
},
{
"label": "June 22, 2015 Release",
"changes": [
"Tweaking buggy Firefox hash detection code based on JavaScript errors that were logged"
]
},
{
"label": "June 16, 2015 Release",
"changes": [
"Fixes issue with expressions containing a \"%\" not rendering in Firefox (see <a href=\"https://github.com/javallone/regexper-static/issues/12\">GitHub issue</a>)",
"Fixed rendering in IE that was causing \"--&gt;\" to display at the top of the page."
]
},
{
"label": "April 14, 2015 Release",
"changes": [
"Rendering speed improved. Most users will probably not see much improvement since logging data indicates that expressing rendering time is typically less than 1 second. Using the <a href=\"http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html\">RFC822 email regular expression</a> though shows a rendering speed improvement from ~120 seconds down to ~80 seconds.",
"Fixing a bug that would only occur when attempting to render an expression while another is in the process of rendering"
]
},
{
"label": "March 14, 2015 Release",
"changes": [
"Removing use of Q for promises in favor of \"native\" ES6 promises (even though they aren't quite native everywhere yet)"
]
},
{
"label": "March 13, 2015 Release",
"changes": [
"Fixes bug with numbering of nested subexpressions (see <a href=\"https://github.com/javallone/regexper-static/issues/7\">GitHub issue</a>)"
]
},
{
"label": "February 11, 2015 Release",
"changes": [
"Various adjustments to analytics: tracking expression rendering time and JS errors",
"Escape sequences that match to a specific character now display their hexadecimal code (actually done on January 25, but I forgot to update the changelog)",
"Fixing styling issue with header links (see <a href=\"https://github.com/javallone/regexper-static/issues/5\">GitHub issue</a>)"
]
},
{
"label": "December 30, 2014 Release",
"changes": [
"Fixing bug that prevented rendering empty subexpressions",
"Fixing minor styling bug when permalink is disabled",
"Cleaning up some duplicated styles and JS"
]
},
{
"label": "December 29, 2014 Release",
"changes": [
"Tweaking analytics data to help with addressing issues in deployed code (work will likely continue on this)",
"Added progress bars on the documentation page",
"Removed the loading spinner everywhere",
"Animated the progress bars"
]
},
{
"label": "December 26, 2014 Release",
"changes": [
"Freshened up design",
"Multiline regular expression input field (press Shift-Enter to render)",
"Added a changelog",
"Added documentation",
"All parsing and rendering happens client-side (using <a href=\"http://canopy.jcoglan.com/\">Canopy</a> and <a href=\"http://snapsvg.io/\">Snap.svg</a>)",
"Added Download link (not available in older browsers)",
"Added display of regular expression flags (ignore case, global, multiline)",
"Added indicator of quantifier greedy-ness",
"Various improvements to parsing of regular expression",
"Rendering of a regular expression can be canceled by pressing Escape"
]
}
]

1
lib/data/date.js Normal file
View File

@ -0,0 +1 @@
module.exports = new Date().toISOString();

7
lib/data/svg_styles.js Normal file
View File

@ -0,0 +1,7 @@
var fs = require('fs'),
path = require('path'),
config = require('../../config');
module.exports = fs.readFileSync(path.join(config.compass.css, 'svg.css'), {
encoding: 'utf-8'
})

5
lib/helpers/layouts.js Normal file
View File

@ -0,0 +1,5 @@
var layouts = require('handlebars-layouts');
module.exports.register = function(handlebars) {
layouts.register(handlebars);
};

View File

@ -0,0 +1,5 @@
<div id="deprecation-notice">
<h1>Regexper</h1>
<p>Your browser is no longer supported by the current version of Regexper. Upgrade your browser to the latest version, or visit <a href="http://old.regexper.com/">the old Regexper</a>.</p>
</div>

66
lib/partials/layout.hbs Normal file
View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Regexper{{#if file.frontMatter.title}} - {{file.frontMatter.title}}{{/if}}</title>
<meta name="description" content="Regular expression visualizer using railroad diagrams" />
<meta name="viewport" content="width=device-width" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="author" href="humans.txt" />
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Bangers&text=Regxpr" />
<link rel="stylesheet" href="/css/main.css" />
<!-- Built: {{date}} -->
</head>
<body>
<!--[if lte IE 8]>
{{> "ie8_notice"}}
<![endif]-->
<!--[if gt IE 8]> <!-->
<script type="text/html" id="svg-container-base">
{{> "svg_template"}}
</script>
<header>
<div class="logo">
<h1><a href="/">Regexper</a></h1>
<!-- n. One who regexpes -->
<span>You thought you only had two problems&hellip;</span>
</div>
<nav>
<ul>
<li>
<a class="oi with-text" data-glyph="list-rich" href="/changelog.html">Changelog</a>
</li>
<li>
<a class="oi with-text" data-glyph="document" href="/documentation.html">Documentation</a>
</li>
<li>
<a class="oi with-text" data-glyph="code" href="https://github.com/javallone/regexper-static">Source on GitHub</a>
</li>
</ul>
</nav>
</header>
<main id="content">
{{#block "body"}}{{/block}}
</main>
<footer>
{{#block "footer"}}
<ul class="inline-list">
<li>Created by <a href="mailto:jeff.avallone@gmail.com">Jeff Avallone</a></li>
<li>
Generated images licensed:
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" src="https://licensebuttons.net/l/by/3.0/80x15.png" /></a>
</li>
</ul>
{{/block}}
</footer>
<!-- <![endif]-->
</body>
</html>

View File

@ -0,0 +1,25 @@
<div class="svg">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
version="1.1">
<defs>
<style type="text/css">{{svg_styles}}</style>
</defs>
<metadata>
<rdf:RDF>
<cc:License rdf:about="http://creativecommons.org/licenses/by/3.0/">
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>
</div>
<div class="progress">
<div style="width:0;"></div>
</div>

View File

@ -18,10 +18,13 @@
"gulp-compass": "^2.0.4", "gulp-compass": "^2.0.4",
"gulp-connect": "^2.2.0", "gulp-connect": "^2.2.0",
"gulp-docco": "0.0.4", "gulp-docco": "0.0.4",
"gulp-front-matter": "^1.3.0",
"gulp-hb": "^2.6.5",
"gulp-notify": "^2.0.1", "gulp-notify": "^2.0.1",
"gulp-plumber": "^1.0.0", "gulp-plumber": "^1.0.0",
"gulp-rename": "^1.2.2",
"gulp-tap": "^0.1.3", "gulp-tap": "^0.1.3",
"gulp-wrap": "^0.11.0", "handlebars-layouts": "^3.1.2",
"jasmine-core": "^2.3.4", "jasmine-core": "^2.3.4",
"karma": "^0.13.14", "karma": "^0.13.14",
"karma-browserify": "^4.4.0", "karma-browserify": "^4.4.0",

17
src/404.hbs Normal file
View File

@ -0,0 +1,17 @@
---
title: Page Not Found
---
{{#extend "layout"}}
{{#content "body"}}
<div class="error copy">
<h1>404: Not Found</h1>
<blockquote>
Some people, when confronted with a problem, think<br/>
&ldquo;I know, I'll use regular expressions.&rdquo; Now they have two problems.
</blockquote>
<p>Apparently, you have three problems&hellip;because the page you requested cannot be found.</p>
</div>
{{/content}}
{{/extend}}

View File

@ -1,10 +0,0 @@
<div class="error copy">
<h1>404: Not Found</h1>
<blockquote>
Some people, when confronted with a problem, think<br/>
&ldquo;I know, I'll use regular expressions.&rdquo; Now they have two problems.
</blockquote>
<p>Apparently, you have three problems&hellip;because the page you requested cannot be found.</p>
</div>

17
src/changelog.hbs Normal file
View File

@ -0,0 +1,17 @@
---
title: Changelog
---
{{#extend "layout"}}
{{#content "body"}}
<div class="copy changelog">
<dl>
{{#each changelog}}
<dt>{{label}}</dt>
{{#each changes}}
<dd>{{{this}}}</dd>
{{/each}}
{{/each}}
</dl>
</div>
{{/content}}
{{/extend}}

View File

@ -1,58 +0,0 @@
<div class="copy changelog">
<dl>
<dt>September 17, 2015 Release</dt>
<dd>Fixing styling of labels on repetitions</dd>
<dd>Fixing issue with vertical centering of alternation expressions that include empty expressions (see <a href="https://github.com/javallone/regexper-static/pull/16">GitHub issue</a>)
<dt>September 2, 2015 Release</dt>
<dd>Merging fix for error reporting from (see <a href="https://github.com/javallone/regexper-static/pull/15">GitHub pull request</a>)
<dt>July 5, 2015 Release</dt>
<dd>Updating Creative Commons license badge URL so it isn't pointing to a redirecting URL anymore</dd>
<dt>June 22, 2015 Release</dt>
<dd>Tweaking buggy Firefox hash detection code based on JavaScript errors that were logged</dd>
<dt>June 16, 2015 Release</dt>
<dd>Fixes issue with expressions containing a "%" not rendering in Firefox (see <a href="https://github.com/javallone/regexper-static/issues/12">GitHub issue</a>)</dd>
<dd>Fixed rendering in IE that was causing "--&gt;" to display at the top of the page.</dd>
<dt>April 14, 2015 Release</dt>
<dd>Rendering speed improved. Most users will probably not see much improvement since logging data indicates that expressing rendering time is typically less than 1 second. Using the <a href="http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html">RFC822 email regular expression</a> though shows a rendering speed improvement from ~120 seconds down to ~80 seconds.</dd>
<dd>Fixing a bug that would only occur when attempting to render an expression while another is in the process of rendering</dd>
<dt>March 14, 2015 Release</dt>
<dd>Removing use of Q for promises in favor of "native" ES6 promises (even though they aren't quite native everywhere yet)</dd>
<dt>March 13, 2015 Release</dt>
<dd>Fixes bug with numbering of nested subexpressions (see <a href="https://github.com/javallone/regexper-static/issues/7">GitHub issue</a>)</dd>
<dt>February 11, 2015 Release</dt>
<dd>Various adjustments to analytics: tracking expression rendering time and JS errors</dd>
<dd>Escape sequences that match to a specific character now display their hexadecimal code (actually done on January 25, but I forgot to update the changelog)</dd>
<dd>Fixing styling issue with header links (see <a href="https://github.com/javallone/regexper-static/issues/5">GitHub issue</a>)</dd>
<dt>December 30, 2014 Release</dt>
<dd>Fixing bug that prevented rendering empty subexpressions</dd>
<dd>Fixing minor styling bug when permalink is disabled</dd>
<dd>Cleaning up some duplicated styles and JS</dd>
<dt>December 29, 2014 Release</dt>
<dd>Tweaking analytics data to help with addressing issues in deployed code (work will likely continue on this)</dd>
<dd>Added progress bars on the documentation page</dd>
<dd>Removed the loading spinner everywhere</dd>
<dd>Animated the progress bars</dd>
<dt>December 26, 2014 Release</dt>
<dd>Freshened up design</dd>
<dd>Multiline regular expression input field (press Shift-Enter to render)</dd>
<dd>Added a changelog</dd>
<dd>Added documentation</dd>
<dd>All parsing and rendering happens client-side (using <a href="http://canopy.jcoglan.com/">Canopy</a> and <a href="http://snapsvg.io/">Snap.svg</a>)</dd>
<dd>Added Download link (not available in older browsers)</dd>
<dd>Added display of regular expression flags (ignore case, global, multiline)</dd>
<dd>Added indicator of quantifier greedy-ness</dd>
<dd>Various improvements to parsing of regular expression</dd>
<dd>Rendering of a regular expression can be canceled by pressing Escape</dd>
</dl>
</div>

138
src/documentation.hbs Normal file
View File

@ -0,0 +1,138 @@
---
title: Documentation
---
{{#extend "layout"}}
{{#content "body"}}
<div class="copy documentation">
<section>
<h1>Reading Railroad Diagrams</h1>
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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>
{{/content}}
{{#content "footer" mode="append"}}
<script src="/js/main.js" async defer></script>
{{/content}}
{{/extend}}

View File

@ -1,129 +0,0 @@
<div class="copy documentation">
<section>
<h1>Reading Railroad Diagrams</h1>
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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 class="section">
<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>

32
src/index.hbs Normal file
View File

@ -0,0 +1,32 @@
{{#extend "layout"}}
{{#content "body"}}
<div class="application">
<form id="regexp-form">
<textarea id="regexp-input" autofocus="autofocus" placeholder="Enter JavaScript-style regular expression to display"></textarea>
<button type="submit">Display</button>
<ul class="inline-list">
<li class="download">
<a href="#" class="oi with-text" data-glyph="data-transfer-download" download="image.svg" type="image/svg+xml">Download</a>
</li>
<li class="permalink">
<a href="#" class="oi with-text" data-glyph="link-intact">Permalink</a>
</li>
</ul>
</form>
</div>
<div class="results">
<div id="error"></div>
<ul id="warnings"></ul>
<div id="regexp-render"></div>
</div>
{{/content}}
{{#content "footer" mode="append"}}
<script src="/js/main.js" async defer></script>
{{/content}}
{{/extend}}

View File

@ -1,25 +0,0 @@
<div class="application">
<form id="regexp-form">
<textarea id="regexp-input" autofocus="autofocus" placeholder="Enter JavaScript-style regular expression to display"></textarea>
<button type="submit">Display</button>
<ul class="inline-list">
<li class="download">
<a href="#" class="oi with-text" data-glyph="data-transfer-download" download="image.svg" type="image/svg+xml">Download</a>
</li>
<li class="permalink">
<a href="#" class="oi with-text" data-glyph="link-intact">Permalink</a>
</li>
</ul>
</form>
</div>
<div class="results">
<div id="error"></div>
<ul id="warnings"></ul>
<div id="regexp-render"></div>
</div>
<script src="/js/main.js" async defer></script>

View File

@ -1,92 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>${title()}</title>
<meta name="description" content="Regular expression visualizer using railroad diagrams" />
<meta name="viewport" content="width=device-width" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="author" href="humans.txt" />
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Bangers&text=Regxpr" />
<link rel="stylesheet" href="/css/main.css" />
<!-- Built: ${date} -->
</head>
<body>
<!--[if lte IE 8]>
<div id="deprecation-notice">
<h1>Regexper</h1>
<p>Your browser is no longer supported by the current version of Regexper. Upgrade your browser to the latest version, or visit <a href="http://old.regexper.com/">the old Regexper</a>.</p>
</div>
<![endif]-->
<!--[if gt IE 8]> <!-->
<script type="text/html" id="svg-container-base">
<div class="svg">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
version="1.1">
<defs>
<style type="text/css">${svgStyles}</style>
</defs>
<metadata>
<rdf:RDF>
<cc:License rdf:about="http://creativecommons.org/licenses/by/3.0/">
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
</svg>
</div>
<div class="progress">
<div style="width:0;"></div>
</div>
</script>
<header>
<div class="logo">
<h1><a href="/">Regexper</a></h1>
<!-- n. One who regexpes -->
<span>You thought you only had two problems&hellip;</span>
</div>
<nav>
<ul>
<li>
<a class="oi with-text" data-glyph="list-rich" href="/changelog.html">Changelog</a>
</li>
<li>
<a class="oi with-text" data-glyph="document" href="/documentation.html">Documentation</a>
</li>
<li>
<a class="oi with-text" data-glyph="code" href="https://github.com/javallone/regexper-static">Source on GitHub</a>
</li>
</ul>
</nav>
</header>
<main id="content">
${contents}
</main>
<footer>
<ul class="inline-list">
<li>Created by <a href="mailto:jeff.avallone@gmail.com">Jeff Avallone</a></li>
<li>
Generated images licensed:
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" src="https://licensebuttons.net/l/by/3.0/80x15.png" /></a>
</li>
</ul>
</footer>
<!-- <![endif]-->
</body>
</html>