mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-11 01:29:59 -06:00
* renames * Refactor proxy into own package, implement middleware pattern don't need these mocha opts anymore fix test no more zunder READMEs fix test * pass request by reference * fix cors path * Move replace_stream to proxy, concat-stream util in network * Pin dependency versions * Revert addDefaultPort behavior * Add READMEs for proxy, network * Update README.md * eslint --fix * set to null not undefined * use delete and bump node types * import cors from package now * parse-domain@2.3.4 * proxy package needs common-tags * move pumpify dep * load through where it's needed, remove unused passthru_stream * remove unneeded getbuffer call Co-authored-by: Gleb Bahmutov <gleb.bahmutov@gmail.com>
81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import through from 'through'
|
|
|
|
const GraphemeSplitter = require('grapheme-splitter')
|
|
|
|
interface IGraphemeSplitter {
|
|
nextBreak: (string: string, at: number) => number
|
|
}
|
|
|
|
const splitter: IGraphemeSplitter = new GraphemeSplitter()
|
|
|
|
/**
|
|
* UTF-8 grapheme aware stream replacer
|
|
* https://github.com/cypress-io/cypress/pull/4984
|
|
*/
|
|
export function replaceStream (patterns: RegExp | RegExp[], replacements: string | string[], options = { maxTailLength: 100 }) {
|
|
if (!Array.isArray(patterns)) {
|
|
patterns = [patterns]
|
|
}
|
|
|
|
if (!Array.isArray(replacements)) {
|
|
replacements = [replacements]
|
|
}
|
|
|
|
let tail = ''
|
|
|
|
return through(function write (this: InternalStream, chunk) {
|
|
let emitted = false
|
|
|
|
const emitTailUpTo = (index) => {
|
|
emitted = true
|
|
this.queue(tail.slice(0, index))
|
|
tail = tail.slice(index)
|
|
}
|
|
|
|
chunk = chunk.toString('utf8')
|
|
|
|
tail = tail + chunk
|
|
|
|
let replacementEndIndex = 0
|
|
|
|
;(patterns as RegExp[]).forEach((pattern, i) => {
|
|
const replacement = replacements[i]
|
|
|
|
tail = tail.replace(pattern, function replacer (match) {
|
|
// ugly, but necessary due to bizarre function signature of String#replace
|
|
const offset = arguments[arguments.length - 2] // eslint-disable-line prefer-rest-params
|
|
|
|
if (offset + replacement.length > replacementEndIndex) {
|
|
replacementEndIndex = offset + replacement.length
|
|
}
|
|
|
|
return match.replace(pattern, replacement)
|
|
})
|
|
})
|
|
|
|
// if a replacement did occur, we should emit up to the end of what was replaced
|
|
if (replacementEndIndex) {
|
|
emitTailUpTo(replacementEndIndex)
|
|
}
|
|
|
|
// if we're overflowing max chars, emit the overflow at the beginning
|
|
if (tail.length > options.maxTailLength) {
|
|
// the maximum width of a unicode char is 4
|
|
// use grapheme-splitter to find a good breaking point
|
|
const breakableAt = splitter.nextBreak(tail, Math.max(0, tail.length - options.maxTailLength - 4))
|
|
|
|
emitTailUpTo(breakableAt)
|
|
}
|
|
|
|
if (!emitted) {
|
|
// this.queue('')
|
|
}
|
|
}, function end (this: InternalStream) {
|
|
if (tail.length) {
|
|
this.queue(tail)
|
|
}
|
|
|
|
this.queue(null)
|
|
})
|
|
}
|