├── .editorconfig
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── README.mdtex
├── docs
└── images
│ ├── flowchart.pdf
│ ├── flowchart.png
│ ├── flowchart.svg
│ ├── fracdrhodt-0-0d95010981.svg
│ ├── fracdrhodt-0-64ee686b6f.svg
│ ├── fracdrhodt-0-6deddd4e7c.svg
│ ├── fracdrhodt-0-d0893f9a61.svg
│ ├── fracdrhodt-0-ebec560456.svg
│ ├── fracdrhodt-0-f9ff87b518.svg
│ ├── latex-35667f6f3d.svg
│ ├── latex-41db537fd1.svg
│ ├── latex-7d8af78a9d.svg
│ ├── latex-8ae45909b6.svg
│ ├── latex-ab99620889.svg
│ ├── latex-d44b8c0ee5.svg
│ ├── nabla-cdot-vecu-0-19e52303bc.svg
│ ├── nabla-cdot-vecu-0-3ec1472ff7.svg
│ ├── nabla-cdot-vecu-0-5ecc63754f.svg
│ ├── nabla-cdot-vecu-0-c3529d4cca.svg
│ ├── nabla-cdot-vecu-0-e420b67a9e.svg
│ └── nabla-cdot-vecu-0-efbf661771.svg
├── example
├── gulpfile.js
├── images
│ ├── y-frac1x-43d4730472.png
│ └── y-frac1x-968f2fff1f.png
├── sample.md
└── sample.mdtex
├── gulpfile.js
├── lib
├── compute-filename.js
├── equation-list.js
├── equation.js
└── index.js
├── package.json
└── test
├── compute-filename.js
├── fixtures
├── index.js
└── sample.mdtex
├── gulp-markdown-equations.js
└── test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 |
3 | # Logs
4 | logs
5 | *.log
6 |
7 | # Runtime data
8 | pids
9 | *.pid
10 | *.seed
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19 | .grunt
20 |
21 | # Compiled binary addons (http://nodejs.org/api/addons.html)
22 | build/Release
23 | build
24 |
25 | # Dependency directory
26 | # Deployed apps should consider commenting this line out:
27 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
28 | node_modules
29 |
30 | **/.DS_Store
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.12"
4 | - "0.11"
5 | - "0.10"
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ricky Reusser
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gulp-markdown-equations
2 | [](https://travis-ci.org/rreusser/gulp-markdown-equations) [](http://badge.fury.io/js/gulp-markdown-equations) [](https://david-dm.org/rreusser/gulp-markdown-equations)
3 |
4 | A gulp plugin that makes it easy to replace markdown latex equations with rendered images
5 |
6 |
7 | ## Introduction
8 |
9 | This module exposes the tools necessary to to transform equations in a markdown document into rendered raster or vector images. It uses the [transform-markdown-mathmode](https://www.npmjs.com/package/transform-markdown-mathmode) node module to locate and transform equations and reconnects with the gulp pipeline after the results have been rendered to complete the transformation using information from the result.
10 |
11 | This means you can just mix
into your markdown document. For example,
12 |
13 | ```markdown
14 | It handles inline equations like $\nabla \cdot \vec{u} = 0$ and display equations like $$\frac{D\rho}{Dt} = 0.$$
15 | ```
16 |
17 | gets transformed into:
18 |
19 | It handles inline equations like
and display equations like

'+img+'
' : img 87 | }) 88 | })) 89 | 90 | // Restore and then change filters to operate on the *.md document: 91 | .pipe(texFilter.restore()).pipe(mdFilter) 92 | 93 | // Output in the current directory: 94 | .pipe(gulp.dest('./')) 95 | }) 96 | ``` 97 | 98 | The task is run with: 99 | 100 | ```bash 101 | $ gulp mdtex 102 | ``` 103 | 104 | 105 | ## API 106 | 107 | #### `require('gulp-markdown-mathmode')( [options] )` 108 | Create a gulp-compatible buffered file stream transform. Options are: 109 | 110 | - `defaults`: Parameters that get added to each equation object and passed to the
'+img+'
' : img 87 | }) 88 | })) 89 | 90 | // Restore and then change filters to operate on the *.md document: 91 | .pipe(texFilter.restore()).pipe(mdFilter) 92 | 93 | // Output in the current directory: 94 | .pipe(gulp.dest('./')) 95 | }) 96 | ``` 97 | 98 | The task is run with: 99 | 100 | ```bash 101 | $ gulp mdtex 102 | ``` 103 | 104 | 105 | ## API 106 | 107 | #### `require('gulp-markdown-mathmode')( [options] )` 108 | Create a gulp-compatible buffered file stream transform. Options are: 109 | 110 | - `defaults`: Parameters that get added to each equation object and passed to the $\LaTeX$ templator. A good example is setting default margins that can be overridden later on with config variables added to a specific equation. 111 | - `inline`: an associative array of key/value pairs for inline equations, into which preprocessed parameters are merged 112 | - `display`: an associative array of key/value pairs for displaystyle equations, into which preprocessed parameters are merged 113 | - `preprocessor`: a function that extracts equation-specific parameters. In other words, if your equation is `$[margin=10pt] y=x$`, the preprocessor extracts `{margin: '10pt'}`. Default preprocessor is [square-parameters](https://github.com/rreusser/square-parameters). If `null`, preprocessor step is skipped. See below for more details. 114 | - `templator`: a function of format `function( tex, params ) {}` that receives the preprocessed `\LaTeX` and parameters and returns a templated $\LaTeX$ document. If null, the original tex string will be passed through unmodified. Default templator is [equation-to-latex](https://github.com/rreusser/equation-to-latex). See below for more detail. 115 | 116 | 117 | ### Methods: 118 | 119 | #### `.completeSync( file, callback )` 120 | Once a file has been processed, you *must* tap into the stream and complete the markdown transformation. See above for an example. `callback` is executed with `this` set to an object containing equation metadata. The value you return is inserted into the markdown document. 121 | 122 | The metadata contains all information about the processed equation, including the fully processed file at this point in the pipeline. If image dimensions are available, they will be added. For example: 123 | 124 | ```javascript 125 | { display: false, 126 | inline: true, 127 | margin: '0 1pt 0pt 0pt', 128 | path: 'docs/images/latex-d3a0aa2938.png', 129 | height: 38, 130 | width: 104, 131 | equation: 132 | { tex: '\\LaTeX', 133 | alt: '\LaTeX', 134 | templated: '\\documentclass[10pt] ... \end{document}\n', 135 | file:'+img+'
') : cb(img) 33 | }) 34 | })) 35 | .pipe(texFilter.restore()) 36 | 37 | .pipe(mdFilter) 38 | .pipe(gulp.dest('./')) 39 | .pipe(mdFilter.restore()) 40 | 41 | }) 42 | 43 | -------------------------------------------------------------------------------- /example/images/y-frac1x-43d4730472.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rreusser/gulp-markdown-equations/eaf814633118f5bff3fb7e66eef453c377952ed7/example/images/y-frac1x-43d4730472.png -------------------------------------------------------------------------------- /example/images/y-frac1x-968f2fff1f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rreusser/gulp-markdown-equations/eaf814633118f5bff3fb7e66eef453c377952ed7/example/images/y-frac1x-968f2fff1f.png -------------------------------------------------------------------------------- /example/sample.md: -------------------------------------------------------------------------------- 1 | An inline hyperbola looks like'+img+'
' : img 39 | }) 40 | })) 41 | .pipe(texFilter.restore()) 42 | 43 | .pipe(mdFilter) 44 | .pipe(gulp.dest('./')) 45 | .pipe(mdFilter.restore()) 46 | 47 | }) 48 | 49 | -------------------------------------------------------------------------------- /lib/compute-filename.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var parameterize = require('parameterize') 4 | , md5 = require('md5') 5 | 6 | module.exports = computeFilename 7 | 8 | function computeFilename( content, params ) { 9 | 10 | var basename = params.name || parameterize(content).slice(0,45) 11 | var hash = md5(JSON.stringify(params)+content).slice(0,10) 12 | 13 | return ( basename + '-' + hash + '.tex') 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lib/equation-list.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var sizeOf = require('image-size') 4 | , path = require('path') 5 | , gutil = require('gulp-util') 6 | , extend = require('util-extend') 7 | 8 | module.exports = EquationLookup 9 | 10 | function EquationLookup() { 11 | this.equations = {} 12 | } 13 | 14 | EquationLookup.prototype.store = function(equation) { 15 | var key = equation.file.basename 16 | var eqset = this.equations[key] = this.equations[key] || [] 17 | eqset.push( equation ) 18 | 19 | return equation 20 | } 21 | 22 | EquationLookup.prototype.completeSync = function(file, callback) { 23 | 24 | this.complete(file, function(result) { 25 | result( callback.bind(this)() ) 26 | }) 27 | } 28 | 29 | EquationLookup.prototype.complete = function(file, callback) { 30 | var key = path.basename(gutil.replaceExtension(file.path, '.tex')) 31 | var eqset = this.equations[key] = this.equations[key] || [] 32 | var equation = eqset.pop(equation) 33 | 34 | var meta = {} 35 | 36 | try { 37 | var dimensions = sizeOf(file.contents) 38 | meta.width = dimensions.width 39 | meta.height = dimensions.height 40 | } catch(e) { } 41 | 42 | meta.path = path.relative(file.cwd, file.path) 43 | 44 | meta = extend(equation.params,meta) 45 | meta.equation = equation 46 | meta.alt = equation.alt 47 | meta.templated = equation.templated 48 | 49 | callback.bind(meta)(function(result) { 50 | equation.callback(result) 51 | }) 52 | } 53 | -------------------------------------------------------------------------------- /lib/equation.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var extend = require('util-extend') 4 | , computeFilename = require('./compute-filename') 5 | , entities = require('entities') 6 | , gutil = require('gulp-util') 7 | , File = require('vinyl') 8 | , assert = require('assert') 9 | 10 | module.exports = Equation 11 | 12 | function Equation( input, params, callback, config ) { 13 | 14 | if( config.preprocessor === null ) { 15 | 16 | // Skip the preprocessor: 17 | this.tex = input 18 | this.params = params 19 | 20 | } else { 21 | var preprocessed = config.preprocessor(input) 22 | 23 | // Set the LaTeX content: 24 | this.tex = preprocessed.content 25 | 26 | // Extend the input params by params from the preprocessor: 27 | this.params = extend(params, preprocessed.params) 28 | } 29 | 30 | this.params.usepackages = (this.params.usepackages || []).concat( config.usepackages || [] ) 31 | 32 | // Set an alt tag unless provided: 33 | this.alt = this.params.alt || entities.encodeHTML( this.tex.trim() ) 34 | 35 | // Stick the raw eq inside a latex template: 36 | this.templated = config.templator === null ? this.tex : config.templator(this.tex, this.params) 37 | 38 | // Compute the filename if not already provided as this.params.name 39 | var filename = computeFilename( this.tex, this.params ) 40 | 41 | // Create a vinyl file. Extension (*.tex) comes from this.filename 42 | this.file = new File({ 43 | cwd: "./", 44 | base: "./", 45 | path: './' + filename, 46 | contents: new Buffer(this.templated) 47 | }) 48 | 49 | this.callback = function() { 50 | this.callback = function(){ 51 | throw new gutil.PluginError('gulp-markdown-equations', 'Equation transform callback executed more than once') 52 | } 53 | return callback.apply(this,arguments) 54 | }.bind(this) 55 | } 56 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var through = require('through2') 4 | , tmm = require('transform-markdown-mathmode') 5 | , gutil = require('gulp-util') 6 | , rawBody = require('raw-body') 7 | , extend = require('util-extend') 8 | , path = require('path') 9 | 10 | , defaultTemplator = require('equation-to-latex') 11 | , defaultPreprocessor = require('square-parameters') 12 | , Equation = require('./equation') 13 | , EquationLookup = require('./equation-list') 14 | 15 | module.exports = gulpMarkdownEquations 16 | 17 | function gulpMarkdownEquations( opts ) { 18 | 19 | 20 | // Generate the expected defaults if not provided: 21 | var config = opts || {} 22 | config.defaults = config.defaults || {} 23 | config.defaults.inline = config.defaults.inline || {} 24 | config.defaults.display = config.defaults.display || {} 25 | 26 | // Set default config: 27 | if( config.templator === undefined ) config.templator = defaultTemplator 28 | if( config.preprocessor === undefined ) config.preprocessor = defaultPreprocessor 29 | 30 | // Create a lookup table so we can match up files with their equations: 31 | var equations = new EquationLookup() 32 | 33 | 34 | // Return a through transform: 35 | var transform = through.obj(function(file,enc,cb) { 36 | 37 | // Pass null files through: 38 | if( file.isNull() ) { 39 | cb(null,file) 40 | return 41 | } 42 | 43 | // No reason we couldn't support streams, really, except LaTeX is pretty 44 | // fundamentally stream-unfriendly 45 | if( file.isStream() ) { 46 | throw new gutil.PluginError('gulp-markdown-equations','Streams not supported!') 47 | } 48 | 49 | 50 | // Locate equations and store the callback in a new equation for later use, 51 | // then push the vinyl file object for this equation down the file stream: 52 | var parser = tmm({ 53 | 54 | display: function(tex,cb) { 55 | var params = extend({display:true,inline:false},config.defaults.display) 56 | this.push( equations.store(new Equation( tex, params, cb, config )).file ) 57 | }.bind(this), 58 | 59 | 60 | inline: function(tex,cb) { 61 | var params = extend({display:false,inline:true},config.defaults.inline) 62 | this.push( equations.store(new Equation( tex, params, cb, config )).file ) 63 | }.bind(this) 64 | 65 | }) 66 | 67 | 68 | // Wait for the parser to complete, then rewrite the original file from 69 | // *.mdtex to *.md and push it down the file stream 70 | rawBody(parser,function(err,data) { 71 | file.contents = data 72 | file.path = gutil.replaceExtension( file.path, '.md' ) 73 | this.push(file) 74 | gutil.log("Pushed '" + gutil.colors.cyan(path.relative( file.base, file.path)) + "' to file stream") 75 | cb() 76 | }.bind(this)) 77 | 78 | 79 | // Oh yeah, actually need to send the file to the parser stream: 80 | file.pipe(parser) 81 | }) 82 | 83 | 84 | // Alias this function so that we can call it from the transform object itself: 85 | transform.complete = equations.complete.bind(equations) 86 | transform.completeSync = equations.completeSync.bind(equations) 87 | 88 | 89 | return transform 90 | } 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-markdown-equations", 3 | "version": "1.2.3", 4 | "description": "A gulp plugin that makes it easy to replace markdown latex equations with rendered images", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "node test/test.js | tap-spec" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/rreusser/gulp-markdown-equations.git" 12 | }, 13 | "keywords": [ 14 | "markdown", 15 | "equations", 16 | "latex", 17 | "gulpplugin", 18 | "mathmode" 19 | ], 20 | "author": "Ricky Reusser", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "glob": "^5.0.14", 24 | "gulp-filter": "^2.0.2", 25 | "gulp-latex": "^1.0.1", 26 | "gulp-pdftocairo": "^0.2.0", 27 | "gulp-tap": "^0.1.3", 28 | "tap-spec": "^4.0.2", 29 | "tape": "^4.0.1" 30 | }, 31 | "dependencies": { 32 | "entities": "^1.1.1", 33 | "equation-to-latex": "^2.0.1", 34 | "gulp-util": "^3.0.6", 35 | "handlebars": "^3.0.3", 36 | "image-size": "^0.3.5", 37 | "md5": "^2.0.0", 38 | "parameterize": "0.0.7", 39 | "raw-body": "^2.1.2", 40 | "square-parameters": "^1.0.2", 41 | "through2": "^2.0.0", 42 | "transform-markdown-mathmode": "^0.1.4", 43 | "util-extend": "^1.0.1", 44 | "vinyl": "^0.5.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/compute-filename.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var name = require('../lib/compute-filename') 4 | , test = require('tape') 5 | 6 | test('compute-filename: parameterizes the tex', function(t) { 7 | t.assert( name("y=x^2", {}).match(/yx2/) ) 8 | t.end() 9 | }) 10 | 11 | test('compute-filename: uses name over parameterized equation if name is provided', function(t) { 12 | t.assert( name("y=x^2", {name: 'equation'}).match(/equation/) ) 13 | t.assert( ! name("y=x^2", {name: 'equation'}).match(/yx2/) ) 14 | t.end() 15 | }) 16 | 17 | test('compute-filename: appends a ten-character hash', function(t) { 18 | t.assert( name("y=x^2", {}).match(/-[a-zA-Z0-9]{10}\./) ) 19 | t.end() 20 | }) 21 | 22 | test('compute-filename: distinct equations have distinct filenames', function(t) { 23 | var n1 = name("y=x^2", {}) 24 | var n2 = name("y=x^3", {}) 25 | t.assert( n1 !== n2 ) 26 | t.end() 27 | }) 28 | 29 | test('compute-filename: distinct parameters yield distinct filenames', function(t) { 30 | var n1 = name("y=x^2", {margin: '10pt'}) 31 | var n2 = name("y=x^2", {margin: '11pt'}) 32 | t.assert( n1 !== n2 ) 33 | t.end() 34 | }) 35 | 36 | test('compute-filename: appends ".tex"', function(t) { 37 | var n1 = name("y=x^2", {margin: '10pt'}) 38 | t.assert( n1.match(/\.tex$/) ) 39 | t.end() 40 | }) 41 | -------------------------------------------------------------------------------- /test/fixtures/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var glob = require('glob') 4 | , path = require('path') 5 | , fs = require('fs') 6 | 7 | var files = glob.sync(__dirname + "/**/*") 8 | var fixtures = {} 9 | 10 | files.forEach(function(f) { 11 | if( f === __filename ) return 12 | var rel = path.relative( __dirname, f ) 13 | 14 | fixtures[rel] = fs.readFileSync(f) 15 | }) 16 | 17 | module.exports = fixtures 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/fixtures/sample.mdtex: -------------------------------------------------------------------------------- 1 | An inline hyperbola looks like $[foo=bar]y = \frac{1}{x}$, and a display hyperbola looks like $$[foo=bar]y = \frac{1}{x}$$ 2 | -------------------------------------------------------------------------------- /test/gulp-markdown-equations.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var test = require('tape') 4 | , gulpMarkdownEquations = require('../lib') 5 | , tap = require('gulp-tap') 6 | , File = require('vinyl') 7 | , fixtures = require('./fixtures') 8 | , path = require('path') 9 | 10 | //test.createStream().pipe(require('tap-spec')()).pipe(process.stdout); 11 | 12 | function testBehavior(input, options, eqCallback, mdCallback) { 13 | 14 | var mdeq = gulpMarkdownEquations(options) 15 | 16 | mdeq.write(new File({ path: 'sample.mdtex', contents: input })) 17 | mdeq.end() 18 | 19 | mdeq.pipe(tap(function(file) { 20 | if( file.contents === null ) return 21 | if( file.basename.match(/\.md$/) ) { 22 | if( mdCallback ) mdCallback.bind(file)() 23 | } else { 24 | if( eqCallback ) { 25 | mdeq.complete(file,eqCallback) 26 | } else { 27 | mdeq.complete(file,function(cb) { cb() }) 28 | } 29 | } 30 | })) 31 | 32 | return mdeq 33 | } 34 | 35 | 36 | test('gulp-markdown-equations: a null templator passes tex through',function(t) { 37 | testBehavior(fixtures['sample.mdtex'], { templator: null }, function(cb) { 38 | t.equal( this.foo, 'bar', 'gets preprocessed config' ) 39 | t.equal( this.templated, 'y = \\frac{1}{x}', 'tex is not templated' ) 40 | cb('test') 41 | }).on('end',t.end) 42 | }) 43 | 44 | test('gulp-markdown-equations: tex gets escaped and added as alt tag',function(t) { 45 | testBehavior(fixtures['sample.mdtex'], { templator: null }, function(cb) { 46 | t.equal( this.alt, 'y = \frac{1}{x}', 'tex shows up in alt tag' ) 47 | cb('test') 48 | }).on('end',t.end) 49 | }) 50 | 51 | test('gulp-markdown-equations: a null preprocessor skips params',function(t) { 52 | testBehavior(fixtures['sample.mdtex'], { preprocessor: null }, function(cb) { 53 | t.equal( this.foo, undefined, 'params are not parsed' ) 54 | cb('test') 55 | }).on('end',t.end) 56 | }) 57 | 58 | test('gulp-markdown-equations: number of files is correct',function(t) { 59 | var numEq = 0, numMd = 0 60 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 61 | numEq++ 62 | cb() 63 | }, function() { 64 | numMd++ 65 | }).on('end',function() { 66 | t.equal(numEq, 2, 'got two equations') 67 | t.equal(numMd, 1, 'got one markdown file') 68 | t.end() 69 | }) 70 | 71 | }) 72 | 73 | test('gulp-markdown-equations: default options get passed',function(t) { 74 | 75 | var options = { 76 | defaults: { 77 | inline: { beep: 'boop' }, 78 | display: { baz: 'bop' } 79 | } 80 | } 81 | 82 | testBehavior( fixtures['sample.mdtex'], options, function(cb) { 83 | if( this.display ) { 84 | t.equal(this.baz, 'bop', 'receives default display mode config') 85 | } else { 86 | t.equal(this.beep, 'boop', 'receives default display mode config') 87 | } 88 | cb() 89 | }).on('end',t.end) 90 | }) 91 | 92 | test('gulp-markdown-equations: correct result is inserted',function(t) { 93 | var numEq = 0, md 94 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 95 | numEq++ 96 | cb('equation-number-' + numEq) 97 | },function() { 98 | md = this.contents.toString() 99 | t.assert( md.match(/equation-number-1/), 'markdown contains the result of the first equation') 100 | t.assert( md.match(/equation-number-2/), 'markdown contains the result of the second equation') 101 | }).on('end',t.end) 102 | }) 103 | 104 | test('gulp-markdown-equations: has the correct filename',function(t) { 105 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 106 | t.assert( this.equation.file.basename.match(/^y-frac1x-[a-z0-9]{10}.tex/), 'has the correct filename') 107 | cb() 108 | }).on('end',t.end) 109 | }) 110 | 111 | test('gulp-markdown-equations: tex is extracted',function(t) { 112 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 113 | t.equal( this.equation.tex, 'y = \\frac{1}{x}', 'has the tex extracted') 114 | cb() 115 | }).on('end',t.end) 116 | }) 117 | 118 | test('gulp-markdown-equations: preprocesses and inserts params',function(t) { 119 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 120 | t.equal( this.foo, 'bar', 'parsed and received its params') 121 | cb() 122 | }).on('end',t.end) 123 | }) 124 | 125 | test('gulp-markdown-equations: latex templating',function(t) { 126 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 127 | t.assert( this.equation.templated.match(/^\\documentclass/), 'got inserted into the latex template') 128 | cb() 129 | }).on('end',t.end) 130 | }) 131 | 132 | test('gulp-markdown-equations: fails if callback executed more than once',function(t) { 133 | testBehavior( fixtures['sample.mdtex'], {}, function(cb) { 134 | cb() 135 | t.throws(cb, Error, 'throws error on second execution') 136 | }).on('end',t.end) 137 | }) 138 | 139 | 140 | test('gulp-markdown-equations: completeSync',function(t) { 141 | t.plan(4) 142 | var eqNum = 0 143 | var mdeq = gulpMarkdownEquations(), md 144 | 145 | mdeq.write(new File({ path: 'sample.mdtex', contents: fixtures['sample.mdtex'] })) 146 | mdeq.end() 147 | mdeq.on('end',t.end) 148 | 149 | mdeq.pipe(tap(function(file) { 150 | if( file.extname !== '.md' ) { 151 | eqNum++ 152 | mdeq.completeSync(file,function() { 153 | t.equal( this.foo, 'bar', 'this is set to the equation' ) 154 | return 'inserted-equation-' + eqNum 155 | }) 156 | } else { 157 | md = file.contents.toString() 158 | t.assert( md.match(/inserted-equation-1/m), 'Markdown contains inserted equations') 159 | t.assert( md.match(/inserted-equation-2/m), 'Markdown contains inserted equations') 160 | } 161 | })) 162 | }) 163 | 164 | test('passes a null file',function(t) { 165 | var numEq = 0, numMd = 0, md 166 | 167 | testBehavior( null, {}, function(cb) { 168 | numEq++ 169 | }, function() { 170 | numMd++ 171 | }).on('end',function() { 172 | t.equal(numEq, 0, 'got no *.tex') 173 | t.equal(numMd, 0, 'got no *.md') 174 | t.end() 175 | }) 176 | }) 177 | 178 | test('gulp-markdown-equations: usepackages',function(t) { 179 | testBehavior( fixtures['sample.mdtex'], { 180 | usepackages: ['package1', 'package2'] 181 | }, function(cb) { 182 | t.assert( this.equation.templated.match( /usepackage\{\s*package1\s*\}/), 'contains \\usepackage{package1}' ) 183 | t.assert( this.equation.templated.match( /usepackage\{\s*package2\s*\}/), 'contains \\usepackage{package2}' ) 184 | cb() 185 | }).on('end',t.end) 186 | }) 187 | 188 | 189 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | require('./compute-filename') 4 | require('./gulp-markdown-equations') 5 | --------------------------------------------------------------------------------