From dc72b2d4e4552a9075b81ecbffed0365af67bb56 Mon Sep 17 00:00:00 2001 From: Jeff Avallone Date: Sat, 31 Oct 2015 13:12:14 -0400 Subject: [PATCH] Switching template rendering to use Handlebars - Extracting the IE8 notice and SVG templates out into partials - Moving changelog details into a data file --- config.js | 14 ++-- gulpfile.js | 37 +++++---- lib/data/changelog.json | 93 +++++++++++++++++++++++ lib/data/date.js | 1 + lib/data/svg_styles.js | 7 ++ lib/helpers/layouts.js | 5 ++ lib/partials/ie8_notice.hbs | 5 ++ lib/partials/layout.hbs | 66 ++++++++++++++++ lib/partials/svg_template.hbs | 25 ++++++ package.json | 5 +- src/404.hbs | 17 +++++ src/404.html | 10 --- src/changelog.hbs | 17 +++++ src/changelog.html | 58 -------------- src/documentation.hbs | 138 ++++++++++++++++++++++++++++++++++ src/documentation.html | 129 ------------------------------- src/index.hbs | 32 ++++++++ src/index.html | 25 ------ template.html | 92 ----------------------- 19 files changed, 436 insertions(+), 340 deletions(-) create mode 100644 lib/data/changelog.json create mode 100644 lib/data/date.js create mode 100644 lib/data/svg_styles.js create mode 100644 lib/helpers/layouts.js create mode 100644 lib/partials/ie8_notice.hbs create mode 100644 lib/partials/layout.hbs create mode 100644 lib/partials/svg_template.hbs create mode 100644 src/404.hbs delete mode 100644 src/404.html create mode 100644 src/changelog.hbs delete mode 100644 src/changelog.html create mode 100644 src/documentation.hbs delete mode 100644 src/documentation.html create mode 100644 src/index.hbs delete mode 100644 src/index.html delete mode 100644 template.html diff --git a/config.js b/config.js index c89ee5c..4b46290 100644 --- a/config.js +++ b/config.js @@ -5,18 +5,14 @@ var path = require('path'), buildPath = _.bind(path.join, path, buildRoot); module.exports = { - titles: { - '_': 'Regexper', - 'changelog.html': 'Regexper - Changelog', - 'documentation.html': 'Regexper - Documentation', - '404.html': 'Regexper - Page Not Found' - }, buildRoot: buildRoot, buildPath: buildPath, - templateFile: './template.html', globs: { - other: './src/**/*.!(html|scss|js|peg)', - html: './src/**/*.html', + other: './src/**/*.!(hbs|scss|js|peg)', + templates: './src/**/*.hbs', + data: ['./lib/data/**/*.json', './lib/data/**/*.js'], + helpers: './lib/helpers/**/*.js', + partials: './lib/partials/**/*.hbs', sass: './src/**/*.scss', js: ['./src/**/*.js', './src/**/*.peg'], spec: './spec/**/*_spec.js' diff --git a/gulpfile.js b/gulpfile.js index 2e83856..fb91220 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,4 +1,5 @@ var gulp = require('gulp'), + _ = require('lodash'), notify = require('gulp-notify'), plumber = require('gulp-plumber'), config = require('./config'); @@ -11,7 +12,13 @@ function errorHandler() { gulp.task('default', ['server', 'docs'], function() { 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']); }); @@ -53,23 +60,21 @@ gulp.task('static', function() { }); gulp.task('markup', ['styles'], function() { - var wrap = require('gulp-wrap'), - path = require('path'), - fs = require('fs'); + var hb = require('gulp-hb'), + frontMatter = require('gulp-front-matter'), + rename = require('gulp-rename'); - return gulp.src(config.globs.html, { base: './src' }) + return gulp.src(config.globs.templates) .pipe(errorHandler()) - .pipe(wrap({ src: config.templateFile }, { - date: new Date().toISOString(), - title: function() { - var root = path.join(this.file.cwd, this.file.base), - file = path.relative(root, this.file.history[0]); - - return config.titles[file] || config.titles['_']; - }, - svgStyles: fs.readFileSync(path.join(config.compass.css, 'svg.css'), { - encoding: 'utf-8' - }) + .pipe(frontMatter()) + .pipe(hb({ + data: config.globs.data, + helpers: config.globs.helpers, + partials: config.globs.partials, + bustCache: true, + })) + .pipe(rename(function(path) { + path.extname = '.html'; })) .pipe(gulp.dest(config.buildRoot)); }); diff --git a/lib/data/changelog.json b/lib/data/changelog.json new file mode 100644 index 0000000..742853d --- /dev/null +++ b/lib/data/changelog.json @@ -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 GitHub issue)" + ] + }, + { + "label": "September 2, 2015 Release", + "changes": [ + "Merging fix for error reporting from (see GitHub pull request)" + ] + }, + { + "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 GitHub issue)", + "Fixed rendering in IE that was causing \"-->\" 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 RFC822 email regular expression 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 GitHub issue)" + ] + }, + { + "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 GitHub issue)" + ] + }, + { + "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 Canopy and Snap.svg)", + "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" + ] + } +] diff --git a/lib/data/date.js b/lib/data/date.js new file mode 100644 index 0000000..926fdb0 --- /dev/null +++ b/lib/data/date.js @@ -0,0 +1 @@ +module.exports = new Date().toISOString(); diff --git a/lib/data/svg_styles.js b/lib/data/svg_styles.js new file mode 100644 index 0000000..94c45e6 --- /dev/null +++ b/lib/data/svg_styles.js @@ -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' +}) diff --git a/lib/helpers/layouts.js b/lib/helpers/layouts.js new file mode 100644 index 0000000..f0878f8 --- /dev/null +++ b/lib/helpers/layouts.js @@ -0,0 +1,5 @@ +var layouts = require('handlebars-layouts'); + +module.exports.register = function(handlebars) { + layouts.register(handlebars); +}; diff --git a/lib/partials/ie8_notice.hbs b/lib/partials/ie8_notice.hbs new file mode 100644 index 0000000..9d7aabf --- /dev/null +++ b/lib/partials/ie8_notice.hbs @@ -0,0 +1,5 @@ +
+

Regexper

+ +

Your browser is no longer supported by the current version of Regexper. Upgrade your browser to the latest version, or visit the old Regexper.

+
diff --git a/lib/partials/layout.hbs b/lib/partials/layout.hbs new file mode 100644 index 0000000..0163a88 --- /dev/null +++ b/lib/partials/layout.hbs @@ -0,0 +1,66 @@ + + + + + + + Regexper{{#if file.frontMatter.title}} - {{file.frontMatter.title}}{{/if}} + + + + + + + + + + + + + + + +
+ + + +
+ +
+ {{#block "body"}}{{/block}} +
+ + + + + diff --git a/lib/partials/svg_template.hbs b/lib/partials/svg_template.hbs new file mode 100644 index 0000000..a6e3f31 --- /dev/null +++ b/lib/partials/svg_template.hbs @@ -0,0 +1,25 @@ +
+ + + + + + + + + + + + + + + + +
+
+
+
diff --git a/package.json b/package.json index 1ada2c6..5a499ad 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,13 @@ "gulp-compass": "^2.0.4", "gulp-connect": "^2.2.0", "gulp-docco": "0.0.4", + "gulp-front-matter": "^1.3.0", + "gulp-hb": "^2.6.5", "gulp-notify": "^2.0.1", "gulp-plumber": "^1.0.0", + "gulp-rename": "^1.2.2", "gulp-tap": "^0.1.3", - "gulp-wrap": "^0.11.0", + "handlebars-layouts": "^3.1.2", "jasmine-core": "^2.3.4", "karma": "^0.13.14", "karma-browserify": "^4.4.0", diff --git a/src/404.hbs b/src/404.hbs new file mode 100644 index 0000000..68567ba --- /dev/null +++ b/src/404.hbs @@ -0,0 +1,17 @@ +--- +title: Page Not Found +--- +{{#extend "layout"}} + {{#content "body"}} +
+

404: Not Found

+ +
+ Some people, when confronted with a problem, think
+ “I know, I'll use regular expressions.” Now they have two problems. +
+ +

Apparently, you have three problems…because the page you requested cannot be found.

+
+ {{/content}} +{{/extend}} diff --git a/src/404.html b/src/404.html deleted file mode 100644 index 77a6d82..0000000 --- a/src/404.html +++ /dev/null @@ -1,10 +0,0 @@ -
-

404: Not Found

- -
- Some people, when confronted with a problem, think
- “I know, I'll use regular expressions.” Now they have two problems. -
- -

Apparently, you have three problems…because the page you requested cannot be found.

-
diff --git a/src/changelog.hbs b/src/changelog.hbs new file mode 100644 index 0000000..4e901d8 --- /dev/null +++ b/src/changelog.hbs @@ -0,0 +1,17 @@ +--- +title: Changelog +--- +{{#extend "layout"}} + {{#content "body"}} +
+
+ {{#each changelog}} +
{{label}}
+ {{#each changes}} +
{{{this}}}
+ {{/each}} + {{/each}} +
+
+ {{/content}} +{{/extend}} diff --git a/src/changelog.html b/src/changelog.html deleted file mode 100644 index a679349..0000000 --- a/src/changelog.html +++ /dev/null @@ -1,58 +0,0 @@ -
-
-
September 17, 2015 Release
-
Fixing styling of labels on repetitions
-
Fixing issue with vertical centering of alternation expressions that include empty expressions (see GitHub issue) - -
September 2, 2015 Release
-
Merging fix for error reporting from (see GitHub pull request) - -
July 5, 2015 Release
-
Updating Creative Commons license badge URL so it isn't pointing to a redirecting URL anymore
- -
June 22, 2015 Release
-
Tweaking buggy Firefox hash detection code based on JavaScript errors that were logged
- -
June 16, 2015 Release
-
Fixes issue with expressions containing a "%" not rendering in Firefox (see GitHub issue)
-
Fixed rendering in IE that was causing "-->" to display at the top of the page.
- -
April 14, 2015 Release
-
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 RFC822 email regular expression 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
- -
March 14, 2015 Release
-
Removing use of Q for promises in favor of "native" ES6 promises (even though they aren't quite native everywhere yet)
- -
March 13, 2015 Release
-
Fixes bug with numbering of nested subexpressions (see GitHub issue)
- -
February 11, 2015 Release
-
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 GitHub issue)
- -
December 30, 2014 Release
-
Fixing bug that prevented rendering empty subexpressions
-
Fixing minor styling bug when permalink is disabled
-
Cleaning up some duplicated styles and JS
- -
December 29, 2014 Release
-
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
- -
December 26, 2014 Release
-
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 Canopy and Snap.svg)
-
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
-
-
diff --git a/src/documentation.hbs b/src/documentation.hbs new file mode 100644 index 0000000..291b8fc --- /dev/null +++ b/src/documentation.hbs @@ -0,0 +1,138 @@ +--- +title: Documentation +--- +{{#extend "layout"}} + {{#content "body"}} +
+
+

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.

+
+
+
+
+ {{/content}} + + {{#content "footer" mode="append"}} + + {{/content}} +{{/extend}} diff --git a/src/documentation.html b/src/documentation.html deleted file mode 100644 index 3768217..0000000 --- a/src/documentation.html +++ /dev/null @@ -1,129 +0,0 @@ -
-
-

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/index.hbs b/src/index.hbs new file mode 100644 index 0000000..8fab2ad --- /dev/null +++ b/src/index.hbs @@ -0,0 +1,32 @@ +{{#extend "layout"}} + {{#content "body"}} +
+
+ + + + +
+
+ +
+
+ + + +
+
+ + {{/content}} + + {{#content "footer" mode="append"}} + + {{/content}} +{{/extend}} diff --git a/src/index.html b/src/index.html deleted file mode 100644 index 026d5a5..0000000 --- a/src/index.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
- - - - -
-
- -
-
- - - -
-
- - diff --git a/template.html b/template.html deleted file mode 100644 index 68e3499..0000000 --- a/template.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - ${title()} - - - - - - - - - - - - - - - -
- - - -
- -
- ${contents} -
- - - - -