UNPKG

3.21 kBJavaScriptView Raw
1/**
2 * @module create-prefix-transform-stream
3 * @author Toru Nagashima
4 * @copyright 2016 Toru Nagashima. All rights reserved.
5 * See LICENSE file in root directory for full license.
6 */
7"use strict"
8
9//------------------------------------------------------------------------------
10// Requirements
11//------------------------------------------------------------------------------
12
13const stream = require("stream")
14
15//------------------------------------------------------------------------------
16// Helpers
17//------------------------------------------------------------------------------
18
19const ALL_BR = /\n/g
20
21/**
22 * The transform stream to insert a specific prefix.
23 *
24 * Several streams can exist for the same output stream.
25 * This stream will insert the prefix if the last output came from other instance.
26 * To do that, this stream is using a shared state object.
27 *
28 * @private
29 */
30class PrefixTransform extends stream.Transform {
31 /**
32 * @param {string} prefix - A prefix text to be inserted.
33 * @param {object} state - A state object.
34 * @param {string} state.lastPrefix - The last prefix which is printed.
35 * @param {boolean} state.lastIsLinebreak -The flag to check whether the last output is a line break or not.
36 */
37 constructor(prefix, state) {
38 super()
39
40 this.prefix = prefix
41 this.state = state
42 }
43
44 /**
45 * Transforms the output chunk.
46 *
47 * @param {string|Buffer} chunk - A chunk to be transformed.
48 * @param {string} _encoding - The encoding of the chunk.
49 * @param {function} callback - A callback function that is called when done.
50 * @returns {void}
51 */
52 _transform(chunk, _encoding, callback) {
53 const prefix = this.prefix
54 const nPrefix = `\n${prefix}`
55 const state = this.state
56 const firstPrefix =
57 state.lastIsLinebreak ? prefix :
58 (state.lastPrefix !== prefix) ? "\n" :
59 /* otherwise */ ""
60 const prefixed = `${firstPrefix}${chunk}`.replace(ALL_BR, nPrefix)
61 const index = prefixed.indexOf(prefix, Math.max(0, prefixed.length - prefix.length))
62
63 state.lastPrefix = prefix
64 state.lastIsLinebreak = (index !== -1)
65
66 callback(null, (index !== -1) ? prefixed.slice(0, index) : prefixed)
67 }
68}
69
70//------------------------------------------------------------------------------
71// Public API
72//------------------------------------------------------------------------------
73
74/**
75 * Create a transform stream to insert the specific prefix.
76 *
77 * Several streams can exist for the same output stream.
78 * This stream will insert the prefix if the last output came from other instance.
79 * To do that, this stream is using a shared state object.
80 *
81 * @param {string} prefix - A prefix text to be inserted.
82 * @param {object} state - A state object.
83 * @param {string} state.lastPrefix - The last prefix which is printed.
84 * @param {boolean} state.lastIsLinebreak -The flag to check whether the last output is a line break or not.
85 * @returns {stream.Transform} The created transform stream.
86 */
87module.exports = function createPrefixTransform(prefix, state) {
88 return new PrefixTransform(prefix, state)
89}