Skip to content

Commit

Permalink
Replace dedent with a template-only dedent
Browse files Browse the repository at this point in the history
Summary:
The `dedent` module has two problems that require its replacement.
First, it dedents the substitutions in addition to the template, but the
substitutions need to be treated as opaque. This is because one such
substitution is the whole HTML contents, which could contain important
leading whitespace in a `<pre>` tag. Second, it replaces the character
sequence "backslash, newline, zero-or-more-whitespace" with the empty
string, and there is no way to disable this behavior, so there is
consequently no way to emit a non-final line ending in a backslash. This
means that it will not be possible to use `dedent` to dedent code
fragments.

Both of these issues are solved by implementing a template tag function
that serves the intended purpose.

Test Plan:
Add

    <test>${"\n    indented!"}</test>\

to the trailing backslash in `server.js`, and check the rendered output
to see that both issues mentioned above are fixed.
  • Loading branch information
wchargin committed Jul 29, 2017
1 parent d4c20eb commit 06475d4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 3 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"homepage": "https://wchargin.github.io/",
"devDependencies": {
"copy-webpack-plugin": "^3.0.1",
"dedent": "^0.6.0",
"babel-cli": "^6.11.4",
"babel-core": "^6.13.2",
"babel-eslint": "^6.1.2",
Expand Down
38 changes: 38 additions & 0 deletions src/dedent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* A template tag function that performs dedenting on the template, but
* not its arguments.
*
* For instance, given the template
*
* |dedent`\
* | one ${one}
* | two ${two}
* | done`,
*
* where `one === "1"` and `two === "\n 2"`, the template string
* would expand to "one 1\n two\n 2\ndone". Note that four spaces
* of indentation were stripped off of each of "one" and "two", but not
* from "2".
*
* Lines that contain only whitespace are not used for measuring.
*/
export default function dedent(strings, ...values) {
const lineLengths = strings.join("")
.split("\n")
.filter(line => line.trim().length !== 0)
.map(line => line.length - line.trimLeft().length);
const trimAmount = Math.min.apply(null, lineLengths);

const parts = [];
for (let i = 0; i < strings.length; i++) {
const trimmed = strings[i]
.split("\n")
.map((line, j) => i === 0 || j > 0 ? line.substr(trimAmount) : line)
.join("\n");
parts.push(trimmed);
if (i < values.length) {
parts.push(values[i]);
}
}
return parts.join("");
}
4 changes: 2 additions & 2 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* used by the static-site-generator-webpack-plugin.
*/

import dedent from 'dedent';
import {StyleSheetServer} from 'aphrodite/no-important';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import {match, RouterContext} from 'react-router';

import dedent from './dedent';
import {createRoutes, resolveTitleFromPath} from './data/Routes';

export default function renderStaticPage(locals, callback) {
Expand All @@ -27,7 +27,7 @@ export default function renderStaticPage(locals, callback) {
const component = <RouterContext {...renderProps} />;
const {html, css} = StyleSheetServer.renderStatic(() =>
ReactDOMServer.renderToString(component));
const page = dedent`
const page = dedent`\
<!DOCTYPE html>
<html>
<head>
Expand Down

1 comment on commit 06475d4

@exah
Copy link

@exah exah commented on 06475d4 Aug 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<3

Please sign in to comment.