commonform-docx 5.5.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,7 @@ It may contain:
18
18
 
19
19
  1. a `title` property whose value is a string
20
20
 
21
- 2. an `edition` property whose value is a string
21
+ 2. an `version` property whose value is a string
22
22
 
23
23
  3. a `hash` property whose value is `true` or `false`
24
24
 
package/bin.js CHANGED
@@ -1,52 +1,55 @@
1
1
  #!/usr/bin/env node
2
- var docopt = require('@kemitchell/docopt').docopt
3
- var fs = require('fs')
4
- var has = require('has')
5
- var path = require('path')
2
+ const docopt = require('@kemitchell/docopt').docopt
3
+ const fs = require('fs')
4
+ const has = require('has')
5
+ const path = require('path')
6
6
 
7
7
  // Parse arguments and options.
8
8
 
9
- var usage = [
9
+ const usage = [
10
10
  'Usage:',
11
11
  ' commonform-docx [options] <FILE>',
12
12
  '',
13
13
  'Options:',
14
- ' -h, --help Show this screen.',
15
- ' -v, --version Show version.',
16
- ' -H, --hash Render form hash',
17
- ' -a, --a4-paper A4 paper.',
18
- ' -b TEXT, --blank-text TEXT Render blanks with custom text.',
19
- ' -d JSON --directions JSON Use directions to fill in blanks',
20
- ' -e EDITION, --edition EDITION Form edition to be rendered',
21
- ' -i, --indent-margins Indent margins, commonwealth style',
22
- ' -l, --left-align-title Align title flush to left margin',
23
- ' -m, --mark-filled Mark filled blanks',
24
- ' -p, --smartify Render Unicode punctuation',
25
- ' -n STYLE, --number STYLE Numbering style [default: decimal]',
26
- ' -r --left-align-body Left-align body paragraphs.',
27
- ' -s PAGES, --signatures PAGES Signature page data',
28
- ' -t TITLE, --title TITLE Render title as <h1>.',
29
- ' -v JSON --values JSON Use values to fill in blanks',
30
- ' -y JSON, --styles JSON Render with custom styles.'
14
+ ' -h, --help Show this screen.',
15
+ ' -v, --version Show version.',
16
+ ' -H, --hash Render form hash',
17
+ ' -a, --a4-paper A4 paper',
18
+ ' -b TEXT, --blank-text TEXT Render blanks with custom text',
19
+ ' --component-style STYLE Change component style [default: both]',
20
+ ' -d JSON --directions JSON Use directions to fill in blanks',
21
+ ' -e VERSION, --form-version VERSION Form version to be rendered',
22
+ ' -i, --indent-margins Indent margins, commonwealth style',
23
+ ' --incorporate-component-text TEXT Verb for component references [default: Incorporate]',
24
+ ' --quote-component-text TEXT Text for introducing quoted components',
25
+ ' -l, --left-align-title Align title flush to left margin',
26
+ ' -m, --mark-filled Mark filled blanks',
27
+ ' -p, --smart Render Unicode punctuation',
28
+ ' -n STYLE, --number STYLE Numbering style [default: decimal]',
29
+ ' -r --left-align-body Left-align body paragraphs.',
30
+ ' -s PAGES, --signatures PAGES Signature page data',
31
+ ' -t TITLE, --title TITLE Render title as <h1>',
32
+ ' -v JSON --values JSON Use values to fill in blanks',
33
+ ' -y JSON, --styles JSON Render with custom styles'
31
34
  ].join('\n')
32
35
 
33
- var parsed = docopt(usage, { version: require('./package.json').version })
36
+ const parsed = docopt(usage, { version: require('./package.json').version })
34
37
 
35
38
  // Parse arguments and options.
36
39
 
37
- var form = readJSON(parsed['<FILE>'])
40
+ const form = readJSON(parsed['<FILE>'])
38
41
 
39
- var values = parsed['--values'] ? readJSON(parsed['--values']) : {}
40
- var directions = parsed['--directions'] ? readJSON(parsed['--directions']) : []
41
- var blanks = require('commonform-prepare-blanks')(values, directions)
42
+ const values = parsed['--values'] ? readJSON(parsed['--values']) : {}
43
+ const directions = parsed['--directions'] ? readJSON(parsed['--directions']) : []
44
+ const blanks = require('commonform-prepare-blanks')(values, directions)
42
45
 
43
- var options = {}
46
+ const options = {}
44
47
 
45
48
  if (parsed['--title']) options.title = parsed['--title']
46
49
 
47
50
  if (parsed['--number']) {
48
- var numberStyle = parsed['--number']
49
- var supportedNumberingStyles = {
51
+ const numberStyle = parsed['--number']
52
+ const supportedNumberingStyles = {
50
53
  rse: 'resolutions-schedules-exhibits-numbering',
51
54
  ase: 'agreement-schedules-exhibits-numbering',
52
55
  pae: 'plan-addenda-exhibits-numbering',
@@ -55,18 +58,18 @@ if (parsed['--number']) {
55
58
  }
56
59
  if (!has(supportedNumberingStyles, numberStyle)) {
57
60
  process.stderr.write([
58
- '"' + numberStyle + '" is not a valid numbering style.',
61
+ `"${numberStyle}" is not a valid numbering style.`,
59
62
  'Valid styles are ' +
60
- Object.keys(supportedNumberingStyles).map(function (s) {
61
- return '"' + s + '"'
62
- }).join(', ') + '.'
63
+ Object.keys(supportedNumberingStyles)
64
+ .map(s => `"${s}"`)
65
+ .join(', ') + '.'
63
66
  ].join('\n') + '\n')
64
67
  process.exit(1)
65
68
  } else {
66
- options.numbering = require(supportedNumberingStyles[numberStyle])
69
+ options.numberStyle = require(supportedNumberingStyles[numberStyle])
67
70
  }
68
71
  } else {
69
- options.numbering = require('decimal-numbering')
72
+ options.numberStyle = require('decimal-numbering')
70
73
  }
71
74
 
72
75
  if (parsed['--signatures']) {
@@ -81,7 +84,7 @@ if (parsed['--styles']) {
81
84
 
82
85
  if (parsed['--title']) options.title = parsed['--title']
83
86
 
84
- if (parsed['--edition']) options.edition = parsed['--edition']
87
+ if (parsed['--form-version']) options.version = parsed['--form-version']
85
88
 
86
89
  if (parsed['--hash']) options.hash = true
87
90
 
@@ -89,21 +92,25 @@ if (parsed['--a4-paper']) options.a4 = true
89
92
 
90
93
  options.indentMargins = parsed['--indent-margins']
91
94
 
92
- options.centerTitle = !parsed['--left-align-title']
95
+ options.leftAlignTitle = parsed['--left-align-title']
93
96
 
94
97
  options.leftAlignBody = parsed['--left-align-body']
95
98
 
96
- options.smartify = !!parsed['--smartify']
99
+ options.smart = !!parsed['--smart']
97
100
 
98
101
  if (parsed['--blank-text']) options.blanks = parsed['--blank-text']
99
102
 
100
103
  if (parsed['--mark-filled']) options.markFilled = true
101
104
 
105
+ options.loadedComponentStyle = parsed['--component-style']
106
+ if (parsed['--quote-component-text']) options.quoteComponentText = parsed['--quote-component-text']
107
+ options.incorporateComponentText = parsed['--incorporate-component-text']
108
+
102
109
  function readJSON (file) {
103
110
  return JSON.parse(fs.readFileSync(path.resolve(file)))
104
111
  }
105
112
 
106
113
  // Render and print.
107
- var rendered = require('./')(form, blanks, options)
114
+ const rendered = require('./')(form, blanks, options)
108
115
 
109
116
  rendered.generateNodeStream().pipe(process.stdout)
package/escape.js CHANGED
@@ -1,12 +1,10 @@
1
- module.exports = function escape (string) {
2
- var special = {
1
+ module.exports = string => {
2
+ const special = {
3
3
  '&amp;': /&/g,
4
4
  '&apos;': /'/g,
5
5
  '&gt;': />/g,
6
6
  '&lt;': /</g,
7
7
  '&quot;': /"/g
8
8
  }
9
- return Object.keys(special).reduce(function (string, escaped) {
10
- return string.replace(special[escaped], escaped)
11
- }, string)
9
+ return Object.keys(special).reduce((string, escaped) => string.replace(special[escaped], escaped), string)
12
10
  }
package/index.js CHANGED
@@ -1,9 +1,10 @@
1
- var JSZip = require('jszip')
2
- var assign = require('object-assign')
3
- var commonformHash = require('commonform-hash')
4
- var smartify = require('commonform-smartify')
1
+ const JSZip = require('jszip')
2
+ const commonformHash = require('commonform-hash')
3
+ const decimalNumbering = require('decimal-numbering')
4
+ const smartify = require('commonform-smartify')
5
5
 
6
- var doc = require('./templates/document')
6
+ const doc = require('./templates/document')
7
+ const docRels = require('./templates/document-relationships')
7
8
 
8
9
  function defaultStyles (smart) {
9
10
  return {
@@ -24,41 +25,67 @@ function defaultStyles (smart) {
24
25
  }
25
26
  }
26
27
 
27
- module.exports = function (form, values, options) {
28
- var title = options.title
29
- var edition = options.edition
30
- var hash = options.hash ? commonformHash(form) : undefined
31
- var centerTitle = options.centerTitle || false
32
- var leftAlignBody = options.leftAlignBody || false
33
- var numberStyle = options.numbering
34
- var indentMargins = options.indentMargins || false
35
- var a4Paper = options.a4 || false
36
- var after = options.after || ''
37
- var smart = options.smartify
38
- var styles = options.styles
39
- ? assign({}, defaultStyles(smart), options.styles)
28
+ module.exports = (
29
+ form,
30
+ values = [],
31
+ {
32
+ a4 = false,
33
+ after = '',
34
+ blanks = { text: '[•]', highlight: 'yellow' },
35
+ hash = false,
36
+ incorporateComponentText = 'Incorporate',
37
+ indentMargins = false,
38
+ leftAlignBody = false,
39
+ leftAlignTitle = false,
40
+ loadedComponentStyle = 'inline',
41
+ markFilled = false,
42
+ numberStyle = decimalNumbering,
43
+ quoteComponentText = 'Quoting for convenience, with any conflicts resolved in favor of the standard:',
44
+ smart,
45
+ styles,
46
+ title,
47
+ version
48
+ }
49
+ ) => {
50
+ styles = styles
51
+ ? Object.assign({}, defaultStyles(smart), styles)
40
52
  : defaultStyles(smart)
41
- var blanks = options.blanks === undefined
42
- ? { text: '[•]', highlight: 'yellow' }
43
- : typeof options.blanks === 'string'
44
- ? { text: options.blanks }
45
- : options.blanks
46
- var markFilled = !!options.markFilled
47
- var scaffold = require('./data/scaffold.json')
48
- scaffold.word['document.xml'] = doc(
53
+ if (typeof blanks === 'string') blanks = { text: blanks }
54
+ hash = hash ? commonformHash(form) : undefined
55
+ const result = doc(
49
56
  smart ? smartify(form) : form,
50
- values, title, edition, hash,
51
- centerTitle, leftAlignBody, numberStyle, indentMargins, a4Paper, after, blanks, markFilled,
52
- styles
57
+ values,
58
+ {
59
+ a4,
60
+ after,
61
+ blanks,
62
+ hash,
63
+ incorporateComponentText,
64
+ indentMargins,
65
+ leftAlignBody,
66
+ leftAlignTitle,
67
+ loadedComponentStyle,
68
+ markFilled,
69
+ numberStyle,
70
+ quoteComponentText,
71
+ smart,
72
+ styles,
73
+ title,
74
+ version
75
+ }
53
76
  )
54
- var zip = new JSZip()
55
- zipObject(zip, scaffold)
77
+ const scaffold = require('./data/scaffold.json')
78
+ const clone = Object.assign({}, scaffold)
79
+ clone.word['document.xml'] = result.xml
80
+ clone.word._rels['document.xml.rels'] = docRels(result.hrefs)
81
+ const zip = new JSZip()
82
+ zipObject(zip, clone)
56
83
  return zip
57
84
  }
58
85
 
59
86
  function zipObject (zip, object) {
60
- Object.keys(object).forEach(function (path) {
61
- var content = object[path]
87
+ Object.keys(object).forEach(path => {
88
+ const content = object[path]
62
89
  // File
63
90
  if (typeof content === 'string') {
64
91
  zip.file(path, content.trim())
package/lint.log ADDED
@@ -0,0 +1,4 @@
1
+
2
+ > commonform-docx@6.0.0 lint
3
+ > standard
4
+
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "commonform-docx",
3
3
  "description": "render Common Forms in Office Open XML (Microsoft Word .docx format)",
4
- "version": "5.5.2",
4
+ "version": "7.0.0",
5
5
  "author": "Kyle E. Mitchell <kyle@kemitchell.com> (http://kemitchell.com)",
6
6
  "bin": "bin.js",
7
7
  "dependencies": {
8
8
  "@kemitchell/docopt": "^1.0.0",
9
9
  "agreement-schedules-exhibits-numbering": "^2.0.0",
10
- "commonform-flatten": "^1.0.0",
10
+ "commonform-flatten": "^2.1.0",
11
11
  "commonform-hash": "^1.0.0",
12
12
  "commonform-prepare-blanks": "^1.0.1",
13
13
  "commonform-smartify": "^1.0.1",
14
14
  "decimal-numbering": "^3.0.2",
15
15
  "has": "^1.0.3",
16
16
  "jszip": "^3.2.1",
17
- "object-assign": "^4.1.1",
17
+ "number-to-words-en": "^1.2.5",
18
18
  "ooxml-signature-pages": "^3.0.2",
19
19
  "outline-numbering": "^2.0.0",
20
20
  "plan-addenda-exhibits-numbering": "^3.0.0",
@@ -23,9 +23,9 @@
23
23
  "devDependencies": {
24
24
  "istanbul": "^0.4.0",
25
25
  "run-series": "^1.1.8",
26
- "standard": "^14.0.2",
26
+ "standard": "^17.0.0",
27
27
  "tape": "^5.0.1",
28
- "textract": "^2.4.0"
28
+ "textract": "^2.5.0"
29
29
  },
30
30
  "keywords": [
31
31
  "Microsoft Office",
@@ -0,0 +1,15 @@
1
+ const escape = require('../escape')
2
+
3
+ module.exports = array => {
4
+ const scaffolded = require('../data/scaffold.json').word._rels['document.xml.rels']
5
+ if (array.length === 0) return scaffolded
6
+ const appended = []
7
+ for (let index = 0; index < array.length; index++) {
8
+ const assignment = array[index]
9
+ appended.push(`<Relationship Id="${assignment.rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="${escape(assignment.url)}" TargetMode="External"/>`)
10
+ }
11
+ return scaffolded.replace(
12
+ '</Relationships>',
13
+ `${appended.join('')}</Relationships>`
14
+ )
15
+ }
@@ -1,9 +1,9 @@
1
- var flatten = require('commonform-flatten')
2
- var hashRun = require('./hash')
3
- var titleRun = require('./title')
4
- var paragraph = require('./paragraph')
1
+ const flatten = require('commonform-flatten')
2
+ const hashRun = require('./hash')
3
+ const titleRun = require('./title')
4
+ const paragraph = require('./paragraph')
5
5
 
6
- var DOCUMENT_XMLNS = (
6
+ const DOCUMENT_XMLNS = (
7
7
  /* jscs:disable maximumLineLength */
8
8
  /* jshint ignore: start */
9
9
  'xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" ' +
@@ -27,7 +27,7 @@ var DOCUMENT_XMLNS = (
27
27
  )
28
28
 
29
29
  function section (a4) {
30
- var returned = '<w:sectPr>'
30
+ let returned = '<w:sectPr>'
31
31
  if (a4) {
32
32
  returned += '<w:pgSz w:w="11907" w:h="16839"/>'
33
33
  } else {
@@ -40,28 +40,35 @@ function section (a4) {
40
40
  return returned
41
41
  }
42
42
 
43
- module.exports = function (
44
- form, values, title, edition, hash,
45
- centerTitle, leftAlignBody, numberStyle, indentMargins, a4Paper, after, blanks, markFilled, styles
46
- ) {
47
- var paragraphs = flatten(form, values)
48
- .map(function (element) {
49
- if (leftAlignBody) element.alignment = 'left'
50
- return paragraph(
51
- element, numberStyle, indentMargins, blanks, markFilled, styles
52
- )
43
+ module.exports = (form, values, options) => {
44
+ // Hyperlinks in documents must refer to Relationships by rId.
45
+ // Set up a running list of HREFs to turn into Relationships,
46
+ // then pass a helper function that assigns rIds to HREFs.
47
+ const hrefs = []
48
+ options.rIdForHREF = url => {
49
+ const rId = `rId${100 + (hrefs.length - 1)}`
50
+ hrefs.push({ rId, url })
51
+ return rId
52
+ }
53
+ const paragraphs = flatten(form, values)
54
+ .map(element => {
55
+ if (options.leftAlignBody) element.alignment = 'left'
56
+ return paragraph(element, options)
53
57
  })
54
58
  .join('')
55
- return (
59
+ const { title, version, hash, after, a4 } = options
60
+ const xml = (
61
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
56
62
  '<w:document ' + DOCUMENT_XMLNS + '>' +
57
63
  '<w:body>' +
58
- (title ? titleRun(title, centerTitle, styles) : '') +
59
- (edition ? titleRun(edition, centerTitle, styles) : '') +
60
- (hash ? hashRun(hash, centerTitle, styles) : '') +
64
+ (title ? titleRun(title, options) : '') +
65
+ (version ? titleRun(version, options) : '') +
66
+ (hash ? hashRun(hash, options) : '') +
61
67
  paragraphs +
62
68
  after +
63
- section(a4Paper) +
69
+ section(a4) +
64
70
  '</w:body>' +
65
71
  '</w:document>'
66
72
  )
73
+ return { xml, hrefs }
67
74
  }
package/templates/hash.js CHANGED
@@ -1,10 +1,9 @@
1
- var paragraph = require('./paragraph')
1
+ const paragraph = require('./paragraph')
2
2
 
3
- module.exports = function (string, center, styles) {
3
+ module.exports = (string, options) => {
4
4
  return paragraph({
5
- alignment: center ? 'center' : 'left',
6
- depth: 1,
7
5
  title: true,
6
+ alignment: options.leftAlignTitle ? 'left' : 'center',
8
7
  content: [{ monospaced: string }]
9
- }, null, null, null, null, styles)
8
+ }, options)
10
9
  }
@@ -1,11 +1,13 @@
1
- var has = require('has')
2
- var run = require('./run')
3
- var tag = require('./tag')
1
+ const escape = require('../escape')
2
+ const has = require('has')
3
+ const numberToWords = require('number-to-words-en')
4
+ const run = require('./run')
5
+ const tag = require('./tag')
4
6
 
5
7
  // Half an inch in twentieths of a point
6
- var HALF_INCH = 720
8
+ const HALF_INCH = 720
7
9
 
8
- var alignments = {
10
+ const alignments = {
9
11
  left: 'start',
10
12
  right: 'end',
11
13
  center: 'center',
@@ -13,113 +15,169 @@ var alignments = {
13
15
  distribute: 'distribute'
14
16
  }
15
17
 
16
- var properties = function (o, number, indentMargins) {
17
- // CAVEAT: The order of properties is important.
18
- var depth = ('heading' in o || 'numbering' in o || 'title' in o)
18
+ function properties (o, number, indentMargins) {
19
+ if (o.title) {
20
+ // Titles don't have margins or indentation.
21
+ return tag('w:pPr', `<w:jc w:val="${alignments[o.alignment]}" />`)
22
+ }
23
+ const depth = ('heading' in o || 'numbering' in o)
19
24
  ? o.depth
20
25
  : o.depth + 1
21
- var alignment = o.alignment
26
+ // CAVEAT: The order of properties is important.
22
27
  return tag('w:pPr',
23
28
  '<w:ind' +
24
29
  (
25
30
  indentMargins
26
31
  ? (
27
- number.length === 0
28
- ? (' w:left="' + ((depth - 2) * HALF_INCH) + '"')
29
- : (
30
- ' w:left="' + ((depth - 1) * HALF_INCH) + '"' +
31
- ' w:firstLine="-' + HALF_INCH + '"'
32
- )
33
- )
32
+ number.length === 0
33
+ ? (
34
+ ' w:left="' + ((depth - 2) * HALF_INCH) + '"'
35
+ )
36
+ : (
37
+ ' w:left="' + ((depth - 1) * HALF_INCH) + '"' +
38
+ ' w:firstLine="-' + HALF_INCH + '"'
39
+ )
40
+ )
34
41
  : (' w:firstLine="' + ((depth - 1) * HALF_INCH) + '"')
35
42
  ) + ' />' +
36
- '<w:jc w:val="' + alignments[alignment] + '" />'
43
+ '<w:jc w:val="' + alignments[o.alignment] + '" />'
37
44
  )
38
45
  }
39
46
 
40
- var TAB = '<w:r><w:tab/></w:r>'
47
+ const TAB = '<w:r><w:tab/></w:r>'
41
48
 
42
- module.exports = function (
43
- element, numberStyle, indentMargins, blanks, markFilled, styles
44
- ) {
49
+ module.exports = (element, options) => {
45
50
  if (!has(element, 'alignment')) {
46
- element.alignment = styles.alignment || 'justify'
51
+ element.alignment = options.styles.alignment || 'justify'
47
52
  }
48
- var number = has(element, 'numbering')
49
- ? numberStyle(element.numbering, true)
53
+ const number = has(element, 'numbering')
54
+ ? options.numberStyle(element.numbering, true)
50
55
  : ''
51
- var conspicuous = has(element, 'conspicuous')
52
- return tag('w:p',
53
- properties(element, number, indentMargins) +
54
- (
55
- number
56
- ? makeRun(number, false) + TAB
57
- : ''
58
- ) + (
59
- has(element, 'heading')
60
- ? (
61
- makeRun({ caption: element.heading }, conspicuous) +
62
- (/\.$/.test(element.heading) ? '' : makeRun('.', false)) +
63
- (element.content.length === 0 ? '' : makeRun(' ', false))
56
+ const conspicuous = has(element, 'conspicuous')
57
+ const hasComponent = has(element, 'component')
58
+ const hasContent = has(element, 'content')
59
+ let returned = '<w:p>'
60
+ returned += properties(element, number, options.indentMargins)
61
+ returned += number ? makeRun(number, false) + TAB : ''
62
+ if (has(element, 'heading')) {
63
+ returned += makeRun({ caption: element.heading }, conspicuous)
64
+ if (!/\.$/.test(element.heading)) {
65
+ returned += makeRun('.', false)
66
+ }
67
+ if ((hasComponent && !hasContent) || element.content.length === 0) {
68
+ // pass
69
+ } else {
70
+ returned += makeRun(' ', false)
71
+ }
72
+ }
73
+ if (hasComponent) {
74
+ if (hasContent) {
75
+ const style = options.loadedComponentStyle
76
+ if (style === 'both') {
77
+ returned += componentReference(element.reference, element.component)
78
+ returned += makeRun(' ' + options.quoteComponentText)
79
+ returned += '</w:p><w:p>'
80
+ returned += properties(
81
+ Object.assign({}, element, { depth: element.depth + 1 }),
82
+ number,
83
+ options.indentMargins
64
84
  )
65
- : ''
66
- ) +
67
- (
68
- has(element, 'repository') // component
69
- ? componentToContent(element)
70
- .map(function (element) {
71
- return makeRun(element, conspicuous)
72
- })
73
- .join('')
74
- : element.content
75
- .map(function (element) {
76
- return makeRun(element, conspicuous)
77
- })
78
- .join('')
79
- )
80
- )
85
+ returned += childContent({ content: element.content })
86
+ } else if (style === 'copy') {
87
+ returned += childContent({ content: element.content })
88
+ } else if (style === 'reference') {
89
+ returned += componentReference(element.reference, element.component)
90
+ } else {
91
+ throw new Error('Uknown Loaded Component Style: ' + style)
92
+ }
93
+ } else {
94
+ returned += componentReference(element)
95
+ }
96
+ } else {
97
+ returned += childContent(element)
98
+ }
99
+ returned += '</w:p>'
100
+ return returned
101
+
102
+ function childContent (element) {
103
+ const conspicuous = has(element, 'conspicuous')
104
+ return element.content
105
+ .map(element => makeRun(element, conspicuous, options))
106
+ .join('')
107
+ }
108
+
81
109
  function makeRun (element, conspicuous) {
82
- return run(element, numberStyle, conspicuous, blanks, markFilled, styles)
110
+ return run(element, conspicuous, options)
83
111
  }
84
- }
85
112
 
86
- function componentToContent (component) {
87
- var url = 'https://' + [
88
- component.repository,
89
- component.publisher,
90
- component.project,
91
- component.edition
92
- ].map(encodeURIComponent).join('/')
93
- var returned = []
94
- var substitutions = component.substitutions
95
- var hasSubstitutions = (
96
- Object.keys(substitutions.terms).length > 0 ||
97
- Object.keys(substitutions.headings).length > 0
98
- )
99
- var firstString = url
100
- if (hasSubstitutions) {
101
- if (component.upgrade) firstString += ' with updates and corrections, replacing '
102
- else firstString += ' replacing '
103
- returned.push(firstString)
104
- var substitutionContent = []
105
- Object.keys(substitutions.terms).forEach(function (from) {
106
- var to = substitutions.terms[from]
107
- substitutionContent.push(from + ' with ', { use: to })
108
- })
109
- Object.keys(substitutions.headings).forEach(function (from) {
110
- var to = substitutions.headings[from]
111
- substitutionContent.push(from + ' with ', { referene: to })
112
- })
113
- var length = substitutionContent.length
114
- for (var index = 2; index < length - 1; index += 2) {
115
- substitutionContent[index] = ', ' + substitutionContent[index]
113
+ function componentReference (component, meta) {
114
+ const href = component.component + '/' + component.version
115
+ const returned = [makeRun(options.incorporateComponentText + ' ')]
116
+ const rId = options.rIdForHREF(href)
117
+ const link = '<w:hyperlink r:id="' + rId + '" w:history="1"><w:r><w:rPr><w:color w:val="0000EE"/><w:u w:val="single"/></w:rPr><w:t>' + escape(href) + '</w:t></w:r></w:hyperlink>'
118
+ if (meta) {
119
+ returned.push(
120
+ makeRun(meta.publisher + ' ' + meta.name + ' Version ' + meta.version + ' ('),
121
+ link,
122
+ makeRun(')')
123
+ )
124
+ } else {
125
+ returned.push(link)
116
126
  }
117
- substitutionContent.forEach(function (element) {
118
- returned.push(element)
119
- })
120
- } else {
121
- if (component.upgrade) firstString += ' with updates and corrections'
122
- returned.push(firstString)
127
+ const substitutions = component.substitutions
128
+ const hasSubstitutions = (
129
+ Object.keys(substitutions.terms).length > 0 ||
130
+ Object.keys(substitutions.headings).length > 0
131
+ )
132
+ if (hasSubstitutions) {
133
+ returned.push(makeRun(' substituting '))
134
+ const phrases = []
135
+ Object.keys(substitutions.terms).forEach(from => {
136
+ const to = substitutions.terms[from]
137
+ phrases.push(
138
+ makeRun('the term ') +
139
+ makeRun({ use: to }) +
140
+ makeRun(' for the term ') +
141
+ makeRun({ use: from })
142
+ )
143
+ })
144
+ Object.keys(substitutions.headings).forEach(from => {
145
+ const to = substitutions.headings[from]
146
+ phrases.push(
147
+ makeRun('references to ') +
148
+ makeRun({ use: to }) +
149
+ makeRun(' for references to ') +
150
+ makeRun({ use: from })
151
+ )
152
+ })
153
+ Object.keys(substitutions.blanks).forEach(number => {
154
+ const value = substitutions.blanks[number]
155
+ phrases.push(
156
+ makeRun(quote(value)) +
157
+ makeRun(' for the ' + numberToWords.toWordsOrdinal(parseInt(number)) + ' blank')
158
+ )
159
+ })
160
+ const length = phrases.length
161
+ if (length === 1) {
162
+ returned.push(phrases[0])
163
+ } else if (length === 2) {
164
+ returned.push(phrases[0])
165
+ returned.push(makeRun(' and '))
166
+ returned.push(phrases[1])
167
+ } else {
168
+ returned.push(
169
+ phrases.slice(0, -1).join(makeRun(', ')) +
170
+ makeRun(', and ') +
171
+ phrases[phrases.length - 1]
172
+ )
173
+ }
174
+ }
175
+ returned.push(makeRun('.'))
176
+ return returned.join('')
177
+ }
178
+
179
+ function quote (string) {
180
+ if (options.smart) return '“' + string + '”'
181
+ else return '"' + string + '"'
123
182
  }
124
- return returned
125
183
  }
package/templates/run.js CHANGED
@@ -1,91 +1,83 @@
1
- var assign = require('object-assign')
2
- var escape = require('../escape')
3
- var has = require('has')
4
- var tag = require('./tag')
1
+ const escape = require('../escape')
2
+ const has = require('has')
3
+ const tag = require('./tag')
5
4
 
6
- var defaults = {
5
+ const defaults = {
7
6
  highlight: false,
8
7
  bold: false,
9
8
  italic: false,
10
9
  underline: false
11
10
  }
12
11
 
13
- module.exports = function run (
14
- element, numberStyle, conspicuous, blanks, markFilled, styles
15
- ) {
16
- var properties = assign({}, defaults)
12
+ module.exports = function run (element, conspicuous, options) {
13
+ const { styles } = options
14
+ const properties = Object.assign({}, defaults)
17
15
  if (conspicuous === true) {
18
- assign(properties, styles.conspicuous)
16
+ Object.assign(properties, styles.conspicuous)
19
17
  }
20
- var text = ''
18
+ let text = ''
21
19
  /* istanbul ignore else */
22
20
  if (typeof element === 'string') {
23
- assign(properties, styles.text)
21
+ Object.assign(properties, styles.text)
24
22
  text = element
25
23
  } else if (has(element, 'caption')) {
26
- assign(properties, styles.heading)
24
+ Object.assign(properties, styles.heading)
27
25
  text = element.caption
28
26
  } else if (has(element, 'title')) {
29
- assign(properties, styles.title)
27
+ Object.assign(properties, styles.title)
30
28
  text = element.title
31
29
  } else if (has(element, 'monospaced')) {
32
- assign(properties, styles.monospaced)
30
+ Object.assign(properties, styles.monospaced)
33
31
  text = element.monospaced
34
32
  } else if (has(element, 'definition')) {
35
- var term = element.definition
33
+ const term = element.definition
36
34
  return (
37
35
  (
38
36
  styles.beforeDefinition
39
- ? run(
40
- styles.beforeDefinition, numberStyle, conspicuous, blanks,
41
- markFilled, styles
42
- )
37
+ ? run(styles.beforeDefinition, conspicuous, options)
43
38
  : ''
44
39
  ) +
45
40
  tag('w:r', runProperties(styles.definition) + runText(term)) +
46
41
  (
47
42
  styles.afterDefinition
48
- ? run(
49
- styles.afterDefinition, numberStyle, conspicuous, blanks,
50
- markFilled, styles
51
- )
43
+ ? run(styles.afterDefinition, conspicuous, options)
52
44
  : ''
53
45
  )
54
46
  )
55
47
  } else if (has(element, 'blank')) {
56
- assign(properties, styles.text)
48
+ Object.assign(properties, styles.text)
57
49
  if (element.blank !== undefined) {
58
50
  text = element.blank
59
- if (markFilled) assign(properties, styles.filled)
51
+ if (options.markFilled) Object.assign(properties, styles.filled)
60
52
  } else {
61
- text = blanks.text
62
- if (blanks.highlight) assign(properties, styles.highlighted)
53
+ text = options.blanks.text
54
+ if (options.blanks.highlight) Object.assign(properties, styles.highlighted)
63
55
  }
64
56
  } else if (has(element, 'use')) {
65
- assign(properties, styles.use)
57
+ Object.assign(properties, styles.use)
66
58
  text = element.use
67
59
  } else if (has(element, 'heading')) {
68
- var numbering = element.numbering
69
- var heading = element.heading
60
+ const numbering = element.numbering
61
+ const heading = element.heading
70
62
  if (
71
63
  has(element, 'broken') ||
72
64
  has(element, 'ambiguous')
73
65
  ) {
74
- assign(properties, styles.broken)
66
+ Object.assign(properties, styles.broken)
75
67
  text = '[Broken Cross-Reference to "' + heading + '"]'
76
68
  } else {
77
- text = numberStyle(numbering)
69
+ text = options.numberStyle(numbering)
78
70
  return (
79
71
  // Underlined reference.
80
72
  tag(
81
73
  'w:r',
82
- runProperties(assign({}, properties, styles.reference)) +
74
+ runProperties(Object.assign({}, properties, styles.reference)) +
83
75
  runText(text)
84
76
  ) +
85
77
  // Name of referenced section in parentheses.
86
78
  tag(
87
79
  'w:r',
88
- runProperties(assign({}, properties, styles.referenceHeading)) +
80
+ runProperties(Object.assign({}, properties, styles.referenceHeading)) +
89
81
  runText(' (' + heading + ')')
90
82
  )
91
83
  )
@@ -98,36 +90,36 @@ module.exports = function run (
98
90
 
99
91
  function underlineFlag (underline) {
100
92
  if (typeof underline === 'string') {
101
- return '<w:u w:val="' + underline + '"/>'
93
+ return `<w:u w:val="${underline}"/>`
102
94
  } else {
103
95
  return '<w:u w:val="none"/>'
104
96
  }
105
97
  }
106
98
 
107
99
  function highlightFlag (highlight) {
108
- return '<w:highlight w:val="' + highlight + '"/>'
100
+ return `<w:highlight w:val="${highlight}"/>`
109
101
  }
110
102
 
111
103
  function flag (name, value) {
112
- return value ? '<w:' + name + '/>' : ''
104
+ return value ? `<w:${name}/>` : ''
113
105
  }
114
106
 
115
- function runProperties (options) {
107
+ function runProperties (style) {
116
108
  return tag('w:rPr',
117
109
  (
118
- flag('b', options.bold || false) +
119
- flag('i', options.italic || false) +
120
- (options.highlight ? highlightFlag(options.highlight) : '') +
121
- underlineFlag(options.underline || false) +
110
+ flag('b', style.bold || false) +
111
+ flag('i', style.italic || false) +
112
+ (style.highlight ? highlightFlag(style.highlight) : '') +
113
+ underlineFlag(style.underline || false) +
122
114
  (
123
- options.monospaced
115
+ style.monospaced
124
116
  ? (
125
- '<w:rFonts ' +
126
- 'w:ascii="Courier New" ' +
127
- 'w:hAnsi="Courier New" ' +
128
- 'w:cs="Courier New"/>' +
129
- '<w:sz w:val="20"/>'
130
- )
117
+ '<w:rFonts ' +
118
+ 'w:ascii="Courier New" ' +
119
+ 'w:hAnsi="Courier New" ' +
120
+ 'w:cs="Courier New"/>' +
121
+ '<w:sz w:val="20"/>'
122
+ )
131
123
  : ''
132
124
  )
133
125
  )
@@ -135,5 +127,5 @@ function runProperties (options) {
135
127
  }
136
128
 
137
129
  function runText (text) {
138
- return '<w:t xml:space="preserve">' + escape(text) + '</w:t>'
130
+ return `<w:t xml:space="preserve">${escape(text)}</w:t>`
139
131
  }
package/templates/tag.js CHANGED
@@ -1,3 +1,3 @@
1
- module.exports = function (name, content) {
2
- return '<' + name + '>' + content + '</' + name + '>'
1
+ module.exports = (name, content) => {
2
+ return `<${name}>${content}</${name}>`
3
3
  }
@@ -1,12 +1,11 @@
1
- var paragraph = require('./paragraph')
1
+ const paragraph = require('./paragraph')
2
2
 
3
- module.exports = function (string, center, styles) {
4
- var argument = {
5
- alignment: 'left',
6
- depth: 1,
3
+ module.exports = (string, options) => {
4
+ const argument = {
7
5
  title: true,
6
+ alignment: 'center',
8
7
  content: [{ title: string }]
9
8
  }
10
- if (center) argument.alignment = 'center'
11
- return paragraph(argument, null, null, null, null, styles)
9
+ if (options.leftAlignTitle) argument.alignment = 'left'
10
+ return paragraph(argument, options)
12
11
  }
package/test.log CHANGED
@@ -1,13 +1,13 @@
1
1
 
2
- > commonform-docx@5.5.1 pretest
2
+ > commonform-docx@6.0.0 pretest
3
3
  > npm run prepublish
4
4
 
5
5
 
6
- > commonform-docx@5.5.1 prepublish
6
+ > commonform-docx@6.0.0 prepublish
7
7
  > node build/scaffold.js data/scaffold.docx > data/scaffold.json
8
8
 
9
9
 
10
- > commonform-docx@5.5.1 test
10
+ > commonform-docx@6.0.0 test
11
11
  > tape test.js
12
12
 
13
13
  TAP version 13
@@ -27,69 +27,72 @@ ok 9 term appears in output
27
27
  ok 10 no render error
28
28
  ok 11 no textract error
29
29
  ok 12 reference appears in output
30
- # omits period after heading ending w/ period
30
+ # handles components without headings
31
31
  ok 13 no render error
32
- ok 14 no textract error
33
- ok 15 double period does not appear in output
32
+ # handles components with substitutions
33
+ ok 14 no render error
34
+ # omits period after heading ending w/ period
35
+ ok 15 no render error
36
+ ok 16 no textract error
37
+ ok 17 double period does not appear in output
34
38
  # adds space between heading and defined term
35
- ok 16 no render error
36
- 1 of 1 1. Heading. "Term"
37
- ok 17 no textract error
38
- ok 18 space between heading and term
39
+ ok 18 no render error
40
+ ok 19 no textract error
41
+ ok 20 space between heading and term
39
42
  # adds space between heading and text
40
- ok 19 no render error
41
- ok 20 no textract error
42
- ok 21 space between heading and text
43
+ ok 21 no render error
44
+ ok 22 no textract error
45
+ ok 23 space between heading and text
43
46
  # renders broken references
44
- ok 22 no render error
45
- ok 23 no textract error
46
- ok 24 reference appears in output
47
+ ok 24 no render error
48
+ ok 25 no textract error
49
+ ok 26 reference appears in output
47
50
  # fills blanks
48
- ok 25 no render error
49
- ok 26 no textract error
50
- ok 27 value appears in output
51
+ ok 27 no render error
52
+ ok 28 no textract error
53
+ ok 29 value appears in output
51
54
  # custom blank text
52
- ok 28 no render error
53
- ok 29 no textract error
54
- ok 30 value appears in output
55
+ ok 30 no render error
56
+ ok 31 no textract error
57
+ ok 32 value appears in output
55
58
  # renders empty blank placeholders
56
- ok 31 no render error
57
- ok 32 no textract error
58
- ok 33 placeholder appears in output
59
+ ok 33 no render error
60
+ ok 34 no textract error
61
+ ok 35 placeholder appears in output
59
62
  # renders custom empty blank placeholders
60
- ok 34 no render error
61
- ok 35 no textract error
62
- ok 36 placeholder appears in output
63
+ ok 36 no render error
64
+ ok 37 no textract error
65
+ ok 38 placeholder appears in output
63
66
  # renders custom empty blank placeholders
64
- ok 37 no render error
65
- ok 38 no textract error
66
- ok 39 placeholder appears in output
67
+ ok 39 no render error
68
+ ok 40 no textract error
69
+ ok 41 placeholder appears in output
67
70
  # renders conspicuous text
68
- ok 40 no render error
69
- ok 41 no textract error
70
- ok 42 conspicuous text appears in output
71
+ ok 42 no render error
72
+ ok 43 no textract error
73
+ ok 44 conspicuous text appears in output
71
74
  # renders titles
72
- ok 43 no render error
73
- ok 44 no textract error
74
- ok 45 title appears in output
75
+ ok 45 no render error
76
+ ok 46 no textract error
77
+ ok 47 title appears in output
75
78
  # renders centered titles
76
- ok 46 no render error
77
- ok 47 no textract error
78
- ok 48 title appears in output
79
- # renders editions
80
- ok 49 no render error
81
- ok 50 no textract error
82
- ok 51 edition appears in output
79
+ ok 48 no render error
80
+ ok 49 no textract error
81
+ ok 50 title appears in output
82
+ # renders versions
83
+ ok 51 no render error
84
+ ok 52 no textract error
85
+ ok 53 version appears in output
83
86
  # renders hashes
84
- ok 52 no render error
85
- ok 53 no textract error
86
- ok 54 hash symbol appears in output
87
+ ok 54 no render error
88
+ ok 55 no textract error
89
+ ok 56 hash symbol appears in output
87
90
  # throws for invalid content
88
- ok 55 throw an error
91
+ ok 57 throw an error
89
92
 
90
- 1..55
91
- # tests 55
92
- # pass 55
93
+ 1..57
94
+ # tests 57
95
+ # pass 57
93
96
 
94
97
  # ok
95
98