diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:01:11 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:02:09 +0200 |
commit | 363723fc84f7b8477592e0105aeb331ec9a017af (patch) | |
tree | 29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/@concordance/react | |
parent | 5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff) |
node_modules
Diffstat (limited to 'node_modules/@concordance/react')
-rw-r--r-- | node_modules/@concordance/react/LICENSE | 14 | ||||
-rw-r--r-- | node_modules/@concordance/react/README.md | 20 | ||||
-rw-r--r-- | node_modules/@concordance/react/index.js | 75 | ||||
-rw-r--r-- | node_modules/@concordance/react/lib/diffShallow.js | 239 | ||||
-rw-r--r-- | node_modules/@concordance/react/lib/elementFactory.js | 349 | ||||
-rw-r--r-- | node_modules/@concordance/react/lib/escapeText.js | 10 | ||||
-rw-r--r-- | node_modules/@concordance/react/lib/testJsonFactory.js | 59 | ||||
-rw-r--r-- | node_modules/@concordance/react/package.json | 80 |
8 files changed, 846 insertions, 0 deletions
diff --git a/node_modules/@concordance/react/LICENSE b/node_modules/@concordance/react/LICENSE new file mode 100644 index 000000000..a192d7dbf --- /dev/null +++ b/node_modules/@concordance/react/LICENSE @@ -0,0 +1,14 @@ +ISC License (ISC) +Copyright (c) 2017, Mark Wubben <mark@novemberborn.net> (novemberborn.net) + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/node_modules/@concordance/react/README.md b/node_modules/@concordance/react/README.md new file mode 100644 index 000000000..baf16efcf --- /dev/null +++ b/node_modules/@concordance/react/README.md @@ -0,0 +1,20 @@ +# @concordance/react + +React plugin for [Concordance](https://github.com/concordancejs/concordance). + +Allows +[`React.createElement()`](https://facebook.github.io/react/docs/react-api.html#createelement) +objects to be compared, formatted, diffed and serialized. Also supports +`toJSON()` renderings of +[`react-test-renderer`](https://www.npmjs.com/package/react-test-renderer). +These may be compared to `React.createElement()` objects. + +When comparing [React +component](https://facebook.github.io/react/docs/components-and-props.html) +elements, the element type is compared by identity. After deserialization the +element types are compared by function name, taking into account whether +serialization and / or comparison is done using Node.js 4, which has less +reliable support for function names. + +Component elements are formatted with a ⍟ character after the element +name. Properties and children are formatted by [Concordance](https://github.com/concordancejs/concordance). diff --git a/node_modules/@concordance/react/index.js b/node_modules/@concordance/react/index.js new file mode 100644 index 000000000..47ec117fa --- /dev/null +++ b/node_modules/@concordance/react/index.js @@ -0,0 +1,75 @@ +'use strict' + +const pkg = require('./package.json') +const elementFactory = require('./lib/elementFactory') +const testJsonFactory = require('./lib/testJsonFactory') + +// Must be unique across all registered plugins. +exports.name = pkg.name + +// Expected API version to be passed to register(). +exports.apiVersion = 1 + +// Expected minimal version of Concordance. Concordance will increment its API +// version for breaking changes, this is useful if you rely on features or +// patches that were introduced in a specific version of Concordance. +exports.minimalConcordanceVersion = '1.0.0' + +// Plugin-specific version of its serialization output. +exports.serializerVersion = 1 + +exports.theme = { + react: { + functionType: '\u235F', + openTag: { + start: '<', + end: '>', + selfClose: '/', + selfCloseVoid: ' /' + }, + closeTag: { + open: '</', + close: '>' + }, + tagName: {open: '', close: ''}, + attribute: { + separator: '=', + value: { + openBracket: '{', + closeBracket: '}', + string: { + line: {open: '"', close: '"', escapeQuote: '"'} + } + } + }, + child: { + openBracket: '{', + closeBracket: '}', + string: { + line: {open: '', close: '', escapeQuote: ''}, + multiline: {start: '', end: '', escapeQuote: ''} + } + } + } +} + +const ELEMENT = Symbol.for('react.element') +const TEST_JSON = Symbol.for('react.test.json') + +function register (api) { + const reactTags = new Set() + const element = elementFactory(api, reactTags) + const testJson = testJsonFactory(api, element) + + api.addDescriptor(0x01, element.tag, element.deserialize) + api.addDescriptor(0x02, testJson.tag, testJson.deserialize) + + reactTags.add(element.tag).add(testJson.tag) + + return value => { + if (value.$$typeof === ELEMENT) return element.describe + if (value.$$typeof === TEST_JSON) return testJson.describe + return null + } +} +exports.register = register diff --git a/node_modules/@concordance/react/lib/diffShallow.js b/node_modules/@concordance/react/lib/diffShallow.js new file mode 100644 index 000000000..4eeb4d4d3 --- /dev/null +++ b/node_modules/@concordance/react/lib/diffShallow.js @@ -0,0 +1,239 @@ +'use strict' + +function diffShallow (api, actual, expected, theme, indent) { + const childBuffer = api.lineBuilder.buffer() + const propertyBuffer = api.lineBuilder.buffer() + + return { + append (formatted, origin) { + if (origin.isItem === true) { + childBuffer.append(formatted) + } else { + propertyBuffer.append(formatted) + } + }, + + finalize: () => { + const namesAreEqual = actual.compareNames(expected) + const actualName = actual.formatName(theme) + const expectedName = expected.formatName(theme) + + const openTag = theme.react.openTag + const innerIndentation = indent.increase() + + const allChildren = childBuffer.withFirstPrefixed(innerIndentation) + const children = allChildren.decompose() + + const allProperties = propertyBuffer.withFirstPrefixed(innerIndentation) + const properties = allProperties.decompose() + // If the first properties are also the last, and either side has no + // children, ensure the properties are treated as being last. This + // leads to a better balanced diff. + if (properties.remaining.isEmpty && (!actual.hasChildren || !expected.hasChildren)) { + properties.last = properties.first + properties.first = {actual: api.lineBuilder.buffer(), expected: api.lineBuilder.buffer()} + } + + const result = api.lineBuilder.buffer() + + // Create a custom diff that is as neat as possible. It's likely + // there's a generic algorithm that can be used, but for expediency's + // sake handles all possible diffs by brute force instead. + if (actual.hasProperties && expected.hasProperties) { + if (namesAreEqual) { + result + .append(api.lineBuilder.first(openTag.start + actualName)) + .append(properties.first.actual.stripFlags()) + .append(properties.first.expected.stripFlags()) + } else { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName)) + .append(properties.first.actual.stripFlags()) + .append(api.lineBuilder.expected.first(openTag.start + expectedName)) + .append(properties.first.expected.stripFlags()) + } + result.append(properties.remaining.stripFlags()) + + if (actual.hasChildren && expected.hasChildren) { + result + .append(properties.last.actual.stripFlags()) + .append(properties.last.expected.stripFlags()) + .append(api.lineBuilder.line(indent + openTag.end)) + + if (namesAreEqual) { + result + .append(allChildren.stripFlags()) + .append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + } else { + result + .append(children.first.actual.stripFlags()) + .append(children.first.expected.stripFlags()) + .append(children.remaining.stripFlags()) + .append(children.last.actual.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } + } else if (actual.hasChildren) { + result + .append(properties.last.actual.stripFlags()) + .append(api.lineBuilder.actual.line(indent + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(properties.last.expected.stripFlags()) + .append(api.lineBuilder.expected.last(indent + openTag.selfClose + openTag.end)) + } else if (expected.hasChildren) { + result + .append(properties.last.actual.stripFlags()) + .append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end)) + .append(properties.last.expected.stripFlags()) + .append(api.lineBuilder.expected.line(indent + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } else { + result + .append(properties.last.actual.stripFlags()) + .append(properties.last.expected.stripFlags()) + .append(api.lineBuilder.last(indent + openTag.selfClose + openTag.end)) + } + } else if (actual.hasProperties) { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName)) + .append(allProperties.stripFlags()) + + if (actual.hasChildren && expected.hasChildren) { + result + .append(api.lineBuilder.actual.line(indent + openTag.end)) + .append(children.first.actual.stripFlags()) + .append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end)) + .append(children.first.expected.stripFlags()) + .append(children.remaining.stripFlags()) + + if (namesAreEqual) { + result + .append(children.last.actual.stripFlags()) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + } else { + result + .append(children.last.actual.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } + } else if (actual.hasChildren) { + result + .append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end)) + } else if (expected.hasChildren) { + result + .append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end)) + .append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } else { + result + .append(api.lineBuilder.actual.last(indent + openTag.selfClose + openTag.end)) + .append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end)) + } + } else if (expected.hasProperties) { + if (actual.hasChildren && expected.hasChildren) { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end)) + .append(children.first.actual.stripFlags()) + .append(api.lineBuilder.expected.first(openTag.start + expectedName)) + .append(allProperties.stripFlags()) + .append(api.lineBuilder.expected.line(indent + openTag.end)) + .append(children.first.expected.stripFlags()) + .append(children.remaining.stripFlags()) + + if (namesAreEqual) { + result + .append(children.last.actual.stripFlags()) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + } else { + result + .append(children.last.actual.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } + } else if (actual.hasChildren) { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(api.lineBuilder.expected.first(openTag.start + expectedName)) + .append(allProperties.stripFlags()) + .append(api.lineBuilder.expected.last(indent + openTag.selfClose + openTag.end)) + } else if (expected.hasChildren) { + result + .append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end)) + .append(api.lineBuilder.expected.first(openTag.start + expectedName)) + .append(allProperties.stripFlags()) + .append(api.lineBuilder.expected.line(indent + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } else { + result + .append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end)) + .append(api.lineBuilder.expected.first(openTag.start + expectedName)) + .append(allProperties.stripFlags()) + .append(api.lineBuilder.expected.last(indent + openTag.selfCloseVoid + openTag.end)) + } + } else { + if (actual.hasChildren && expected.hasChildren) { + if (namesAreEqual) { + result + .append(api.lineBuilder.first(openTag.start + actualName + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + } else { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end)) + .append(children.first.actual.stripFlags()) + .append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end)) + .append(children.first.expected.stripFlags()) + .append(children.remaining.stripFlags()) + .append(children.last.actual.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(children.last.expected.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, expectedName))) + } + } else if (actual.hasChildren) { + result + .append(api.lineBuilder.actual.first(openTag.start + actualName + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.actual.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + .append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end)) + } else if (expected.hasChildren) { + result + .append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end)) + .append(api.lineBuilder.expected.first(openTag.start + expectedName + openTag.end)) + .append(allChildren.stripFlags()) + .append(api.lineBuilder.expected.last(indent + api.wrapFromTheme(theme.react.closeTag, actualName))) + } else { + if (namesAreEqual) { + result.append(api.lineBuilder.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end)) + } else { + result + .append(api.lineBuilder.actual.single(openTag.start + actualName + openTag.selfCloseVoid + openTag.end)) + .append(api.lineBuilder.expected.single(openTag.start + expectedName + openTag.selfCloseVoid + openTag.end)) + } + } + } + + return result + }, + + shouldFormat (subject) { + return subject.isItem === true || subject.isProperty === true + }, + + increaseIndent: true + } +} +module.exports = diffShallow diff --git a/node_modules/@concordance/react/lib/elementFactory.js b/node_modules/@concordance/react/lib/elementFactory.js new file mode 100644 index 000000000..9be125cef --- /dev/null +++ b/node_modules/@concordance/react/lib/elementFactory.js @@ -0,0 +1,349 @@ +'use strict' + +const arrify = require('arrify') +const diffShallow = require('./diffShallow') +const escapeText = require('./escapeText') + +function factory (api, reactTags) { + const tag = Symbol('@concordance/react.ElementValue') + + function customPropertyFormatter (theme, indent, key, value) { + const separator = theme.react.attribute.separator + theme.react.attribute.value.openBracket + if (value.isSingle) { + return value + .withFirstPrefixed(key.formatAsKey(theme) + separator) + .withLastPostfixed(theme.react.attribute.value.closeBracket) + } + + return api.lineBuilder.first(key.formatAsKey(theme) + separator) + .concat(value.withFirstPrefixed(indent.increase()).stripFlags()) + .append(api.lineBuilder.last(indent + theme.react.attribute.value.closeBracket)) + } + + function themeProperty (theme) { + theme.property.increaseValueIndent = true + theme.property.customFormat = customPropertyFormatter + } + + function themeStringProperty (theme) { + theme.property.separator = theme.react.attribute.separator + theme.property.after = '' + Object.assign(theme.string.line, theme.react.attribute.value.string.line) + } + + function customItemFormatter (theme, indent, value) { + if (value.isSingle) { + return value + .withFirstPrefixed(theme.react.child.openBracket) + .withLastPostfixed(theme.react.child.closeBracket) + } + + return api.lineBuilder.first(theme.react.child.openBracket) + .concat(value.withFirstPrefixed(indent.increase()).stripFlags()) + .append(api.lineBuilder.last(indent + theme.react.child.closeBracket)) + } + + function themeChild (theme) { + theme.item.increaseValueIndent = true + theme.item.customFormat = customItemFormatter + } + + function themeReactChild (theme) { + theme.item.after = '' + } + + function themeStringChild (theme) { + theme.item.after = '' + Object.assign(theme.string, theme.react.child.string) + } + + function describe (props) { + const element = props.value + + const type = element.type + const hasTypeFn = typeof type === 'function' + const typeFn = hasTypeFn ? type : null + const name = hasTypeFn ? type.displayName || type.name : type + + const children = arrify(element.props.children) + + const properties = Object.assign({}, element.props) + delete properties.children + if (element.key !== null) { + properties.key = element.key + } + const hasProperties = Object.keys(properties).length > 0 + + return new DescribedElementValue(Object.assign({ + children, + hasProperties, + hasTypeFn, + name, + properties, + typeFn, + isList: children.length > 0 + }, props)) + } + + function deserialize (state, recursor) { + return new DeserializedElementValue(state, recursor) + } + + class ElementValue extends api.ObjectValue { + constructor (props) { + super(props) + this.name = props.name + this.hasProperties = props.hasProperties + this.hasTypeFn = props.hasTypeFn + + this.hasChildren = this.isList + } + + compare (expected) { + return this.tag === expected.tag && this.name === expected.name + ? api.SHALLOW_EQUAL + : api.UNEQUAL + } + + formatName (theme) { + const formatted = api.wrapFromTheme(theme.react.tagName, this.name) + return this.hasTypeFn + ? formatted + theme.react.functionType + : formatted + } + + compareNames (expected) { + return this.name === expected.name && this.hasTypeFn === expected.hasTypeFn + } + + formatShallow (theme, indent) { + const childBuffer = api.lineBuilder.buffer() + const propertyBuffer = api.lineBuilder.buffer() + + return { + append (formatted, origin) { + if (origin.isItem === true) { + childBuffer.append(formatted) + } else { + propertyBuffer.append(formatted) + } + }, + + finalize: () => { + const name = this.formatName(theme) + const openTag = theme.react.openTag + + if (!this.hasChildren && !this.hasProperties) { + return api.lineBuilder.single(openTag.start + name + openTag.selfCloseVoid + openTag.end) + } + + const innerIndentation = indent.increase() + const children = childBuffer.withFirstPrefixed(innerIndentation).stripFlags() + const properties = propertyBuffer.withFirstPrefixed(innerIndentation).stripFlags() + + const result = api.lineBuilder.buffer() + if (this.hasProperties) { + result + .append(api.lineBuilder.first(openTag.start + name)) + .append(properties) + + if (this.hasChildren) { + result.append(api.lineBuilder.line(indent + openTag.end)) + } else { + result.append(api.lineBuilder.last(indent + openTag.selfClose + openTag.end)) + } + } else { + result.append(api.lineBuilder.first(openTag.start + name + openTag.end)) + } + + if (this.hasChildren) { + result + .append(children) + .append(api.lineBuilder.last(indent + api.wrapFromTheme(theme.react.closeTag, name))) + } + + return result + }, + + maxDepth: () => { + const name = this.formatName(theme) + const openTag = theme.react.openTag + + if (!this.hasChildren && !this.hasProperties) { + return api.lineBuilder.single(openTag.start + name + openTag.selfCloseVoid + openTag.end) + } + + let str = openTag.start + name + if (this.hasProperties) { + str += theme.maxDepth + if (this.hasChildren) { + str += openTag.end + } else { + str += ' ' + openTag.selfClose + openTag.end + } + } else { + str += openTag.end + } + + if (this.hasChildren) { + str += theme.maxDepth + api.wrapFromTheme(theme.react.closeTag, name) + } + + return api.lineBuilder.single(str) + }, + + shouldFormat (subject) { + return subject.isItem === true || subject.isProperty === true + }, + + increaseIndent: true + } + } + + prepareDiff (expected) { + return { + compareResult: this.tag === expected.tag + ? api.SHALLOW_EQUAL + : api.UNEQUAL + } + } + + diffShallow (expected, theme, indent) { + return diffShallow(api, this, expected, theme, indent) + } + + serialize () { + return [this.name, this.hasProperties, this.hasTypeFn, super.serialize()] + } + } + Object.defineProperty(ElementValue.prototype, 'tag', {value: tag}) + + function modifyThemes (recursor) { + return api.mapRecursor(recursor, next => { + let modifier + if (next.isItem === true) { + if (next.tag === api.descriptorTags.primitiveItem && next.value.tag === api.descriptorTags.string) { + modifier = themeStringChild + } else if (next.tag === api.descriptorTags.complexItem && reactTags.has(next.value.tag)) { + modifier = themeReactChild + } else { + modifier = themeChild + } + } else if (next.isProperty === true) { + if ( + next.tag === api.descriptorTags.primitiveProperty && + next.value.tag === api.descriptorTags.string && + !next.value.includesLinebreaks + ) { + modifier = themeStringProperty + } else { + modifier = themeProperty + } + } + + return modifier + ? api.modifyTheme(next, modifier) + : next + }) + } + + function DescribedMixin (base) { + return class extends api.DescribedMixin(base) { + constructor (props) { + super(props) + this.children = props.children + this.properties = props.properties + this.typeFn = props.typeFn + } + + compare (expected) { + const result = super.compare(expected) + return result === api.SHALLOW_EQUAL && this.typeFn !== expected.typeFn + ? api.UNEQUAL + : result + } + + compareNames (expected) { + return super.compareNames(expected) && this.typeFn === expected.typeFn + } + + createPropertyRecursor () { + // Symbols are not valid property keys for React elements. This code + // also assumes that the keys can be formatted as JSX-like attribute + // names. Keys are not pre-escaped before being passed to Concordance's + // property descriptor. + const keys = Object.keys(this.properties).sort() + const size = keys.length + + let index = 0 + const next = () => { + if (index === size) return null + + const key = keys[index++] + // Note that string values are not specifically escaped such that the + // output is valid JSX. + return this.describeProperty(key, this.describeAny(this.properties[key])) + } + + return {size, next} + } + + createListRecursor () { + if (!this.isList) return super.createListRecursor() + + const size = this.children.length + + let index = 0 + const next = () => { + if (index === size) return null + + const current = index++ + const child = this.children[current] + const type = typeof child + let descriptor + if (type === 'string') { + descriptor = this.describeAny(escapeText(child)) + } else { + descriptor = this.describeAny(child) + } + + return this.describeItem(current, descriptor) + } + + return {size, next} + } + + createRecursor () { + return modifyThemes(super.createRecursor()) + } + } + } + + function DeserializedMixin (base) { + return class extends api.DeserializedMixin(base) { + constructor (state, recursor) { + super(state[3], recursor) + this.name = state[0] + this.hasProperties = state[1] + this.hasTypeFn = state[2] + } + + createRecursor () { + return modifyThemes(super.createRecursor()) + } + } + } + + const DescribedElementValue = DescribedMixin(ElementValue) + const DeserializedElementValue = DeserializedMixin(ElementValue) + + return { + DescribedMixin, + DeserializedMixin, + ElementValue, + describe, + deserialize, + tag + } +} +module.exports = factory diff --git a/node_modules/@concordance/react/lib/escapeText.js b/node_modules/@concordance/react/lib/escapeText.js new file mode 100644 index 000000000..52447b1b6 --- /dev/null +++ b/node_modules/@concordance/react/lib/escapeText.js @@ -0,0 +1,10 @@ +'use strict' + +function escapeText (text) { + return text + .replace(/</g, '<') + .replace(/>/g, '>') + // TODO: Escape characters that Concordance would otherwise replace with \u + // sequences. +} +module.exports = escapeText diff --git a/node_modules/@concordance/react/lib/testJsonFactory.js b/node_modules/@concordance/react/lib/testJsonFactory.js new file mode 100644 index 000000000..c3e97a620 --- /dev/null +++ b/node_modules/@concordance/react/lib/testJsonFactory.js @@ -0,0 +1,59 @@ +'use strict' + +const arrify = require('arrify') + +function factory (api, element) { + const tag = Symbol('@concordance/react.TestJsonValue') + + function describe (props) { + const obj = props.value + + const name = obj.type + const children = arrify(obj.children) + const properties = Object.assign({}, obj.props) + const hasProperties = Object.keys(properties).length > 0 + + return new DescribedTestJsonValue(Object.assign({ + children, + hasProperties, + hasTypeFn: false, + name, + properties, + typeFn: null, + isList: children.length > 0 + }, props)) + } + + function deserialize (state, recursor) { + return new DeserializedTestJsonValue(state, recursor) + } + + class TestJsonValue extends element.ElementValue { + compare (expected) { + // Allow expected value to be a React element. + return (this.tag === expected.tag || expected.tag === element.tag) && this.name === expected.name + ? api.SHALLOW_EQUAL + : api.UNEQUAL + } + + prepareDiff (expected) { + return { + // Allow expected value to be a React element. + compareResult: this.tag === expected.tag || expected.tag === element.tag + ? api.SHALLOW_EQUAL + : api.UNEQUAL + } + } + } + Object.defineProperty(TestJsonValue.prototype, 'tag', {value: tag}) + + const DescribedTestJsonValue = element.DescribedMixin(TestJsonValue) + const DeserializedTestJsonValue = element.DeserializedMixin(TestJsonValue) + + return { + describe, + deserialize, + tag + } +} +module.exports = factory diff --git a/node_modules/@concordance/react/package.json b/node_modules/@concordance/react/package.json new file mode 100644 index 000000000..7ba194481 --- /dev/null +++ b/node_modules/@concordance/react/package.json @@ -0,0 +1,80 @@ +{ + "name": "@concordance/react", + "version": "1.0.0", + "description": "Compare, format, diff and serialize React trees with Concordance", + "main": "index.js", + "files": [ + "lib", + "index.js" + ], + "engines": { + "node": ">=4.5" + }, + "scripts": { + "build:fixtures": "babel --presets=react,@ava/stage-4 --out-dir=test/fixtures/react --extensions=.jsx test/fixtures/react", + "coverage": "nyc npm test", + "lint": "as-i-preach", + "pretest": "npm run build:fixtures", + "test": "ava", + "posttest": "as-i-preach" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/concordancejs/react.git" + }, + "author": "Mark Wubben (https://novemberborn.net/)", + "license": "ISC", + "bugs": { + "url": "https://github.com/concordancejs/react/issues" + }, + "homepage": "https://github.com/concordancejs/react#readme", + "keywords": [ + "concordance-plugin", + "concordance", + "react" + ], + "dependencies": { + "arrify": "^1.0.1" + }, + "devDependencies": { + "@novemberborn/as-i-preach": "^10.0.1", + "ava": "^0.19.0", + "babel-cli": "^6.24.1", + "babel-core": "^6.25.0", + "babel-preset-react": "^6.24.1", + "codecov": "^2.1.0", + "concordance": "^1.0.0", + "nyc": "^11.0.1", + "react": "^15.6.1", + "react-test-renderer": "^15.6.1" + }, + "as-i-preach": { + "allowDevDependencies": [ + "test/**/*.js", + "test/**/*.jsx" + ], + "ignore": [ + "test/fixtures/react/*.js" + ] + }, + "ava": { + "source": [ + "!test/**/*.js.snap" + ], + "babel": { + "presets": [ + "@ava/stage-4", + "@ava/transform-test-files", + "react" + ] + } + }, + "nyc": { + "reporter": [ + "html", + "lcov", + "text" + ] + }, + "standard-engine": "@novemberborn/as-i-preach" +} |