├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── elm.json ├── package-lock.json ├── package.json ├── src └── String │ └── Extra.elm └── tests ├── .gitignore ├── CamelizeTest.elm ├── ClassifyTest.elm ├── DasherizeTest.elm ├── HumanizeTest.elm ├── NonEmptyTest.elm ├── RemoveAccentsTest.elm ├── ReplaceSliceTest.elm ├── TestData.elm ├── Tests.elm ├── UnderscoredTest.elm ├── UnicodeTests.elm ├── UnindentTest.elm └── elm-package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # elm-package generated files 2 | elm-stuff/ 3 | # elm-repl generated files 4 | repl-temp-* 5 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: node 3 | 4 | 5 | cache: 6 | directories: 7 | - elm-stuff/build-artifacts 8 | - elm-stuff/packages 9 | - test/elm-stuff/build-artifacts 10 | - test/elm-stuff/packages 11 | - sysconfcpus 12 | 13 | before_install: 14 | - if [ ${TRAVIS_OS_NAME} == "osx" ]; 15 | then brew update; brew install nvm; mkdir ~/.nvm; export NVM_DIR=~/.nvm; source $(brew --prefix nvm)/nvm.sh; 16 | fi 17 | 18 | install: 19 | - npm install 20 | 21 | script: 22 | - npm run test 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Elm Community 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of string-extra nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | string-extra 2 | ============ 3 | 4 | String helper functions for Elm, inspired by [underscore.string](http://epeli.github.io/underscore.string/). 5 | 6 | [![Build Status](https://travis-ci.org/elm-community/string-extra.svg?branch=master)](https://travis-ci.org/elm-community/string-extra) 7 | 8 | Contributing 9 | ------------ 10 | 11 | Pull requests are welcome. If you want to talk to us, join us on the 12 | `#elm-community` or `#string-extra` channels on the [Elm Slack](https://elmlang.slack.com). 13 | 14 | Testing 15 | ------- 16 | 17 | ``` 18 | npm i 19 | npm run test 20 | ``` 21 | 22 | Maintainers 23 | ----------- 24 | 25 | This package is maintained by 26 | 27 | - [José Lorenzo Rodríguez](https://github.com/lorenzo) 28 | - [Jaap Broekhuizen](https://github.com/jaapz) 29 | 30 | Thanks 31 | ------ 32 | 33 | This package is an effort to consolidate [lorenzo/elm-string-addons](https://github.com/lorenzo/elm-string-addons), 34 | [NoRedInk/elm-string-extra](https://github.com/NoRedInk/elm-string-extra), and 35 | add utility functions inspired by [underscore.string](http://epeli.github.io/underscore.string/). 36 | 37 | So thanks to the authors of those libraries for making `string-extra` possible. 38 | 39 | License 40 | ------- 41 | 42 | The source code for this package is released under the terms of the BSD3 43 | license. See the `LICENSE` file. 44 | -------------------------------------------------------------------------------- /elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "package", 3 | "name": "elm-community/string-extra", 4 | "summary": "String helper functions for Elm", 5 | "license": "BSD-3-Clause", 6 | "version": "4.0.0", 7 | "exposed-modules": [ 8 | "String.Extra" 9 | ], 10 | "elm-version": "0.19.0 <= v < 0.20.0", 11 | "dependencies": { 12 | "elm/core": "1.0.0 <= v < 2.0.0", 13 | "elm/regex": "1.0.0 <= v < 2.0.0" 14 | }, 15 | "test-dependencies": { 16 | "elm-explorations/test": "1.2.1 <= v < 2.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string-extra", 3 | "version": "1.4.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "6.10.0", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 10 | "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", 11 | "requires": { 12 | "fast-deep-equal": "^2.0.1", 13 | "fast-json-stable-stringify": "^2.0.0", 14 | "json-schema-traverse": "^0.4.1", 15 | "uri-js": "^4.2.2" 16 | } 17 | }, 18 | "ansi-styles": { 19 | "version": "3.2.1", 20 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 21 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 22 | "requires": { 23 | "color-convert": "^1.9.0" 24 | } 25 | }, 26 | "anymatch": { 27 | "version": "1.3.2", 28 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", 29 | "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", 30 | "requires": { 31 | "micromatch": "^2.1.5", 32 | "normalize-path": "^2.0.0" 33 | } 34 | }, 35 | "arr-diff": { 36 | "version": "2.0.0", 37 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", 38 | "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", 39 | "requires": { 40 | "arr-flatten": "^1.0.1" 41 | } 42 | }, 43 | "arr-flatten": { 44 | "version": "1.1.0", 45 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", 46 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" 47 | }, 48 | "arr-union": { 49 | "version": "3.1.0", 50 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", 51 | "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" 52 | }, 53 | "array-unique": { 54 | "version": "0.2.1", 55 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", 56 | "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" 57 | }, 58 | "asn1": { 59 | "version": "0.2.4", 60 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 61 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 62 | "requires": { 63 | "safer-buffer": "~2.1.0" 64 | } 65 | }, 66 | "assert-plus": { 67 | "version": "1.0.0", 68 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 69 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 70 | }, 71 | "assign-symbols": { 72 | "version": "1.0.0", 73 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", 74 | "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" 75 | }, 76 | "async-each": { 77 | "version": "1.0.1", 78 | "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", 79 | "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" 80 | }, 81 | "asynckit": { 82 | "version": "0.4.0", 83 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 84 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 85 | }, 86 | "atob": { 87 | "version": "2.1.2", 88 | "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", 89 | "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" 90 | }, 91 | "aws-sign2": { 92 | "version": "0.7.0", 93 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 94 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 95 | }, 96 | "aws4": { 97 | "version": "1.8.0", 98 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 99 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 100 | }, 101 | "balanced-match": { 102 | "version": "1.0.0", 103 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 104 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 105 | }, 106 | "base": { 107 | "version": "0.11.2", 108 | "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", 109 | "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", 110 | "requires": { 111 | "cache-base": "^1.0.1", 112 | "class-utils": "^0.3.5", 113 | "component-emitter": "^1.2.1", 114 | "define-property": "^1.0.0", 115 | "isobject": "^3.0.1", 116 | "mixin-deep": "^1.2.0", 117 | "pascalcase": "^0.1.1" 118 | }, 119 | "dependencies": { 120 | "define-property": { 121 | "version": "1.0.0", 122 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 123 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 124 | "requires": { 125 | "is-descriptor": "^1.0.0" 126 | } 127 | }, 128 | "is-accessor-descriptor": { 129 | "version": "1.0.0", 130 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 131 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 132 | "requires": { 133 | "kind-of": "^6.0.0" 134 | } 135 | }, 136 | "is-data-descriptor": { 137 | "version": "1.0.0", 138 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 139 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 140 | "requires": { 141 | "kind-of": "^6.0.0" 142 | } 143 | }, 144 | "is-descriptor": { 145 | "version": "1.0.2", 146 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 147 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 148 | "requires": { 149 | "is-accessor-descriptor": "^1.0.0", 150 | "is-data-descriptor": "^1.0.0", 151 | "kind-of": "^6.0.2" 152 | } 153 | }, 154 | "isobject": { 155 | "version": "3.0.1", 156 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 157 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 158 | }, 159 | "kind-of": { 160 | "version": "6.0.2", 161 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 162 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 163 | } 164 | } 165 | }, 166 | "bcrypt-pbkdf": { 167 | "version": "1.0.2", 168 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 169 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 170 | "requires": { 171 | "tweetnacl": "^0.14.3" 172 | } 173 | }, 174 | "binary": { 175 | "version": "0.3.0", 176 | "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", 177 | "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", 178 | "requires": { 179 | "buffers": "~0.1.1", 180 | "chainsaw": "~0.1.0" 181 | } 182 | }, 183 | "binary-extensions": { 184 | "version": "1.13.0", 185 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", 186 | "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==" 187 | }, 188 | "binwrap": { 189 | "version": "0.2.0", 190 | "resolved": "https://registry.npmjs.org/binwrap/-/binwrap-0.2.0.tgz", 191 | "integrity": "sha512-HUspivC8zPE37KJQ0S4zsNHUpymzQBinmpdMoa+JwmB6Mi+p30ywVZJcillYpbQmiX2wLykaaDJxXmwZkbaZGA==", 192 | "requires": { 193 | "mustache": "^2.3.0", 194 | "request": "^2.87.0", 195 | "request-promise": "^4.2.0", 196 | "tar": "^2.2.1", 197 | "unzip-stream": "^0.3.0" 198 | } 199 | }, 200 | "block-stream": { 201 | "version": "0.0.9", 202 | "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", 203 | "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", 204 | "requires": { 205 | "inherits": "~2.0.0" 206 | } 207 | }, 208 | "bluebird": { 209 | "version": "3.5.3", 210 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", 211 | "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" 212 | }, 213 | "brace-expansion": { 214 | "version": "1.1.11", 215 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 216 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 217 | "requires": { 218 | "balanced-match": "^1.0.0", 219 | "concat-map": "0.0.1" 220 | } 221 | }, 222 | "braces": { 223 | "version": "1.8.5", 224 | "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", 225 | "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", 226 | "requires": { 227 | "expand-range": "^1.8.1", 228 | "preserve": "^0.2.0", 229 | "repeat-element": "^1.1.2" 230 | } 231 | }, 232 | "buffers": { 233 | "version": "0.1.1", 234 | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", 235 | "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" 236 | }, 237 | "cache-base": { 238 | "version": "1.0.1", 239 | "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", 240 | "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", 241 | "requires": { 242 | "collection-visit": "^1.0.0", 243 | "component-emitter": "^1.2.1", 244 | "get-value": "^2.0.6", 245 | "has-value": "^1.0.0", 246 | "isobject": "^3.0.1", 247 | "set-value": "^2.0.0", 248 | "to-object-path": "^0.3.0", 249 | "union-value": "^1.0.0", 250 | "unset-value": "^1.0.0" 251 | }, 252 | "dependencies": { 253 | "isobject": { 254 | "version": "3.0.1", 255 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 256 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 257 | } 258 | } 259 | }, 260 | "caseless": { 261 | "version": "0.12.0", 262 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 263 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 264 | }, 265 | "chainsaw": { 266 | "version": "0.1.0", 267 | "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", 268 | "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", 269 | "requires": { 270 | "traverse": ">=0.3.0 <0.4" 271 | } 272 | }, 273 | "chalk": { 274 | "version": "2.1.0", 275 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", 276 | "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", 277 | "requires": { 278 | "ansi-styles": "^3.1.0", 279 | "escape-string-regexp": "^1.0.5", 280 | "supports-color": "^4.0.0" 281 | } 282 | }, 283 | "chokidar": { 284 | "version": "1.7.0", 285 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", 286 | "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", 287 | "requires": { 288 | "anymatch": "^1.3.0", 289 | "async-each": "^1.0.0", 290 | "fsevents": "^1.0.0", 291 | "glob-parent": "^2.0.0", 292 | "inherits": "^2.0.1", 293 | "is-binary-path": "^1.0.0", 294 | "is-glob": "^2.0.0", 295 | "path-is-absolute": "^1.0.0", 296 | "readdirp": "^2.0.0" 297 | } 298 | }, 299 | "class-utils": { 300 | "version": "0.3.6", 301 | "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", 302 | "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", 303 | "requires": { 304 | "arr-union": "^3.1.0", 305 | "define-property": "^0.2.5", 306 | "isobject": "^3.0.0", 307 | "static-extend": "^0.1.1" 308 | }, 309 | "dependencies": { 310 | "define-property": { 311 | "version": "0.2.5", 312 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 313 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 314 | "requires": { 315 | "is-descriptor": "^0.1.0" 316 | } 317 | }, 318 | "isobject": { 319 | "version": "3.0.1", 320 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 321 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 322 | } 323 | } 324 | }, 325 | "collection-visit": { 326 | "version": "1.0.0", 327 | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", 328 | "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", 329 | "requires": { 330 | "map-visit": "^1.0.0", 331 | "object-visit": "^1.0.0" 332 | } 333 | }, 334 | "color-convert": { 335 | "version": "1.9.3", 336 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 337 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 338 | "requires": { 339 | "color-name": "1.1.3" 340 | } 341 | }, 342 | "color-name": { 343 | "version": "1.1.3", 344 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 345 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 346 | }, 347 | "combined-stream": { 348 | "version": "1.0.7", 349 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 350 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 351 | "requires": { 352 | "delayed-stream": "~1.0.0" 353 | } 354 | }, 355 | "component-emitter": { 356 | "version": "1.2.1", 357 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 358 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 359 | }, 360 | "concat-map": { 361 | "version": "0.0.1", 362 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 363 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 364 | }, 365 | "copy-descriptor": { 366 | "version": "0.1.1", 367 | "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", 368 | "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" 369 | }, 370 | "core-util-is": { 371 | "version": "1.0.2", 372 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 373 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 374 | }, 375 | "cross-spawn": { 376 | "version": "4.0.0", 377 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz", 378 | "integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=", 379 | "requires": { 380 | "lru-cache": "^4.0.1", 381 | "which": "^1.2.9" 382 | } 383 | }, 384 | "dashdash": { 385 | "version": "1.14.1", 386 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 387 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 388 | "requires": { 389 | "assert-plus": "^1.0.0" 390 | } 391 | }, 392 | "debug": { 393 | "version": "2.6.9", 394 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 395 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 396 | "requires": { 397 | "ms": "2.0.0" 398 | } 399 | }, 400 | "decode-uri-component": { 401 | "version": "0.2.0", 402 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 403 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 404 | }, 405 | "define-property": { 406 | "version": "2.0.2", 407 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", 408 | "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", 409 | "requires": { 410 | "is-descriptor": "^1.0.2", 411 | "isobject": "^3.0.1" 412 | }, 413 | "dependencies": { 414 | "is-accessor-descriptor": { 415 | "version": "1.0.0", 416 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 417 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 418 | "requires": { 419 | "kind-of": "^6.0.0" 420 | } 421 | }, 422 | "is-data-descriptor": { 423 | "version": "1.0.0", 424 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 425 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 426 | "requires": { 427 | "kind-of": "^6.0.0" 428 | } 429 | }, 430 | "is-descriptor": { 431 | "version": "1.0.2", 432 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 433 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 434 | "requires": { 435 | "is-accessor-descriptor": "^1.0.0", 436 | "is-data-descriptor": "^1.0.0", 437 | "kind-of": "^6.0.2" 438 | } 439 | }, 440 | "isobject": { 441 | "version": "3.0.1", 442 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 443 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 444 | }, 445 | "kind-of": { 446 | "version": "6.0.2", 447 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 448 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 449 | } 450 | } 451 | }, 452 | "delayed-stream": { 453 | "version": "1.0.0", 454 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 455 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 456 | }, 457 | "ecc-jsbn": { 458 | "version": "0.1.2", 459 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 460 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 461 | "requires": { 462 | "jsbn": "~0.1.0", 463 | "safer-buffer": "^2.1.0" 464 | } 465 | }, 466 | "elm": { 467 | "version": "0.19.0-bugfix6", 468 | "resolved": "https://registry.npmjs.org/elm/-/elm-0.19.0-bugfix6.tgz", 469 | "integrity": "sha512-nD/oK/nG26ULh94GREsILA9aQa3Gon+KKBmS0Z0MstywLWwrhuWKba8gfiIWLdnpQWHFIf+UsThk6Z71UWi6TQ==", 470 | "requires": { 471 | "binwrap": "0.2.0" 472 | } 473 | }, 474 | "elm-test": { 475 | "version": "0.19.0-rev5", 476 | "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.0-rev5.tgz", 477 | "integrity": "sha512-D/LS6Db9VIuaM3UffbBkrHmR6oLpm68EYVSru9CeHkVqUQwedVuLmZX6d0jvnU0C8I/dLSEdXlGueaPgTGhNnA==", 478 | "requires": { 479 | "chalk": "2.1.0", 480 | "chokidar": "1.7.0", 481 | "cross-spawn": "4.0.0", 482 | "elmi-to-json": "0.19.1", 483 | "find-parent-dir": "^0.3.0", 484 | "firstline": "1.2.1", 485 | "fs-extra": "0.30.0", 486 | "fsevents": "1.2.4", 487 | "glob": "7.1.1", 488 | "lodash": "4.17.11", 489 | "minimist": "^1.2.0", 490 | "murmur-hash-js": "1.0.0", 491 | "node-elm-compiler": "5.0.1", 492 | "split": "1.0.1", 493 | "supports-color": "4.2.0", 494 | "temp": "0.8.3", 495 | "which": "1.3.1", 496 | "xmlbuilder": "^8.2.2" 497 | }, 498 | "dependencies": { 499 | "glob": { 500 | "version": "7.1.1", 501 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 502 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 503 | "requires": { 504 | "fs.realpath": "^1.0.0", 505 | "inflight": "^1.0.4", 506 | "inherits": "2", 507 | "minimatch": "^3.0.2", 508 | "once": "^1.3.0", 509 | "path-is-absolute": "^1.0.0" 510 | } 511 | }, 512 | "minimist": { 513 | "version": "1.2.0", 514 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 515 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 516 | } 517 | } 518 | }, 519 | "elmi-to-json": { 520 | "version": "0.19.1", 521 | "resolved": "https://registry.npmjs.org/elmi-to-json/-/elmi-to-json-0.19.1.tgz", 522 | "integrity": "sha512-O0Z3YsYU9OTb1hTDGORWxi69QjQFEIPfZVq/oc1D5lhL3swduHKY8vdKGuo+WlKVdTas99oNIsgL7yojWdYcsQ==", 523 | "requires": { 524 | "binwrap": "^0.2.0-rc2" 525 | } 526 | }, 527 | "escape-string-regexp": { 528 | "version": "1.0.5", 529 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 530 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 531 | }, 532 | "expand-brackets": { 533 | "version": "0.1.5", 534 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", 535 | "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", 536 | "requires": { 537 | "is-posix-bracket": "^0.1.0" 538 | } 539 | }, 540 | "expand-range": { 541 | "version": "1.8.2", 542 | "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", 543 | "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", 544 | "requires": { 545 | "fill-range": "^2.1.0" 546 | } 547 | }, 548 | "extend": { 549 | "version": "3.0.2", 550 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 551 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 552 | }, 553 | "extend-shallow": { 554 | "version": "3.0.2", 555 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", 556 | "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", 557 | "requires": { 558 | "assign-symbols": "^1.0.0", 559 | "is-extendable": "^1.0.1" 560 | }, 561 | "dependencies": { 562 | "is-extendable": { 563 | "version": "1.0.1", 564 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 565 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 566 | "requires": { 567 | "is-plain-object": "^2.0.4" 568 | } 569 | } 570 | } 571 | }, 572 | "extglob": { 573 | "version": "0.3.2", 574 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", 575 | "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", 576 | "requires": { 577 | "is-extglob": "^1.0.0" 578 | } 579 | }, 580 | "extsprintf": { 581 | "version": "1.3.0", 582 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 583 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 584 | }, 585 | "fast-deep-equal": { 586 | "version": "2.0.1", 587 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 588 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 589 | }, 590 | "fast-json-stable-stringify": { 591 | "version": "2.0.0", 592 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 593 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 594 | }, 595 | "filename-regex": { 596 | "version": "2.0.1", 597 | "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", 598 | "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" 599 | }, 600 | "fill-range": { 601 | "version": "2.2.4", 602 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", 603 | "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", 604 | "requires": { 605 | "is-number": "^2.1.0", 606 | "isobject": "^2.0.0", 607 | "randomatic": "^3.0.0", 608 | "repeat-element": "^1.1.2", 609 | "repeat-string": "^1.5.2" 610 | } 611 | }, 612 | "find-elm-dependencies": { 613 | "version": "2.0.0", 614 | "resolved": "https://registry.npmjs.org/find-elm-dependencies/-/find-elm-dependencies-2.0.0.tgz", 615 | "integrity": "sha512-lnLilxwdS3U/CSPoMnfUL1u21MBNolv6NF54y4Yds7WxdRMrTBXrmugrcvIGvakWQ2anYuinmBSUR+jUQy+vpA==", 616 | "requires": { 617 | "firstline": "1.2.0", 618 | "lodash": "4.17.10" 619 | }, 620 | "dependencies": { 621 | "firstline": { 622 | "version": "1.2.0", 623 | "resolved": "https://registry.npmjs.org/firstline/-/firstline-1.2.0.tgz", 624 | "integrity": "sha1-yfSIbn9/vwr8EtcZQdzgaxkq6gU=" 625 | }, 626 | "lodash": { 627 | "version": "4.17.10", 628 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 629 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 630 | } 631 | } 632 | }, 633 | "find-parent-dir": { 634 | "version": "0.3.0", 635 | "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", 636 | "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=" 637 | }, 638 | "firstline": { 639 | "version": "1.2.1", 640 | "resolved": "https://registry.npmjs.org/firstline/-/firstline-1.2.1.tgz", 641 | "integrity": "sha1-uIZzxCAJ+IIfrCkm6ZcgrO6ST64=" 642 | }, 643 | "for-in": { 644 | "version": "1.0.2", 645 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 646 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" 647 | }, 648 | "for-own": { 649 | "version": "0.1.5", 650 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", 651 | "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", 652 | "requires": { 653 | "for-in": "^1.0.1" 654 | } 655 | }, 656 | "forever-agent": { 657 | "version": "0.6.1", 658 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 659 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 660 | }, 661 | "form-data": { 662 | "version": "2.3.3", 663 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 664 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 665 | "requires": { 666 | "asynckit": "^0.4.0", 667 | "combined-stream": "^1.0.6", 668 | "mime-types": "^2.1.12" 669 | } 670 | }, 671 | "fragment-cache": { 672 | "version": "0.2.1", 673 | "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", 674 | "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", 675 | "requires": { 676 | "map-cache": "^0.2.2" 677 | } 678 | }, 679 | "fs-extra": { 680 | "version": "0.30.0", 681 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", 682 | "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", 683 | "requires": { 684 | "graceful-fs": "^4.1.2", 685 | "jsonfile": "^2.1.0", 686 | "klaw": "^1.0.0", 687 | "path-is-absolute": "^1.0.0", 688 | "rimraf": "^2.2.8" 689 | } 690 | }, 691 | "fs.realpath": { 692 | "version": "1.0.0", 693 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 694 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 695 | }, 696 | "fsevents": { 697 | "version": "1.2.4", 698 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", 699 | "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", 700 | "optional": true, 701 | "requires": { 702 | "nan": "^2.9.2", 703 | "node-pre-gyp": "^0.10.0" 704 | }, 705 | "dependencies": { 706 | "abbrev": { 707 | "version": "1.1.1", 708 | "bundled": true, 709 | "optional": true 710 | }, 711 | "ansi-regex": { 712 | "version": "2.1.1", 713 | "bundled": true, 714 | "optional": true 715 | }, 716 | "aproba": { 717 | "version": "1.2.0", 718 | "bundled": true, 719 | "optional": true 720 | }, 721 | "are-we-there-yet": { 722 | "version": "1.1.4", 723 | "bundled": true, 724 | "optional": true, 725 | "requires": { 726 | "delegates": "^1.0.0", 727 | "readable-stream": "^2.0.6" 728 | } 729 | }, 730 | "balanced-match": { 731 | "version": "1.0.0", 732 | "bundled": true, 733 | "optional": true 734 | }, 735 | "brace-expansion": { 736 | "version": "1.1.11", 737 | "bundled": true, 738 | "optional": true, 739 | "requires": { 740 | "balanced-match": "^1.0.0", 741 | "concat-map": "0.0.1" 742 | } 743 | }, 744 | "chownr": { 745 | "version": "1.0.1", 746 | "bundled": true, 747 | "optional": true 748 | }, 749 | "code-point-at": { 750 | "version": "1.1.0", 751 | "bundled": true, 752 | "optional": true 753 | }, 754 | "concat-map": { 755 | "version": "0.0.1", 756 | "bundled": true, 757 | "optional": true 758 | }, 759 | "console-control-strings": { 760 | "version": "1.1.0", 761 | "bundled": true, 762 | "optional": true 763 | }, 764 | "core-util-is": { 765 | "version": "1.0.2", 766 | "bundled": true, 767 | "optional": true 768 | }, 769 | "debug": { 770 | "version": "2.6.9", 771 | "bundled": true, 772 | "optional": true, 773 | "requires": { 774 | "ms": "2.0.0" 775 | } 776 | }, 777 | "deep-extend": { 778 | "version": "0.5.1", 779 | "bundled": true, 780 | "optional": true 781 | }, 782 | "delegates": { 783 | "version": "1.0.0", 784 | "bundled": true, 785 | "optional": true 786 | }, 787 | "detect-libc": { 788 | "version": "1.0.3", 789 | "bundled": true, 790 | "optional": true 791 | }, 792 | "fs-minipass": { 793 | "version": "1.2.5", 794 | "bundled": true, 795 | "optional": true, 796 | "requires": { 797 | "minipass": "^2.2.1" 798 | } 799 | }, 800 | "fs.realpath": { 801 | "version": "1.0.0", 802 | "bundled": true, 803 | "optional": true 804 | }, 805 | "gauge": { 806 | "version": "2.7.4", 807 | "bundled": true, 808 | "optional": true, 809 | "requires": { 810 | "aproba": "^1.0.3", 811 | "console-control-strings": "^1.0.0", 812 | "has-unicode": "^2.0.0", 813 | "object-assign": "^4.1.0", 814 | "signal-exit": "^3.0.0", 815 | "string-width": "^1.0.1", 816 | "strip-ansi": "^3.0.1", 817 | "wide-align": "^1.1.0" 818 | } 819 | }, 820 | "glob": { 821 | "version": "7.1.2", 822 | "bundled": true, 823 | "optional": true, 824 | "requires": { 825 | "fs.realpath": "^1.0.0", 826 | "inflight": "^1.0.4", 827 | "inherits": "2", 828 | "minimatch": "^3.0.4", 829 | "once": "^1.3.0", 830 | "path-is-absolute": "^1.0.0" 831 | } 832 | }, 833 | "has-unicode": { 834 | "version": "2.0.1", 835 | "bundled": true, 836 | "optional": true 837 | }, 838 | "iconv-lite": { 839 | "version": "0.4.21", 840 | "bundled": true, 841 | "optional": true, 842 | "requires": { 843 | "safer-buffer": "^2.1.0" 844 | } 845 | }, 846 | "ignore-walk": { 847 | "version": "3.0.1", 848 | "bundled": true, 849 | "optional": true, 850 | "requires": { 851 | "minimatch": "^3.0.4" 852 | } 853 | }, 854 | "inflight": { 855 | "version": "1.0.6", 856 | "bundled": true, 857 | "optional": true, 858 | "requires": { 859 | "once": "^1.3.0", 860 | "wrappy": "1" 861 | } 862 | }, 863 | "inherits": { 864 | "version": "2.0.3", 865 | "bundled": true, 866 | "optional": true 867 | }, 868 | "ini": { 869 | "version": "1.3.5", 870 | "bundled": true, 871 | "optional": true 872 | }, 873 | "is-fullwidth-code-point": { 874 | "version": "1.0.0", 875 | "bundled": true, 876 | "optional": true, 877 | "requires": { 878 | "number-is-nan": "^1.0.0" 879 | } 880 | }, 881 | "isarray": { 882 | "version": "1.0.0", 883 | "bundled": true, 884 | "optional": true 885 | }, 886 | "minimatch": { 887 | "version": "3.0.4", 888 | "bundled": true, 889 | "optional": true, 890 | "requires": { 891 | "brace-expansion": "^1.1.7" 892 | } 893 | }, 894 | "minimist": { 895 | "version": "0.0.8", 896 | "bundled": true, 897 | "optional": true 898 | }, 899 | "minipass": { 900 | "version": "2.2.4", 901 | "bundled": true, 902 | "optional": true, 903 | "requires": { 904 | "safe-buffer": "^5.1.1", 905 | "yallist": "^3.0.0" 906 | } 907 | }, 908 | "minizlib": { 909 | "version": "1.1.0", 910 | "bundled": true, 911 | "optional": true, 912 | "requires": { 913 | "minipass": "^2.2.1" 914 | } 915 | }, 916 | "mkdirp": { 917 | "version": "0.5.1", 918 | "bundled": true, 919 | "optional": true, 920 | "requires": { 921 | "minimist": "0.0.8" 922 | } 923 | }, 924 | "ms": { 925 | "version": "2.0.0", 926 | "bundled": true, 927 | "optional": true 928 | }, 929 | "needle": { 930 | "version": "2.2.0", 931 | "bundled": true, 932 | "optional": true, 933 | "requires": { 934 | "debug": "^2.1.2", 935 | "iconv-lite": "^0.4.4", 936 | "sax": "^1.2.4" 937 | } 938 | }, 939 | "node-pre-gyp": { 940 | "version": "0.10.0", 941 | "bundled": true, 942 | "optional": true, 943 | "requires": { 944 | "detect-libc": "^1.0.2", 945 | "mkdirp": "^0.5.1", 946 | "needle": "^2.2.0", 947 | "nopt": "^4.0.1", 948 | "npm-packlist": "^1.1.6", 949 | "npmlog": "^4.0.2", 950 | "rc": "^1.1.7", 951 | "rimraf": "^2.6.1", 952 | "semver": "^5.3.0", 953 | "tar": "^4" 954 | } 955 | }, 956 | "nopt": { 957 | "version": "4.0.1", 958 | "bundled": true, 959 | "optional": true, 960 | "requires": { 961 | "abbrev": "1", 962 | "osenv": "^0.1.4" 963 | } 964 | }, 965 | "npm-bundled": { 966 | "version": "1.0.3", 967 | "bundled": true, 968 | "optional": true 969 | }, 970 | "npm-packlist": { 971 | "version": "1.1.10", 972 | "bundled": true, 973 | "optional": true, 974 | "requires": { 975 | "ignore-walk": "^3.0.1", 976 | "npm-bundled": "^1.0.1" 977 | } 978 | }, 979 | "npmlog": { 980 | "version": "4.1.2", 981 | "bundled": true, 982 | "optional": true, 983 | "requires": { 984 | "are-we-there-yet": "~1.1.2", 985 | "console-control-strings": "~1.1.0", 986 | "gauge": "~2.7.3", 987 | "set-blocking": "~2.0.0" 988 | } 989 | }, 990 | "number-is-nan": { 991 | "version": "1.0.1", 992 | "bundled": true, 993 | "optional": true 994 | }, 995 | "object-assign": { 996 | "version": "4.1.1", 997 | "bundled": true, 998 | "optional": true 999 | }, 1000 | "once": { 1001 | "version": "1.4.0", 1002 | "bundled": true, 1003 | "optional": true, 1004 | "requires": { 1005 | "wrappy": "1" 1006 | } 1007 | }, 1008 | "os-homedir": { 1009 | "version": "1.0.2", 1010 | "bundled": true, 1011 | "optional": true 1012 | }, 1013 | "os-tmpdir": { 1014 | "version": "1.0.2", 1015 | "bundled": true, 1016 | "optional": true 1017 | }, 1018 | "osenv": { 1019 | "version": "0.1.5", 1020 | "bundled": true, 1021 | "optional": true, 1022 | "requires": { 1023 | "os-homedir": "^1.0.0", 1024 | "os-tmpdir": "^1.0.0" 1025 | } 1026 | }, 1027 | "path-is-absolute": { 1028 | "version": "1.0.1", 1029 | "bundled": true, 1030 | "optional": true 1031 | }, 1032 | "process-nextick-args": { 1033 | "version": "2.0.0", 1034 | "bundled": true, 1035 | "optional": true 1036 | }, 1037 | "rc": { 1038 | "version": "1.2.7", 1039 | "bundled": true, 1040 | "optional": true, 1041 | "requires": { 1042 | "deep-extend": "^0.5.1", 1043 | "ini": "~1.3.0", 1044 | "minimist": "^1.2.0", 1045 | "strip-json-comments": "~2.0.1" 1046 | }, 1047 | "dependencies": { 1048 | "minimist": { 1049 | "version": "1.2.0", 1050 | "bundled": true, 1051 | "optional": true 1052 | } 1053 | } 1054 | }, 1055 | "readable-stream": { 1056 | "version": "2.3.6", 1057 | "bundled": true, 1058 | "optional": true, 1059 | "requires": { 1060 | "core-util-is": "~1.0.0", 1061 | "inherits": "~2.0.3", 1062 | "isarray": "~1.0.0", 1063 | "process-nextick-args": "~2.0.0", 1064 | "safe-buffer": "~5.1.1", 1065 | "string_decoder": "~1.1.1", 1066 | "util-deprecate": "~1.0.1" 1067 | } 1068 | }, 1069 | "rimraf": { 1070 | "version": "2.6.2", 1071 | "bundled": true, 1072 | "optional": true, 1073 | "requires": { 1074 | "glob": "^7.0.5" 1075 | } 1076 | }, 1077 | "safe-buffer": { 1078 | "version": "5.1.1", 1079 | "bundled": true, 1080 | "optional": true 1081 | }, 1082 | "safer-buffer": { 1083 | "version": "2.1.2", 1084 | "bundled": true, 1085 | "optional": true 1086 | }, 1087 | "sax": { 1088 | "version": "1.2.4", 1089 | "bundled": true, 1090 | "optional": true 1091 | }, 1092 | "semver": { 1093 | "version": "5.5.0", 1094 | "bundled": true, 1095 | "optional": true 1096 | }, 1097 | "set-blocking": { 1098 | "version": "2.0.0", 1099 | "bundled": true, 1100 | "optional": true 1101 | }, 1102 | "signal-exit": { 1103 | "version": "3.0.2", 1104 | "bundled": true, 1105 | "optional": true 1106 | }, 1107 | "string-width": { 1108 | "version": "1.0.2", 1109 | "bundled": true, 1110 | "optional": true, 1111 | "requires": { 1112 | "code-point-at": "^1.0.0", 1113 | "is-fullwidth-code-point": "^1.0.0", 1114 | "strip-ansi": "^3.0.0" 1115 | } 1116 | }, 1117 | "string_decoder": { 1118 | "version": "1.1.1", 1119 | "bundled": true, 1120 | "optional": true, 1121 | "requires": { 1122 | "safe-buffer": "~5.1.0" 1123 | } 1124 | }, 1125 | "strip-ansi": { 1126 | "version": "3.0.1", 1127 | "bundled": true, 1128 | "optional": true, 1129 | "requires": { 1130 | "ansi-regex": "^2.0.0" 1131 | } 1132 | }, 1133 | "strip-json-comments": { 1134 | "version": "2.0.1", 1135 | "bundled": true, 1136 | "optional": true 1137 | }, 1138 | "tar": { 1139 | "version": "4.4.1", 1140 | "bundled": true, 1141 | "optional": true, 1142 | "requires": { 1143 | "chownr": "^1.0.1", 1144 | "fs-minipass": "^1.2.5", 1145 | "minipass": "^2.2.4", 1146 | "minizlib": "^1.1.0", 1147 | "mkdirp": "^0.5.0", 1148 | "safe-buffer": "^5.1.1", 1149 | "yallist": "^3.0.2" 1150 | } 1151 | }, 1152 | "util-deprecate": { 1153 | "version": "1.0.2", 1154 | "bundled": true, 1155 | "optional": true 1156 | }, 1157 | "wide-align": { 1158 | "version": "1.1.2", 1159 | "bundled": true, 1160 | "optional": true, 1161 | "requires": { 1162 | "string-width": "^1.0.2" 1163 | } 1164 | }, 1165 | "wrappy": { 1166 | "version": "1.0.2", 1167 | "bundled": true, 1168 | "optional": true 1169 | }, 1170 | "yallist": { 1171 | "version": "3.0.2", 1172 | "bundled": true, 1173 | "optional": true 1174 | } 1175 | } 1176 | }, 1177 | "fstream": { 1178 | "version": "1.0.11", 1179 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", 1180 | "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", 1181 | "requires": { 1182 | "graceful-fs": "^4.1.2", 1183 | "inherits": "~2.0.0", 1184 | "mkdirp": ">=0.5 0", 1185 | "rimraf": "2" 1186 | } 1187 | }, 1188 | "get-value": { 1189 | "version": "2.0.6", 1190 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", 1191 | "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" 1192 | }, 1193 | "getpass": { 1194 | "version": "0.1.7", 1195 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 1196 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 1197 | "requires": { 1198 | "assert-plus": "^1.0.0" 1199 | } 1200 | }, 1201 | "glob": { 1202 | "version": "7.1.3", 1203 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 1204 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 1205 | "requires": { 1206 | "fs.realpath": "^1.0.0", 1207 | "inflight": "^1.0.4", 1208 | "inherits": "2", 1209 | "minimatch": "^3.0.4", 1210 | "once": "^1.3.0", 1211 | "path-is-absolute": "^1.0.0" 1212 | } 1213 | }, 1214 | "glob-base": { 1215 | "version": "0.3.0", 1216 | "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", 1217 | "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", 1218 | "requires": { 1219 | "glob-parent": "^2.0.0", 1220 | "is-glob": "^2.0.0" 1221 | } 1222 | }, 1223 | "glob-parent": { 1224 | "version": "2.0.0", 1225 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", 1226 | "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", 1227 | "requires": { 1228 | "is-glob": "^2.0.0" 1229 | } 1230 | }, 1231 | "graceful-fs": { 1232 | "version": "4.1.15", 1233 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 1234 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" 1235 | }, 1236 | "har-schema": { 1237 | "version": "2.0.0", 1238 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 1239 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 1240 | }, 1241 | "har-validator": { 1242 | "version": "5.1.3", 1243 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 1244 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 1245 | "requires": { 1246 | "ajv": "^6.5.5", 1247 | "har-schema": "^2.0.0" 1248 | } 1249 | }, 1250 | "has-flag": { 1251 | "version": "2.0.0", 1252 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 1253 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" 1254 | }, 1255 | "has-value": { 1256 | "version": "1.0.0", 1257 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", 1258 | "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", 1259 | "requires": { 1260 | "get-value": "^2.0.6", 1261 | "has-values": "^1.0.0", 1262 | "isobject": "^3.0.0" 1263 | }, 1264 | "dependencies": { 1265 | "isobject": { 1266 | "version": "3.0.1", 1267 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1268 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1269 | } 1270 | } 1271 | }, 1272 | "has-values": { 1273 | "version": "1.0.0", 1274 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", 1275 | "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", 1276 | "requires": { 1277 | "is-number": "^3.0.0", 1278 | "kind-of": "^4.0.0" 1279 | }, 1280 | "dependencies": { 1281 | "is-number": { 1282 | "version": "3.0.0", 1283 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 1284 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 1285 | "requires": { 1286 | "kind-of": "^3.0.2" 1287 | }, 1288 | "dependencies": { 1289 | "kind-of": { 1290 | "version": "3.2.2", 1291 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1292 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1293 | "requires": { 1294 | "is-buffer": "^1.1.5" 1295 | } 1296 | } 1297 | } 1298 | }, 1299 | "kind-of": { 1300 | "version": "4.0.0", 1301 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", 1302 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", 1303 | "requires": { 1304 | "is-buffer": "^1.1.5" 1305 | } 1306 | } 1307 | } 1308 | }, 1309 | "http-signature": { 1310 | "version": "1.2.0", 1311 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 1312 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 1313 | "requires": { 1314 | "assert-plus": "^1.0.0", 1315 | "jsprim": "^1.2.2", 1316 | "sshpk": "^1.7.0" 1317 | } 1318 | }, 1319 | "inflight": { 1320 | "version": "1.0.6", 1321 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1322 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1323 | "requires": { 1324 | "once": "^1.3.0", 1325 | "wrappy": "1" 1326 | } 1327 | }, 1328 | "inherits": { 1329 | "version": "2.0.3", 1330 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1331 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1332 | }, 1333 | "is-accessor-descriptor": { 1334 | "version": "0.1.6", 1335 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", 1336 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", 1337 | "requires": { 1338 | "kind-of": "^3.0.2" 1339 | } 1340 | }, 1341 | "is-binary-path": { 1342 | "version": "1.0.1", 1343 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", 1344 | "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", 1345 | "requires": { 1346 | "binary-extensions": "^1.0.0" 1347 | } 1348 | }, 1349 | "is-buffer": { 1350 | "version": "1.1.6", 1351 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1352 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 1353 | }, 1354 | "is-data-descriptor": { 1355 | "version": "0.1.4", 1356 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", 1357 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", 1358 | "requires": { 1359 | "kind-of": "^3.0.2" 1360 | } 1361 | }, 1362 | "is-descriptor": { 1363 | "version": "0.1.6", 1364 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", 1365 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", 1366 | "requires": { 1367 | "is-accessor-descriptor": "^0.1.6", 1368 | "is-data-descriptor": "^0.1.4", 1369 | "kind-of": "^5.0.0" 1370 | }, 1371 | "dependencies": { 1372 | "kind-of": { 1373 | "version": "5.1.0", 1374 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", 1375 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" 1376 | } 1377 | } 1378 | }, 1379 | "is-dotfile": { 1380 | "version": "1.0.3", 1381 | "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", 1382 | "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" 1383 | }, 1384 | "is-equal-shallow": { 1385 | "version": "0.1.3", 1386 | "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", 1387 | "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", 1388 | "requires": { 1389 | "is-primitive": "^2.0.0" 1390 | } 1391 | }, 1392 | "is-extendable": { 1393 | "version": "0.1.1", 1394 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 1395 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" 1396 | }, 1397 | "is-extglob": { 1398 | "version": "1.0.0", 1399 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", 1400 | "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" 1401 | }, 1402 | "is-glob": { 1403 | "version": "2.0.1", 1404 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", 1405 | "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", 1406 | "requires": { 1407 | "is-extglob": "^1.0.0" 1408 | } 1409 | }, 1410 | "is-number": { 1411 | "version": "2.1.0", 1412 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", 1413 | "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", 1414 | "requires": { 1415 | "kind-of": "^3.0.2" 1416 | } 1417 | }, 1418 | "is-plain-object": { 1419 | "version": "2.0.4", 1420 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1421 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1422 | "requires": { 1423 | "isobject": "^3.0.1" 1424 | }, 1425 | "dependencies": { 1426 | "isobject": { 1427 | "version": "3.0.1", 1428 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1429 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1430 | } 1431 | } 1432 | }, 1433 | "is-posix-bracket": { 1434 | "version": "0.1.1", 1435 | "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", 1436 | "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" 1437 | }, 1438 | "is-primitive": { 1439 | "version": "2.0.0", 1440 | "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", 1441 | "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" 1442 | }, 1443 | "is-typedarray": { 1444 | "version": "1.0.0", 1445 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1446 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 1447 | }, 1448 | "is-windows": { 1449 | "version": "1.0.2", 1450 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1451 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" 1452 | }, 1453 | "isarray": { 1454 | "version": "1.0.0", 1455 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1456 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1457 | }, 1458 | "isexe": { 1459 | "version": "2.0.0", 1460 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1461 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 1462 | }, 1463 | "isobject": { 1464 | "version": "2.1.0", 1465 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", 1466 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", 1467 | "requires": { 1468 | "isarray": "1.0.0" 1469 | } 1470 | }, 1471 | "isstream": { 1472 | "version": "0.1.2", 1473 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1474 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 1475 | }, 1476 | "jsbn": { 1477 | "version": "0.1.1", 1478 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1479 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 1480 | }, 1481 | "json-schema": { 1482 | "version": "0.2.3", 1483 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 1484 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 1485 | }, 1486 | "json-schema-traverse": { 1487 | "version": "0.4.1", 1488 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1489 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 1490 | }, 1491 | "json-stringify-safe": { 1492 | "version": "5.0.1", 1493 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1494 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 1495 | }, 1496 | "jsonfile": { 1497 | "version": "2.4.0", 1498 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", 1499 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", 1500 | "requires": { 1501 | "graceful-fs": "^4.1.6" 1502 | } 1503 | }, 1504 | "jsprim": { 1505 | "version": "1.4.1", 1506 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 1507 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 1508 | "requires": { 1509 | "assert-plus": "1.0.0", 1510 | "extsprintf": "1.3.0", 1511 | "json-schema": "0.2.3", 1512 | "verror": "1.10.0" 1513 | } 1514 | }, 1515 | "kind-of": { 1516 | "version": "3.2.2", 1517 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1518 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1519 | "requires": { 1520 | "is-buffer": "^1.1.5" 1521 | } 1522 | }, 1523 | "klaw": { 1524 | "version": "1.3.1", 1525 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", 1526 | "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", 1527 | "requires": { 1528 | "graceful-fs": "^4.1.9" 1529 | } 1530 | }, 1531 | "lodash": { 1532 | "version": "4.17.11", 1533 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 1534 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 1535 | }, 1536 | "lru-cache": { 1537 | "version": "4.1.5", 1538 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1539 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1540 | "requires": { 1541 | "pseudomap": "^1.0.2", 1542 | "yallist": "^2.1.2" 1543 | } 1544 | }, 1545 | "map-cache": { 1546 | "version": "0.2.2", 1547 | "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", 1548 | "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" 1549 | }, 1550 | "map-visit": { 1551 | "version": "1.0.0", 1552 | "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", 1553 | "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", 1554 | "requires": { 1555 | "object-visit": "^1.0.0" 1556 | } 1557 | }, 1558 | "math-random": { 1559 | "version": "1.0.4", 1560 | "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", 1561 | "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" 1562 | }, 1563 | "micromatch": { 1564 | "version": "2.3.11", 1565 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", 1566 | "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", 1567 | "requires": { 1568 | "arr-diff": "^2.0.0", 1569 | "array-unique": "^0.2.1", 1570 | "braces": "^1.8.2", 1571 | "expand-brackets": "^0.1.4", 1572 | "extglob": "^0.3.1", 1573 | "filename-regex": "^2.0.0", 1574 | "is-extglob": "^1.0.0", 1575 | "is-glob": "^2.0.1", 1576 | "kind-of": "^3.0.2", 1577 | "normalize-path": "^2.0.1", 1578 | "object.omit": "^2.0.0", 1579 | "parse-glob": "^3.0.4", 1580 | "regex-cache": "^0.4.2" 1581 | } 1582 | }, 1583 | "mime-db": { 1584 | "version": "1.38.0", 1585 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", 1586 | "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" 1587 | }, 1588 | "mime-types": { 1589 | "version": "2.1.22", 1590 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", 1591 | "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", 1592 | "requires": { 1593 | "mime-db": "~1.38.0" 1594 | } 1595 | }, 1596 | "minimatch": { 1597 | "version": "3.0.4", 1598 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1599 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1600 | "requires": { 1601 | "brace-expansion": "^1.1.7" 1602 | } 1603 | }, 1604 | "minimist": { 1605 | "version": "0.0.8", 1606 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1607 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1608 | }, 1609 | "mixin-deep": { 1610 | "version": "1.3.1", 1611 | "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", 1612 | "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", 1613 | "requires": { 1614 | "for-in": "^1.0.2", 1615 | "is-extendable": "^1.0.1" 1616 | }, 1617 | "dependencies": { 1618 | "is-extendable": { 1619 | "version": "1.0.1", 1620 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 1621 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 1622 | "requires": { 1623 | "is-plain-object": "^2.0.4" 1624 | } 1625 | } 1626 | } 1627 | }, 1628 | "mkdirp": { 1629 | "version": "0.5.1", 1630 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1631 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1632 | "requires": { 1633 | "minimist": "0.0.8" 1634 | } 1635 | }, 1636 | "ms": { 1637 | "version": "2.0.0", 1638 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1639 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1640 | }, 1641 | "murmur-hash-js": { 1642 | "version": "1.0.0", 1643 | "resolved": "https://registry.npmjs.org/murmur-hash-js/-/murmur-hash-js-1.0.0.tgz", 1644 | "integrity": "sha1-UEEEkmnJZjPIZjhpYLL0KJ515bA=" 1645 | }, 1646 | "mustache": { 1647 | "version": "2.3.2", 1648 | "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", 1649 | "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==" 1650 | }, 1651 | "nan": { 1652 | "version": "2.12.1", 1653 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", 1654 | "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", 1655 | "optional": true 1656 | }, 1657 | "nanomatch": { 1658 | "version": "1.2.13", 1659 | "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", 1660 | "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", 1661 | "requires": { 1662 | "arr-diff": "^4.0.0", 1663 | "array-unique": "^0.3.2", 1664 | "define-property": "^2.0.2", 1665 | "extend-shallow": "^3.0.2", 1666 | "fragment-cache": "^0.2.1", 1667 | "is-windows": "^1.0.2", 1668 | "kind-of": "^6.0.2", 1669 | "object.pick": "^1.3.0", 1670 | "regex-not": "^1.0.0", 1671 | "snapdragon": "^0.8.1", 1672 | "to-regex": "^3.0.1" 1673 | }, 1674 | "dependencies": { 1675 | "arr-diff": { 1676 | "version": "4.0.0", 1677 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 1678 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" 1679 | }, 1680 | "array-unique": { 1681 | "version": "0.3.2", 1682 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", 1683 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" 1684 | }, 1685 | "kind-of": { 1686 | "version": "6.0.2", 1687 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 1688 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 1689 | } 1690 | } 1691 | }, 1692 | "node-elm-compiler": { 1693 | "version": "5.0.1", 1694 | "resolved": "https://registry.npmjs.org/node-elm-compiler/-/node-elm-compiler-5.0.1.tgz", 1695 | "integrity": "sha512-Li9NfZTL83/URoUEWly+iHJeOcZRBYUaeIL4MImnB4r21oe/xpkR6JRHjdNjLf1rMtO0tgPyOvuGW4Beytaaow==", 1696 | "requires": { 1697 | "cross-spawn": "4.0.0", 1698 | "find-elm-dependencies": "2.0.0", 1699 | "lodash": "4.17.10", 1700 | "temp": "^0.8.3" 1701 | }, 1702 | "dependencies": { 1703 | "lodash": { 1704 | "version": "4.17.10", 1705 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 1706 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 1707 | } 1708 | } 1709 | }, 1710 | "normalize-path": { 1711 | "version": "2.1.1", 1712 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", 1713 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", 1714 | "requires": { 1715 | "remove-trailing-separator": "^1.0.1" 1716 | } 1717 | }, 1718 | "oauth-sign": { 1719 | "version": "0.9.0", 1720 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1721 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 1722 | }, 1723 | "object-copy": { 1724 | "version": "0.1.0", 1725 | "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", 1726 | "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", 1727 | "requires": { 1728 | "copy-descriptor": "^0.1.0", 1729 | "define-property": "^0.2.5", 1730 | "kind-of": "^3.0.3" 1731 | }, 1732 | "dependencies": { 1733 | "define-property": { 1734 | "version": "0.2.5", 1735 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 1736 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 1737 | "requires": { 1738 | "is-descriptor": "^0.1.0" 1739 | } 1740 | } 1741 | } 1742 | }, 1743 | "object-visit": { 1744 | "version": "1.0.1", 1745 | "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", 1746 | "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", 1747 | "requires": { 1748 | "isobject": "^3.0.0" 1749 | }, 1750 | "dependencies": { 1751 | "isobject": { 1752 | "version": "3.0.1", 1753 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1754 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1755 | } 1756 | } 1757 | }, 1758 | "object.omit": { 1759 | "version": "2.0.1", 1760 | "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", 1761 | "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", 1762 | "requires": { 1763 | "for-own": "^0.1.4", 1764 | "is-extendable": "^0.1.1" 1765 | } 1766 | }, 1767 | "object.pick": { 1768 | "version": "1.3.0", 1769 | "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", 1770 | "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", 1771 | "requires": { 1772 | "isobject": "^3.0.1" 1773 | }, 1774 | "dependencies": { 1775 | "isobject": { 1776 | "version": "3.0.1", 1777 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1778 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1779 | } 1780 | } 1781 | }, 1782 | "once": { 1783 | "version": "1.4.0", 1784 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1785 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1786 | "requires": { 1787 | "wrappy": "1" 1788 | } 1789 | }, 1790 | "os-tmpdir": { 1791 | "version": "1.0.2", 1792 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1793 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 1794 | }, 1795 | "parse-glob": { 1796 | "version": "3.0.4", 1797 | "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", 1798 | "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", 1799 | "requires": { 1800 | "glob-base": "^0.3.0", 1801 | "is-dotfile": "^1.0.0", 1802 | "is-extglob": "^1.0.0", 1803 | "is-glob": "^2.0.0" 1804 | } 1805 | }, 1806 | "pascalcase": { 1807 | "version": "0.1.1", 1808 | "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", 1809 | "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" 1810 | }, 1811 | "path-is-absolute": { 1812 | "version": "1.0.1", 1813 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1814 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1815 | }, 1816 | "performance-now": { 1817 | "version": "2.1.0", 1818 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1819 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1820 | }, 1821 | "posix-character-classes": { 1822 | "version": "0.1.1", 1823 | "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", 1824 | "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" 1825 | }, 1826 | "preserve": { 1827 | "version": "0.2.0", 1828 | "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", 1829 | "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" 1830 | }, 1831 | "process-nextick-args": { 1832 | "version": "2.0.0", 1833 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 1834 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 1835 | }, 1836 | "pseudomap": { 1837 | "version": "1.0.2", 1838 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1839 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 1840 | }, 1841 | "psl": { 1842 | "version": "1.1.31", 1843 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 1844 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" 1845 | }, 1846 | "punycode": { 1847 | "version": "2.1.1", 1848 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1849 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 1850 | }, 1851 | "qs": { 1852 | "version": "6.5.2", 1853 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1854 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1855 | }, 1856 | "randomatic": { 1857 | "version": "3.1.1", 1858 | "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", 1859 | "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", 1860 | "requires": { 1861 | "is-number": "^4.0.0", 1862 | "kind-of": "^6.0.0", 1863 | "math-random": "^1.0.1" 1864 | }, 1865 | "dependencies": { 1866 | "is-number": { 1867 | "version": "4.0.0", 1868 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", 1869 | "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" 1870 | }, 1871 | "kind-of": { 1872 | "version": "6.0.2", 1873 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 1874 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 1875 | } 1876 | } 1877 | }, 1878 | "readable-stream": { 1879 | "version": "2.3.6", 1880 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1881 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1882 | "requires": { 1883 | "core-util-is": "~1.0.0", 1884 | "inherits": "~2.0.3", 1885 | "isarray": "~1.0.0", 1886 | "process-nextick-args": "~2.0.0", 1887 | "safe-buffer": "~5.1.1", 1888 | "string_decoder": "~1.1.1", 1889 | "util-deprecate": "~1.0.1" 1890 | } 1891 | }, 1892 | "readdirp": { 1893 | "version": "2.2.1", 1894 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", 1895 | "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", 1896 | "requires": { 1897 | "graceful-fs": "^4.1.11", 1898 | "micromatch": "^3.1.10", 1899 | "readable-stream": "^2.0.2" 1900 | }, 1901 | "dependencies": { 1902 | "arr-diff": { 1903 | "version": "4.0.0", 1904 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 1905 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" 1906 | }, 1907 | "array-unique": { 1908 | "version": "0.3.2", 1909 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", 1910 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" 1911 | }, 1912 | "braces": { 1913 | "version": "2.3.2", 1914 | "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", 1915 | "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", 1916 | "requires": { 1917 | "arr-flatten": "^1.1.0", 1918 | "array-unique": "^0.3.2", 1919 | "extend-shallow": "^2.0.1", 1920 | "fill-range": "^4.0.0", 1921 | "isobject": "^3.0.1", 1922 | "repeat-element": "^1.1.2", 1923 | "snapdragon": "^0.8.1", 1924 | "snapdragon-node": "^2.0.1", 1925 | "split-string": "^3.0.2", 1926 | "to-regex": "^3.0.1" 1927 | }, 1928 | "dependencies": { 1929 | "extend-shallow": { 1930 | "version": "2.0.1", 1931 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 1932 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 1933 | "requires": { 1934 | "is-extendable": "^0.1.0" 1935 | } 1936 | } 1937 | } 1938 | }, 1939 | "expand-brackets": { 1940 | "version": "2.1.4", 1941 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", 1942 | "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", 1943 | "requires": { 1944 | "debug": "^2.3.3", 1945 | "define-property": "^0.2.5", 1946 | "extend-shallow": "^2.0.1", 1947 | "posix-character-classes": "^0.1.0", 1948 | "regex-not": "^1.0.0", 1949 | "snapdragon": "^0.8.1", 1950 | "to-regex": "^3.0.1" 1951 | }, 1952 | "dependencies": { 1953 | "define-property": { 1954 | "version": "0.2.5", 1955 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 1956 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 1957 | "requires": { 1958 | "is-descriptor": "^0.1.0" 1959 | } 1960 | }, 1961 | "extend-shallow": { 1962 | "version": "2.0.1", 1963 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 1964 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 1965 | "requires": { 1966 | "is-extendable": "^0.1.0" 1967 | } 1968 | }, 1969 | "is-accessor-descriptor": { 1970 | "version": "0.1.6", 1971 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", 1972 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", 1973 | "requires": { 1974 | "kind-of": "^3.0.2" 1975 | }, 1976 | "dependencies": { 1977 | "kind-of": { 1978 | "version": "3.2.2", 1979 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1980 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1981 | "requires": { 1982 | "is-buffer": "^1.1.5" 1983 | } 1984 | } 1985 | } 1986 | }, 1987 | "is-data-descriptor": { 1988 | "version": "0.1.4", 1989 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", 1990 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", 1991 | "requires": { 1992 | "kind-of": "^3.0.2" 1993 | }, 1994 | "dependencies": { 1995 | "kind-of": { 1996 | "version": "3.2.2", 1997 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1998 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1999 | "requires": { 2000 | "is-buffer": "^1.1.5" 2001 | } 2002 | } 2003 | } 2004 | }, 2005 | "is-descriptor": { 2006 | "version": "0.1.6", 2007 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", 2008 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", 2009 | "requires": { 2010 | "is-accessor-descriptor": "^0.1.6", 2011 | "is-data-descriptor": "^0.1.4", 2012 | "kind-of": "^5.0.0" 2013 | } 2014 | }, 2015 | "kind-of": { 2016 | "version": "5.1.0", 2017 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", 2018 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" 2019 | } 2020 | } 2021 | }, 2022 | "extglob": { 2023 | "version": "2.0.4", 2024 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", 2025 | "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", 2026 | "requires": { 2027 | "array-unique": "^0.3.2", 2028 | "define-property": "^1.0.0", 2029 | "expand-brackets": "^2.1.4", 2030 | "extend-shallow": "^2.0.1", 2031 | "fragment-cache": "^0.2.1", 2032 | "regex-not": "^1.0.0", 2033 | "snapdragon": "^0.8.1", 2034 | "to-regex": "^3.0.1" 2035 | }, 2036 | "dependencies": { 2037 | "define-property": { 2038 | "version": "1.0.0", 2039 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 2040 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 2041 | "requires": { 2042 | "is-descriptor": "^1.0.0" 2043 | } 2044 | }, 2045 | "extend-shallow": { 2046 | "version": "2.0.1", 2047 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2048 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2049 | "requires": { 2050 | "is-extendable": "^0.1.0" 2051 | } 2052 | } 2053 | } 2054 | }, 2055 | "fill-range": { 2056 | "version": "4.0.0", 2057 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", 2058 | "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", 2059 | "requires": { 2060 | "extend-shallow": "^2.0.1", 2061 | "is-number": "^3.0.0", 2062 | "repeat-string": "^1.6.1", 2063 | "to-regex-range": "^2.1.0" 2064 | }, 2065 | "dependencies": { 2066 | "extend-shallow": { 2067 | "version": "2.0.1", 2068 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2069 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2070 | "requires": { 2071 | "is-extendable": "^0.1.0" 2072 | } 2073 | } 2074 | } 2075 | }, 2076 | "is-accessor-descriptor": { 2077 | "version": "1.0.0", 2078 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 2079 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 2080 | "requires": { 2081 | "kind-of": "^6.0.0" 2082 | } 2083 | }, 2084 | "is-data-descriptor": { 2085 | "version": "1.0.0", 2086 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 2087 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 2088 | "requires": { 2089 | "kind-of": "^6.0.0" 2090 | } 2091 | }, 2092 | "is-descriptor": { 2093 | "version": "1.0.2", 2094 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 2095 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 2096 | "requires": { 2097 | "is-accessor-descriptor": "^1.0.0", 2098 | "is-data-descriptor": "^1.0.0", 2099 | "kind-of": "^6.0.2" 2100 | } 2101 | }, 2102 | "is-number": { 2103 | "version": "3.0.0", 2104 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 2105 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 2106 | "requires": { 2107 | "kind-of": "^3.0.2" 2108 | }, 2109 | "dependencies": { 2110 | "kind-of": { 2111 | "version": "3.2.2", 2112 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2113 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2114 | "requires": { 2115 | "is-buffer": "^1.1.5" 2116 | } 2117 | } 2118 | } 2119 | }, 2120 | "isobject": { 2121 | "version": "3.0.1", 2122 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 2123 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 2124 | }, 2125 | "kind-of": { 2126 | "version": "6.0.2", 2127 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 2128 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 2129 | }, 2130 | "micromatch": { 2131 | "version": "3.1.10", 2132 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", 2133 | "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", 2134 | "requires": { 2135 | "arr-diff": "^4.0.0", 2136 | "array-unique": "^0.3.2", 2137 | "braces": "^2.3.1", 2138 | "define-property": "^2.0.2", 2139 | "extend-shallow": "^3.0.2", 2140 | "extglob": "^2.0.4", 2141 | "fragment-cache": "^0.2.1", 2142 | "kind-of": "^6.0.2", 2143 | "nanomatch": "^1.2.9", 2144 | "object.pick": "^1.3.0", 2145 | "regex-not": "^1.0.0", 2146 | "snapdragon": "^0.8.1", 2147 | "to-regex": "^3.0.2" 2148 | } 2149 | } 2150 | } 2151 | }, 2152 | "regex-cache": { 2153 | "version": "0.4.4", 2154 | "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", 2155 | "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", 2156 | "requires": { 2157 | "is-equal-shallow": "^0.1.3" 2158 | } 2159 | }, 2160 | "regex-not": { 2161 | "version": "1.0.2", 2162 | "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", 2163 | "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", 2164 | "requires": { 2165 | "extend-shallow": "^3.0.2", 2166 | "safe-regex": "^1.1.0" 2167 | } 2168 | }, 2169 | "remove-trailing-separator": { 2170 | "version": "1.1.0", 2171 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", 2172 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" 2173 | }, 2174 | "repeat-element": { 2175 | "version": "1.1.3", 2176 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", 2177 | "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" 2178 | }, 2179 | "repeat-string": { 2180 | "version": "1.6.1", 2181 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 2182 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 2183 | }, 2184 | "request": { 2185 | "version": "2.88.0", 2186 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 2187 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 2188 | "requires": { 2189 | "aws-sign2": "~0.7.0", 2190 | "aws4": "^1.8.0", 2191 | "caseless": "~0.12.0", 2192 | "combined-stream": "~1.0.6", 2193 | "extend": "~3.0.2", 2194 | "forever-agent": "~0.6.1", 2195 | "form-data": "~2.3.2", 2196 | "har-validator": "~5.1.0", 2197 | "http-signature": "~1.2.0", 2198 | "is-typedarray": "~1.0.0", 2199 | "isstream": "~0.1.2", 2200 | "json-stringify-safe": "~5.0.1", 2201 | "mime-types": "~2.1.19", 2202 | "oauth-sign": "~0.9.0", 2203 | "performance-now": "^2.1.0", 2204 | "qs": "~6.5.2", 2205 | "safe-buffer": "^5.1.2", 2206 | "tough-cookie": "~2.4.3", 2207 | "tunnel-agent": "^0.6.0", 2208 | "uuid": "^3.3.2" 2209 | } 2210 | }, 2211 | "request-promise": { 2212 | "version": "4.2.4", 2213 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", 2214 | "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", 2215 | "requires": { 2216 | "bluebird": "^3.5.0", 2217 | "request-promise-core": "1.1.2", 2218 | "stealthy-require": "^1.1.1", 2219 | "tough-cookie": "^2.3.3" 2220 | } 2221 | }, 2222 | "request-promise-core": { 2223 | "version": "1.1.2", 2224 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", 2225 | "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", 2226 | "requires": { 2227 | "lodash": "^4.17.11" 2228 | } 2229 | }, 2230 | "resolve-url": { 2231 | "version": "0.2.1", 2232 | "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", 2233 | "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" 2234 | }, 2235 | "ret": { 2236 | "version": "0.1.15", 2237 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 2238 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" 2239 | }, 2240 | "rimraf": { 2241 | "version": "2.6.3", 2242 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 2243 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 2244 | "requires": { 2245 | "glob": "^7.1.3" 2246 | } 2247 | }, 2248 | "safe-buffer": { 2249 | "version": "5.1.2", 2250 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2251 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2252 | }, 2253 | "safe-regex": { 2254 | "version": "1.1.0", 2255 | "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", 2256 | "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", 2257 | "requires": { 2258 | "ret": "~0.1.10" 2259 | } 2260 | }, 2261 | "safer-buffer": { 2262 | "version": "2.1.2", 2263 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2264 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2265 | }, 2266 | "set-value": { 2267 | "version": "2.0.0", 2268 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", 2269 | "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", 2270 | "requires": { 2271 | "extend-shallow": "^2.0.1", 2272 | "is-extendable": "^0.1.1", 2273 | "is-plain-object": "^2.0.3", 2274 | "split-string": "^3.0.1" 2275 | }, 2276 | "dependencies": { 2277 | "extend-shallow": { 2278 | "version": "2.0.1", 2279 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2280 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2281 | "requires": { 2282 | "is-extendable": "^0.1.0" 2283 | } 2284 | } 2285 | } 2286 | }, 2287 | "snapdragon": { 2288 | "version": "0.8.2", 2289 | "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", 2290 | "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", 2291 | "requires": { 2292 | "base": "^0.11.1", 2293 | "debug": "^2.2.0", 2294 | "define-property": "^0.2.5", 2295 | "extend-shallow": "^2.0.1", 2296 | "map-cache": "^0.2.2", 2297 | "source-map": "^0.5.6", 2298 | "source-map-resolve": "^0.5.0", 2299 | "use": "^3.1.0" 2300 | }, 2301 | "dependencies": { 2302 | "define-property": { 2303 | "version": "0.2.5", 2304 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2305 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2306 | "requires": { 2307 | "is-descriptor": "^0.1.0" 2308 | } 2309 | }, 2310 | "extend-shallow": { 2311 | "version": "2.0.1", 2312 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2313 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2314 | "requires": { 2315 | "is-extendable": "^0.1.0" 2316 | } 2317 | } 2318 | } 2319 | }, 2320 | "snapdragon-node": { 2321 | "version": "2.1.1", 2322 | "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", 2323 | "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", 2324 | "requires": { 2325 | "define-property": "^1.0.0", 2326 | "isobject": "^3.0.0", 2327 | "snapdragon-util": "^3.0.1" 2328 | }, 2329 | "dependencies": { 2330 | "define-property": { 2331 | "version": "1.0.0", 2332 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 2333 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 2334 | "requires": { 2335 | "is-descriptor": "^1.0.0" 2336 | } 2337 | }, 2338 | "is-accessor-descriptor": { 2339 | "version": "1.0.0", 2340 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 2341 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 2342 | "requires": { 2343 | "kind-of": "^6.0.0" 2344 | } 2345 | }, 2346 | "is-data-descriptor": { 2347 | "version": "1.0.0", 2348 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 2349 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 2350 | "requires": { 2351 | "kind-of": "^6.0.0" 2352 | } 2353 | }, 2354 | "is-descriptor": { 2355 | "version": "1.0.2", 2356 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 2357 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 2358 | "requires": { 2359 | "is-accessor-descriptor": "^1.0.0", 2360 | "is-data-descriptor": "^1.0.0", 2361 | "kind-of": "^6.0.2" 2362 | } 2363 | }, 2364 | "isobject": { 2365 | "version": "3.0.1", 2366 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 2367 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 2368 | }, 2369 | "kind-of": { 2370 | "version": "6.0.2", 2371 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 2372 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 2373 | } 2374 | } 2375 | }, 2376 | "snapdragon-util": { 2377 | "version": "3.0.1", 2378 | "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", 2379 | "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", 2380 | "requires": { 2381 | "kind-of": "^3.2.0" 2382 | } 2383 | }, 2384 | "source-map": { 2385 | "version": "0.5.7", 2386 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2387 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 2388 | }, 2389 | "source-map-resolve": { 2390 | "version": "0.5.2", 2391 | "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", 2392 | "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", 2393 | "requires": { 2394 | "atob": "^2.1.1", 2395 | "decode-uri-component": "^0.2.0", 2396 | "resolve-url": "^0.2.1", 2397 | "source-map-url": "^0.4.0", 2398 | "urix": "^0.1.0" 2399 | } 2400 | }, 2401 | "source-map-url": { 2402 | "version": "0.4.0", 2403 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 2404 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" 2405 | }, 2406 | "split": { 2407 | "version": "1.0.1", 2408 | "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", 2409 | "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", 2410 | "requires": { 2411 | "through": "2" 2412 | } 2413 | }, 2414 | "split-string": { 2415 | "version": "3.1.0", 2416 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", 2417 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", 2418 | "requires": { 2419 | "extend-shallow": "^3.0.0" 2420 | } 2421 | }, 2422 | "sshpk": { 2423 | "version": "1.16.1", 2424 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 2425 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 2426 | "requires": { 2427 | "asn1": "~0.2.3", 2428 | "assert-plus": "^1.0.0", 2429 | "bcrypt-pbkdf": "^1.0.0", 2430 | "dashdash": "^1.12.0", 2431 | "ecc-jsbn": "~0.1.1", 2432 | "getpass": "^0.1.1", 2433 | "jsbn": "~0.1.0", 2434 | "safer-buffer": "^2.0.2", 2435 | "tweetnacl": "~0.14.0" 2436 | } 2437 | }, 2438 | "static-extend": { 2439 | "version": "0.1.2", 2440 | "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", 2441 | "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", 2442 | "requires": { 2443 | "define-property": "^0.2.5", 2444 | "object-copy": "^0.1.0" 2445 | }, 2446 | "dependencies": { 2447 | "define-property": { 2448 | "version": "0.2.5", 2449 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2450 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2451 | "requires": { 2452 | "is-descriptor": "^0.1.0" 2453 | } 2454 | } 2455 | } 2456 | }, 2457 | "stealthy-require": { 2458 | "version": "1.1.1", 2459 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 2460 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" 2461 | }, 2462 | "string_decoder": { 2463 | "version": "1.1.1", 2464 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2465 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2466 | "requires": { 2467 | "safe-buffer": "~5.1.0" 2468 | } 2469 | }, 2470 | "supports-color": { 2471 | "version": "4.2.0", 2472 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.0.tgz", 2473 | "integrity": "sha512-Ts0Mu/A1S1aZxEJNG88I4Oc9rcZSBFNac5e27yh4j2mqbhZSSzR1Ah79EYwSn9Zuh7lrlGD2cVGzw1RKGzyLSg==", 2474 | "requires": { 2475 | "has-flag": "^2.0.0" 2476 | } 2477 | }, 2478 | "tar": { 2479 | "version": "2.2.1", 2480 | "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", 2481 | "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", 2482 | "requires": { 2483 | "block-stream": "*", 2484 | "fstream": "^1.0.2", 2485 | "inherits": "2" 2486 | } 2487 | }, 2488 | "temp": { 2489 | "version": "0.8.3", 2490 | "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", 2491 | "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", 2492 | "requires": { 2493 | "os-tmpdir": "^1.0.0", 2494 | "rimraf": "~2.2.6" 2495 | }, 2496 | "dependencies": { 2497 | "rimraf": { 2498 | "version": "2.2.8", 2499 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", 2500 | "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" 2501 | } 2502 | } 2503 | }, 2504 | "through": { 2505 | "version": "2.3.8", 2506 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2507 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 2508 | }, 2509 | "to-object-path": { 2510 | "version": "0.3.0", 2511 | "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", 2512 | "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", 2513 | "requires": { 2514 | "kind-of": "^3.0.2" 2515 | } 2516 | }, 2517 | "to-regex": { 2518 | "version": "3.0.2", 2519 | "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", 2520 | "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", 2521 | "requires": { 2522 | "define-property": "^2.0.2", 2523 | "extend-shallow": "^3.0.2", 2524 | "regex-not": "^1.0.2", 2525 | "safe-regex": "^1.1.0" 2526 | } 2527 | }, 2528 | "to-regex-range": { 2529 | "version": "2.1.1", 2530 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", 2531 | "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", 2532 | "requires": { 2533 | "is-number": "^3.0.0", 2534 | "repeat-string": "^1.6.1" 2535 | }, 2536 | "dependencies": { 2537 | "is-number": { 2538 | "version": "3.0.0", 2539 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 2540 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 2541 | "requires": { 2542 | "kind-of": "^3.0.2" 2543 | } 2544 | } 2545 | } 2546 | }, 2547 | "tough-cookie": { 2548 | "version": "2.4.3", 2549 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 2550 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 2551 | "requires": { 2552 | "psl": "^1.1.24", 2553 | "punycode": "^1.4.1" 2554 | }, 2555 | "dependencies": { 2556 | "punycode": { 2557 | "version": "1.4.1", 2558 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 2559 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 2560 | } 2561 | } 2562 | }, 2563 | "traverse": { 2564 | "version": "0.3.9", 2565 | "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", 2566 | "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" 2567 | }, 2568 | "tunnel-agent": { 2569 | "version": "0.6.0", 2570 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2571 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 2572 | "requires": { 2573 | "safe-buffer": "^5.0.1" 2574 | } 2575 | }, 2576 | "tweetnacl": { 2577 | "version": "0.14.5", 2578 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2579 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 2580 | }, 2581 | "union-value": { 2582 | "version": "1.0.0", 2583 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", 2584 | "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", 2585 | "requires": { 2586 | "arr-union": "^3.1.0", 2587 | "get-value": "^2.0.6", 2588 | "is-extendable": "^0.1.1", 2589 | "set-value": "^0.4.3" 2590 | }, 2591 | "dependencies": { 2592 | "extend-shallow": { 2593 | "version": "2.0.1", 2594 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2595 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2596 | "requires": { 2597 | "is-extendable": "^0.1.0" 2598 | } 2599 | }, 2600 | "set-value": { 2601 | "version": "0.4.3", 2602 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", 2603 | "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", 2604 | "requires": { 2605 | "extend-shallow": "^2.0.1", 2606 | "is-extendable": "^0.1.1", 2607 | "is-plain-object": "^2.0.1", 2608 | "to-object-path": "^0.3.0" 2609 | } 2610 | } 2611 | } 2612 | }, 2613 | "unset-value": { 2614 | "version": "1.0.0", 2615 | "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", 2616 | "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", 2617 | "requires": { 2618 | "has-value": "^0.3.1", 2619 | "isobject": "^3.0.0" 2620 | }, 2621 | "dependencies": { 2622 | "has-value": { 2623 | "version": "0.3.1", 2624 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", 2625 | "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", 2626 | "requires": { 2627 | "get-value": "^2.0.3", 2628 | "has-values": "^0.1.4", 2629 | "isobject": "^2.0.0" 2630 | }, 2631 | "dependencies": { 2632 | "isobject": { 2633 | "version": "2.1.0", 2634 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", 2635 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", 2636 | "requires": { 2637 | "isarray": "1.0.0" 2638 | } 2639 | } 2640 | } 2641 | }, 2642 | "has-values": { 2643 | "version": "0.1.4", 2644 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", 2645 | "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" 2646 | }, 2647 | "isobject": { 2648 | "version": "3.0.1", 2649 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 2650 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 2651 | } 2652 | } 2653 | }, 2654 | "unzip-stream": { 2655 | "version": "0.3.0", 2656 | "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.0.tgz", 2657 | "integrity": "sha512-NG1h/MdGIX3HzyqMjyj1laBCmlPYhcO4xEy7gEqqzGiSLw7XqDQCnY4nYSn5XSaH8mQ6TFkaujrO8d/PIZN85A==", 2658 | "requires": { 2659 | "binary": "^0.3.0", 2660 | "mkdirp": "^0.5.1" 2661 | } 2662 | }, 2663 | "uri-js": { 2664 | "version": "4.2.2", 2665 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 2666 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 2667 | "requires": { 2668 | "punycode": "^2.1.0" 2669 | } 2670 | }, 2671 | "urix": { 2672 | "version": "0.1.0", 2673 | "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", 2674 | "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" 2675 | }, 2676 | "use": { 2677 | "version": "3.1.1", 2678 | "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", 2679 | "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" 2680 | }, 2681 | "util-deprecate": { 2682 | "version": "1.0.2", 2683 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2684 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2685 | }, 2686 | "uuid": { 2687 | "version": "3.3.2", 2688 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 2689 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 2690 | }, 2691 | "verror": { 2692 | "version": "1.10.0", 2693 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 2694 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 2695 | "requires": { 2696 | "assert-plus": "^1.0.0", 2697 | "core-util-is": "1.0.2", 2698 | "extsprintf": "^1.2.0" 2699 | } 2700 | }, 2701 | "which": { 2702 | "version": "1.3.1", 2703 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 2704 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 2705 | "requires": { 2706 | "isexe": "^2.0.0" 2707 | } 2708 | }, 2709 | "wrappy": { 2710 | "version": "1.0.2", 2711 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2712 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 2713 | }, 2714 | "xmlbuilder": { 2715 | "version": "8.2.2", 2716 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", 2717 | "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" 2718 | }, 2719 | "yallist": { 2720 | "version": "2.1.2", 2721 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2722 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 2723 | } 2724 | } 2725 | } 2726 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string-extra", 3 | "version": "1.4.0", 4 | "description": "String helper functions for Elm", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "test": "elm-test" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/elm-community/string-extra.git" 15 | }, 16 | "author": "", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/elm-community/string-extra/issues" 20 | }, 21 | "homepage": "https://github.com/elm-community/string-extra#readme", 22 | "dependencies": { 23 | "elm": "0.19.0-bugfix6", 24 | "elm-test": "0.19.0-rev5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/String/Extra.elm: -------------------------------------------------------------------------------- 1 | module String.Extra exposing 2 | ( toSentenceCase, toTitleCase, decapitalize 3 | , camelize, classify, underscored, dasherize, humanize 4 | , replaceSlice, insertAt, nonEmpty, nonBlank, removeAccents 5 | , break, softBreak 6 | , wrap, wrapWith, softWrap, softWrapWith, quote, surround 7 | , isBlank, countOccurrences 8 | , clean, unquote, unsurround, unindent, ellipsis, softEllipsis, ellipsisWith, stripTags, pluralize 9 | , toSentence, toSentenceOxford 10 | , rightOf, leftOf, rightOfBack, leftOfBack 11 | , toCodePoints, fromCodePoints 12 | ) 13 | 14 | {-| Additional functions for working with Strings 15 | 16 | 17 | ## Change words casing 18 | 19 | @docs toSentenceCase, toTitleCase, decapitalize 20 | 21 | 22 | ## Inflector functions 23 | 24 | Functions borrowed from the Rails Inflector class 25 | 26 | @docs camelize, classify, underscored, dasherize, humanize 27 | 28 | 29 | ## Replace and Splice 30 | 31 | @docs replaceSlice, insertAt, nonEmpty, nonBlank, removeAccents 32 | 33 | 34 | ## Splitting 35 | 36 | @docs break, softBreak 37 | 38 | 39 | ## Wrapping 40 | 41 | @docs wrap, wrapWith, softWrap, softWrapWith, quote, surround 42 | 43 | 44 | ## Checks 45 | 46 | @docs isBlank, countOccurrences 47 | 48 | 49 | ## Formatting 50 | 51 | @docs clean, unquote, unsurround, unindent, ellipsis, softEllipsis, ellipsisWith, stripTags, pluralize 52 | 53 | 54 | ## Converting Lists 55 | 56 | @docs toSentence, toSentenceOxford 57 | 58 | 59 | ## Finding 60 | 61 | @docs rightOf, leftOf, rightOfBack, leftOfBack 62 | 63 | 64 | ## Converting UTF-32 65 | 66 | @docs toCodePoints, fromCodePoints 67 | 68 | -} 69 | 70 | import Char exposing (toLower, toUpper) 71 | import List 72 | import Maybe exposing (Maybe(..)) 73 | import Regex exposing (Regex) 74 | import String exposing (cons, join, uncons) 75 | import Tuple 76 | 77 | 78 | {-| Change the case of the first letter of a string to either uppercase or 79 | lowercase, depending of the value of `wantedCase`. This is an internal 80 | function for use in `toSentenceCase` and `decapitalize`. 81 | -} 82 | changeCase : (Char -> Char) -> String -> String 83 | changeCase mutator word = 84 | uncons word 85 | |> Maybe.map (\( head, tail ) -> cons (mutator head) tail) 86 | |> Maybe.withDefault "" 87 | 88 | 89 | {-| Capitalize the first letter of a string. 90 | 91 | toSentenceCase "this is a phrase" == "This is a phrase" 92 | 93 | toSentenceCase "hello, world" == "Hello, world" 94 | 95 | -} 96 | toSentenceCase : String -> String 97 | toSentenceCase word = 98 | changeCase toUpper word 99 | 100 | 101 | {-| Decapitalize the first letter of a string. 102 | 103 | decapitalize "This is a phrase" == "this is a phrase" 104 | 105 | decapitalize "Hello, World" == "hello, World" 106 | 107 | -} 108 | decapitalize : String -> String 109 | decapitalize word = 110 | changeCase toLower word 111 | 112 | 113 | {-| Capitalize the first character of each word in a string. 114 | 115 | toTitleCase "this is a phrase" == "This Is A Phrase" 116 | 117 | toTitleCase "hello, world" == "Hello, World" 118 | 119 | -} 120 | toTitleCase : String -> String 121 | toTitleCase ws = 122 | let 123 | uppercaseMatch = 124 | Regex.replace (regexFromString "\\w+") (.match >> toSentenceCase) 125 | in 126 | ws 127 | |> Regex.replace 128 | (regexFromString "^([a-z])|\\s+([a-z])") 129 | (.match >> uppercaseMatch) 130 | 131 | 132 | {-| Replace text within a portion of a string given a substitution 133 | string, a start index and an end index. The substitution includes the character 134 | at the start index but not the one at the end index. 135 | 136 | replaceSlice "Sue" 4 7 "Hi, Bob" == "Hi, Sue" 137 | 138 | replaceSlice "elephants" 0 6 "snakes on a plane!" == "elephants on a plane!" 139 | 140 | replaceSlice "under" 7 9 "snakes on a plane!" == "snakes under a plane!" 141 | 142 | -} 143 | replaceSlice : String -> Int -> Int -> String -> String 144 | replaceSlice substitution start end string = 145 | String.slice 0 start string ++ substitution ++ String.slice end (String.length string) string 146 | 147 | 148 | {-| Insert a substring at the specified index. 149 | 150 | insertAt "world" 6 "Hello " == "Hello world" 151 | 152 | -} 153 | insertAt : String -> Int -> String -> String 154 | insertAt insert pos string = 155 | replaceSlice insert pos pos string 156 | 157 | 158 | {-| Break a string into a list of strings of a specified maximum length. 159 | 160 | break 10 "The quick brown fox" == [ "The quick ", "brown fox" ] 161 | 162 | break 2 "" == [ "" ] 163 | 164 | -} 165 | break : Int -> String -> List String 166 | break width string = 167 | if width == 0 || string == "" then 168 | [ string ] 169 | 170 | else 171 | breaker width string [] 172 | 173 | 174 | breaker : Int -> String -> List String -> List String 175 | breaker width string acc = 176 | case string of 177 | "" -> 178 | List.reverse acc 179 | 180 | _ -> 181 | breaker width 182 | (String.dropLeft width string) 183 | (String.slice 0 width string :: acc) 184 | 185 | 186 | {-| Break a string into a list of strings of a specified maximum length, 187 | without truncating words. 188 | 189 | softBreak 6 "The quick brown fox" == [ "The quick", " brown", " fox" ] 190 | 191 | -} 192 | softBreak : Int -> String -> List String 193 | softBreak width string = 194 | if width <= 0 then 195 | [] 196 | 197 | else 198 | string 199 | |> Regex.find (softBreakRegexp width) 200 | |> List.map .match 201 | 202 | 203 | softBreakRegexp : Int -> Regex.Regex 204 | softBreakRegexp width = 205 | regexFromString <| ".{1," ++ String.fromInt width ++ "}(\\s+|$)|\\S+?(\\s+|$)" 206 | 207 | 208 | {-| Trim the whitespace of both sides of the string and compress 209 | repeated whitespace internally to a single whitespace char. 210 | 211 | clean " The quick brown fox " == "The quick brown fox" 212 | 213 | -} 214 | clean : String -> String 215 | clean string = 216 | string 217 | |> Regex.replace (regexFromString "\\s\\s+") (always " ") 218 | |> String.trim 219 | 220 | 221 | {-| Test if a string is empty or only contains whitespace. 222 | 223 | isBlank "" == True 224 | 225 | isBlank "\n" == True 226 | 227 | isBlank " " == True 228 | 229 | isBlank " a" == False 230 | 231 | -} 232 | isBlank : String -> Bool 233 | isBlank string = 234 | Regex.contains (regexFromString "^\\s*$") string 235 | 236 | 237 | {-| Convert an underscored or dasherized string to a camelized one. 238 | 239 | camelize "-moz-transform" == "MozTransform" 240 | 241 | -} 242 | camelize : String -> String 243 | camelize string = 244 | Regex.replace 245 | (regexFromString "[-_\\s]+(.)?") 246 | (\{ submatches } -> 247 | case submatches of 248 | (Just match) :: _ -> 249 | String.toUpper match 250 | 251 | _ -> 252 | "" 253 | ) 254 | (String.trim string) 255 | 256 | 257 | {-| Convert a string to a camelized string starting with an uppercase letter. 258 | All non-word characters will be stripped out of the original string. 259 | 260 | classify "some_class_name" == "SomeClassName" 261 | 262 | classify "myLittleCamel.class.name" == "MyLittleCamelClassName" 263 | 264 | -} 265 | classify : String -> String 266 | classify string = 267 | string 268 | |> Regex.replace (regexFromString "[\\W_]") (always " ") 269 | |> camelize 270 | |> String.replace " " "" 271 | |> toSentenceCase 272 | 273 | 274 | {-| Surround a string with another string. 275 | 276 | surround "bar" "foo" == "barfoobar" 277 | 278 | -} 279 | surround : String -> String -> String 280 | surround wrapper string = 281 | wrapper ++ string ++ wrapper 282 | 283 | 284 | {-| Remove surrounding strings from another string. 285 | 286 | unsurround "foo" "foobarfoo" == "bar" 287 | 288 | -} 289 | unsurround : String -> String -> String 290 | unsurround wrapper string = 291 | if String.startsWith wrapper string && String.endsWith wrapper string then 292 | let 293 | length = 294 | String.length wrapper 295 | in 296 | string 297 | |> String.dropLeft length 298 | |> String.dropRight length 299 | 300 | else 301 | string 302 | 303 | 304 | {-| Add quotes to a string. 305 | 306 | quote "foo" == "\"foo\"" 307 | 308 | -} 309 | quote : String -> String 310 | quote string = 311 | surround "\"" string 312 | 313 | 314 | {-| Remove quotes that surround a string. 315 | 316 | unquote "\"foo\"" == "foo" 317 | 318 | unquote "\"foo\"bar\"" 319 | 320 | -} 321 | unquote : String -> String 322 | unquote string = 323 | unsurround "\"" string 324 | 325 | 326 | {-| Return a string joined by underscores after separating it by its uppercase characters. 327 | Any sequence of spaces or dashes will also be converted to a single underscore. 328 | The final string will be lowercased. 329 | 330 | underscored "SomeClassName" == "some_class_name" 331 | underscored "some-class-name" == "some_class_name" 332 | underscored "SomeClass name" == "some_class_name 333 | 334 | -} 335 | underscored : String -> String 336 | underscored string = 337 | string 338 | |> String.trim 339 | |> Regex.replace (regexFromString "([a-z\\d])([A-Z]+)") (.submatches >> List.filterMap identity >> String.join "_") 340 | |> Regex.replace (regexFromString "[_-\\s]+") (always "_") 341 | |> String.toLower 342 | 343 | 344 | {-| Return a string joined by dashes after separating it by its uppercase characters. 345 | Any sequence of spaces or underscores will also be converted to a single dash. 346 | The final string will be lowercased. 347 | 348 | dasherize "SomeClassName" == "-some-class-name" 349 | dasherize "some_class_name" = "some-class-name" 350 | dasherize "someClass name" = "some-class-name" 351 | 352 | -} 353 | dasherize : String -> String 354 | dasherize string = 355 | string 356 | |> String.trim 357 | |> Regex.replace (regexFromString "([A-Z])") (.match >> String.append "-") 358 | |> Regex.replace (regexFromString "[_-\\s]+") (always "-") 359 | |> String.toLower 360 | 361 | 362 | {-| Separate a string into parts of a given width, using a given separator. 363 | 364 | Look at `wrap` if you just want to wrap using newlines. 365 | 366 | wrapWith 7 "\n" "My very long text" === "My very\nlong text" 367 | 368 | wrapWith 100 "\n" "Too short" === "Too short" 369 | 370 | -} 371 | wrapWith : Int -> String -> String -> String 372 | wrapWith width separator string = 373 | string 374 | |> break width 375 | |> String.join separator 376 | 377 | 378 | {-| Chop a given string into parts of a given width, separating them with a 379 | new line. 380 | 381 | wrap 7 "My very long text" === "My very\nlong te\nxt" 382 | 383 | wrap 100 "Too short" === "Too short" 384 | 385 | -} 386 | wrap : Int -> String -> String 387 | wrap width string = 388 | wrapWith width "\n" string 389 | 390 | 391 | {-| Chop a given string into parts of a given width without breaking words apart, 392 | and then separate them using a new line. 393 | 394 | softWrap 7 "My very long text" === "My very\nlong text" 395 | 396 | softWrap 3 "Hello World" === "Hello \nWorld" 397 | 398 | softWrap 100 "Too short" === "Too short" 399 | 400 | -} 401 | softWrap : Int -> String -> String 402 | softWrap width string = 403 | softWrapWith width "\n" string 404 | 405 | 406 | {-| Chop a given string into parts of a given width without breaking words apart, 407 | and then separate them using the given separator. 408 | 409 | softWrapWith 7 "..." "My very long text" === "My very...long text" 410 | 411 | softWrapWith 3 "\n" "Hello World" === "Hello \nWorld" 412 | 413 | softWrapWith 100 "\t" "Too short" === "Too short" 414 | 415 | -} 416 | softWrapWith : Int -> String -> String -> String 417 | softWrapWith width separator string = 418 | string 419 | |> softBreak width 420 | |> String.join separator 421 | 422 | 423 | {-| Convert an underscored, camelized, or dasherized string into one that can be 424 | read by humans. Also remove beginning and ending whitespace, and removes the 425 | postfix '\_id'. The first character will be capitalized. 426 | 427 | humanize "this_is_great" == "This is great" 428 | humanize "ThisIsGreat" = "This is great" 429 | humanize "this-is-great" = "This is great" 430 | humanize "author_id" = "Author" 431 | 432 | -} 433 | humanize : String -> String 434 | humanize string = 435 | string 436 | |> Regex.replace (regexFromString "[A-Z]+") (.match >> String.append "-") 437 | |> Regex.replace (regexFromString "_id$|[-_\\s]+") (always " ") 438 | |> String.trim 439 | |> String.toLower 440 | |> toSentenceCase 441 | 442 | 443 | {-| Remove the shortest sequence of leading spaces or tabs on each line 444 | of the string, so that at least one of the lines will not have any 445 | leading spaces nor tabs and the rest of the lines will have the same 446 | amount of indentation removed. 447 | 448 | unindent " Hello\n World " == "Hello\n World" 449 | 450 | unindent "\t\tHello\n\t\t\t\tWorld" == "Hello\n\t\tWorld" 451 | 452 | -} 453 | unindent : String -> String 454 | unindent multilineSting = 455 | let 456 | lines = 457 | String.lines multilineSting 458 | 459 | countLeadingWhitespace count line = 460 | case String.uncons line of 461 | Nothing -> 462 | count 463 | 464 | Just ( char, rest ) -> 465 | case char of 466 | ' ' -> 467 | countLeadingWhitespace (count + 1) rest 468 | 469 | '\t' -> 470 | countLeadingWhitespace (count + 1) rest 471 | 472 | _ -> 473 | count 474 | 475 | isNotWhitespace char = 476 | char /= ' ' && char /= '\t' 477 | 478 | minLead = 479 | lines 480 | |> List.filter (String.any isNotWhitespace) 481 | |> List.map (countLeadingWhitespace 0) 482 | |> List.minimum 483 | |> Maybe.withDefault 0 484 | in 485 | lines 486 | |> List.map (String.dropLeft minLead) 487 | |> String.join "\n" 488 | 489 | 490 | {-| Return the number of occurrences of a substring in another string. 491 | 492 | countOccurrences "Hello" "Hello World" == 1 493 | 494 | countOccurrences "o" "Hello World" == 2 495 | 496 | -} 497 | countOccurrences : String -> String -> Int 498 | countOccurrences needle haystack = 499 | if String.length needle == 0 || String.length haystack == 0 then 500 | 0 501 | 502 | else 503 | haystack 504 | |> String.indexes needle 505 | |> List.length 506 | 507 | 508 | {-| Truncate the second string at the specified length if the string is 509 | longer than the specified length, and replace the end of the truncated 510 | string with the first string, such that the resulting string is of the 511 | specified length. 512 | 513 | The resulting string will have at most the specified length. 514 | 515 | ellipsisWith 5 " .." "Hello World" == "He .." 516 | 517 | ellipsisWith 10 " .." "Hello World" == "Hello W .." 518 | 519 | ellipsisWith 10 " .." "Hello" == "Hello" 520 | 521 | ellipsisWith 8 " .." "Hello World" == "Hello .." 522 | 523 | -} 524 | ellipsisWith : Int -> String -> String -> String 525 | ellipsisWith howLong append string = 526 | if String.length string <= howLong then 527 | string 528 | 529 | else 530 | String.left (howLong - String.length append) string ++ append 531 | 532 | 533 | {-| Truncate the string at the specified length if the string is 534 | longer than the specified length, and replace the end of the truncated 535 | string with `"..."`, such that the resulting string is of the 536 | specified length. 537 | 538 | The resulting string will have at most the specified length. 539 | 540 | ellipsis 5 "Hello World" == "He..." 541 | 542 | ellipsis 10 "Hello World" == "Hello W..." 543 | 544 | ellipsis 10 "Hello" == "Hello" 545 | 546 | ellipsis 8 "Hello World" == "Hello..." 547 | 548 | -} 549 | ellipsis : Int -> String -> String 550 | ellipsis howLong string = 551 | ellipsisWith howLong "..." string 552 | 553 | 554 | {-| Truncate the string at the last complete word less than or equal to 555 | the specified length and append `"..."`. When the specified length is 556 | less than the length of the first word, the ellipsis is appended to the 557 | first word. When the specified length is greater than or equal to the 558 | length of the string, an identical string is returned. 559 | 560 | In contrast to `ellipsis`, this function will not produce incomplete 561 | words, and the resulting string can exceed the specified length. In 562 | addition, it removes trailing whitespace and punctuation characters at 563 | the end of the truncated string. 564 | 565 | softEllipsis 1 "Hello, World" == "Hello..." 566 | 567 | softEllipsis 5 "Hello, World" == "Hello..." 568 | 569 | softEllipsis 6 "Hello, World" == "Hello..." 570 | 571 | softEllipsis 15 "Hello, cruel world" == "Hello, cruel..." 572 | 573 | softEllipsis 10 "Hello" == "Hello" 574 | 575 | -} 576 | softEllipsis : Int -> String -> String 577 | softEllipsis howLong string = 578 | if String.length string <= howLong then 579 | string 580 | 581 | else 582 | string 583 | |> Regex.findAtMost 1 (softBreakRegexp howLong) 584 | |> List.map .match 585 | |> String.join "" 586 | |> Regex.replace (regexFromString "([\\.,;:\\s])+$") (always "") 587 | |> (\a -> String.append a "...") 588 | 589 | 590 | {-| Convert a list of strings into a human-readable list. 591 | 592 | toSentence [] == "" 593 | 594 | toSentence [ "lions" ] == "lions" 595 | 596 | toSentence [ "lions", "tigers" ] == "lions and tigers" 597 | 598 | toSentence [ "lions", "tigers", "bears" ] == "lions, tigers and bears" 599 | 600 | -} 601 | toSentence : List String -> String 602 | toSentence list = 603 | case list of 604 | x :: y :: z :: more -> 605 | toSentenceHelper " and " (x ++ ", " ++ y) (z :: more) 606 | 607 | _ -> 608 | toSentenceBaseCase list 609 | 610 | 611 | {-| Convert a list of strings into a human-readable list using an oxford comma. 612 | 613 | toSentenceOxford [] == "" 614 | 615 | toSentenceOxford [ "lions" ] == "lions" 616 | 617 | toSentenceOxford [ "lions", "tigers" ] == "lions and tigers" 618 | 619 | toSentenceOxford [ "lions", "tigers", "bears" ] == "lions, tigers, and bears" 620 | 621 | -} 622 | toSentenceOxford : List String -> String 623 | toSentenceOxford list = 624 | case list of 625 | x :: y :: z :: more -> 626 | toSentenceHelper ", and " (x ++ ", " ++ y) (z :: more) 627 | 628 | _ -> 629 | toSentenceBaseCase list 630 | 631 | 632 | toSentenceBaseCase : List String -> String 633 | toSentenceBaseCase list = 634 | case list of 635 | x :: [] -> 636 | x 637 | 638 | x :: y :: [] -> 639 | x ++ " and " ++ y 640 | 641 | _ -> 642 | "" 643 | 644 | 645 | toSentenceHelper : String -> String -> List String -> String 646 | toSentenceHelper lastPart sentence list = 647 | case list of 648 | [] -> 649 | sentence 650 | 651 | x :: [] -> 652 | sentence ++ lastPart ++ x 653 | 654 | x :: xs -> 655 | toSentenceHelper lastPart (sentence ++ ", " ++ x) xs 656 | 657 | 658 | {-| Remove all HTML tags from the string, preserving the text inside them. 659 | 660 | stripTags "a link" == "a link" 661 | stripTags " == "alert('hello world!')" 662 | 663 | -} 664 | stripTags : String -> String 665 | stripTags string = 666 | string 667 | |> Regex.replace (regexFromString "<\\/?[^>]+>") (always "") 668 | 669 | 670 | {-| Given a number, a singular string, and a plural string, return the number 671 | followed by a space, followed by either the singular string if the number was 1, 672 | or the plural string otherwise. 673 | 674 | pluralize "elf" "elves" 2 == "2 elves" 675 | 676 | pluralize "elf" "elves" 1 == "1 elf" 677 | 678 | pluralize "elf" "elves" 0 == "0 elves" 679 | 680 | -} 681 | pluralize : String -> String -> Int -> String 682 | pluralize singular plural count = 683 | if count == 1 then 684 | "1 " ++ singular 685 | 686 | else 687 | String.fromInt count ++ " " ++ plural 688 | 689 | 690 | {-| Search a string from left to right for a pattern and return a substring 691 | consisting of the characters in the string that are to the right of the pattern. 692 | 693 | rightOf "_" "This_is_a_test_string" == "is_a_test_string" 694 | 695 | -} 696 | rightOf : String -> String -> String 697 | rightOf pattern string = 698 | string 699 | |> Regex.findAtMost 1 (regexFromString <| regexEscape pattern ++ "(.*)$") 700 | |> List.map (.submatches >> firstResult) 701 | |> String.join "" 702 | 703 | 704 | {-| Search a string from left to right for a pattern and return a substring 705 | consisting of the characters in the string that are to the left of the pattern. 706 | 707 | leftOf "_" "This_is_a_test_string" == "This" 708 | 709 | -} 710 | leftOf : String -> String -> String 711 | leftOf pattern string = 712 | string 713 | |> Regex.findAtMost 1 (regexFromString <| "^(.*?)" ++ regexEscape pattern) 714 | |> List.map (.submatches >> firstResult) 715 | |> String.join "" 716 | 717 | 718 | firstResult : List (Maybe String) -> String 719 | firstResult list = 720 | firstResultHelp "" list 721 | 722 | 723 | firstResultHelp : String -> List (Maybe String) -> String 724 | firstResultHelp default list = 725 | case list of 726 | [] -> 727 | default 728 | 729 | (Just a) :: _ -> 730 | a 731 | 732 | Nothing :: rest -> 733 | firstResultHelp default rest 734 | 735 | 736 | {-| Search a string from right to left for a pattern and return a substring 737 | consisting of the characters in the string that are to the right of the pattern. 738 | 739 | rightOfBack "_" "This_is_a_test_string" == "string" 740 | 741 | -} 742 | rightOfBack : String -> String -> String 743 | rightOfBack pattern string = 744 | string 745 | |> String.indexes pattern 746 | |> List.reverse 747 | |> List.head 748 | |> Maybe.map ((+) (String.length pattern) >> (\a -> String.dropLeft a string)) 749 | |> Maybe.withDefault "" 750 | 751 | 752 | {-| Search a string from right to left for a pattern and return a substring 753 | consisting of the characters in the string that are to the left of the pattern. 754 | 755 | leftOfBack "_" "This_is_a_test_string" == "This_is_a_test" 756 | 757 | -} 758 | leftOfBack : String -> String -> String 759 | leftOfBack pattern string = 760 | string 761 | |> String.indexes pattern 762 | |> List.reverse 763 | |> List.head 764 | |> Maybe.map (\a -> String.left a string) 765 | |> Maybe.withDefault "" 766 | 767 | 768 | {-| Convert a string into a list of UTF-32 code points. 769 | 770 | toCodePoints "abc" == [ 97, 98, 99 ] 771 | 772 | toCodePoints "©§π" == [ 169, 167, 960 ] 773 | 774 | toCodePoints "💩!" == [ 128169, 33 ] 775 | 776 | Note that code points do not necessarily correspond to logical/visual 777 | characters, since it is possible for things like accented characters to be 778 | represented as two separate UTF-32 code points (a base character and a 779 | combining accent). 780 | 781 | `toCodePoints string` is equivalent to: 782 | 783 | List.map Char.toCode (String.toList string) 784 | 785 | -} 786 | toCodePoints : String -> List Int 787 | toCodePoints string = 788 | List.map Char.toCode (String.toList string) 789 | 790 | 791 | {-| Convert a list of UTF-32 code points into a string. Inverse of 792 | `toCodePoints`. 793 | 794 | fromCodePoints [ 97, 98, 99 ] == "abc" 795 | 796 | fromCodePoints [ 169, 167, 960 ] == "©§π" 797 | 798 | fromCodePoints [ 128169, 33 ] == "💩!" 799 | 800 | `fromCodePoints codePoints` is equivalent to: 801 | 802 | String.fromList (List.map Char.fromCode codePoints) 803 | 804 | -} 805 | fromCodePoints : List Int -> String 806 | fromCodePoints codePoints = 807 | String.fromList (List.map Char.fromCode codePoints) 808 | 809 | 810 | {-| Convert a string to a Nothing when empty. 811 | 812 | nonEmpty "" == Nothing 813 | 814 | nonEmpty "Hello world" == Just "Hello world" 815 | 816 | -} 817 | nonEmpty : String -> Maybe String 818 | nonEmpty string = 819 | if String.isEmpty string then 820 | Nothing 821 | 822 | else 823 | Just string 824 | 825 | 826 | {-| Convert a string to a Nothing when blank. 827 | 828 | nonBlank "" == Nothing 829 | 830 | nonBlank " " == Nothing 831 | 832 | nonBlank "Hello world" == Just "Hello world" 833 | 834 | -} 835 | nonBlank : String -> Maybe String 836 | nonBlank string = 837 | if isBlank string then 838 | Nothing 839 | 840 | else 841 | Just string 842 | 843 | 844 | {-| Remove accents from string. 845 | 846 | removeAccents "andré" == "andre" 847 | 848 | removeAccents "Atenção" == "Atencao" 849 | 850 | -} 851 | removeAccents : String -> String 852 | removeAccents string = 853 | if String.isEmpty string then 854 | string 855 | 856 | else 857 | let 858 | do_regex_to_remove_acents ( regex, replace_character ) = 859 | Regex.replace regex (\_ -> replace_character) 860 | in 861 | List.foldl do_regex_to_remove_acents string accentRegex 862 | 863 | 864 | {-| Create list with regex and char to replace. 865 | -} 866 | accentRegex : List ( Regex.Regex, String ) 867 | accentRegex = 868 | let 869 | matches = 870 | [ ( "[à-æ]", "a" ) 871 | , ( "[À-Æ]", "A" ) 872 | , ( "ç", "c" ) 873 | , ( "Ç", "C" ) 874 | , ( "[è-ë]", "e" ) 875 | , ( "[È-Ë]", "E" ) 876 | , ( "[ì-ï]", "i" ) 877 | , ( "[Ì-Ï]", "I" ) 878 | , ( "ñ", "n" ) 879 | , ( "Ñ", "N" ) 880 | , ( "[ò-ö]", "o" ) 881 | , ( "[Ò-Ö]", "O" ) 882 | , ( "[ù-ü]", "u" ) 883 | , ( "[Ù-Ü]", "U" ) 884 | , ( "ý", "y" ) 885 | , ( "ÿ", "y" ) 886 | , ( "Ý", "Y" ) 887 | ] 888 | in 889 | List.map (Tuple.mapFirst regexFromString) matches 890 | 891 | 892 | regexEscape : String -> String 893 | regexEscape = 894 | Regex.replace (regexFromString "[-/\\^$*+?.()|[\\]{}]") (\{ match } -> "\\" ++ match) 895 | 896 | 897 | regexFromString : String -> Regex 898 | regexFromString = 899 | Regex.fromString >> Maybe.withDefault Regex.never 900 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | elm.js 3 | test.js 4 | -------------------------------------------------------------------------------- /tests/CamelizeTest.elm: -------------------------------------------------------------------------------- 1 | module CamelizeTest exposing (camelizeTest) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import Regex 7 | import String exposing (replace, uncons) 8 | import String.Extra exposing (..) 9 | import Test exposing (..) 10 | import TestData 11 | 12 | 13 | camelizeTest : Test 14 | camelizeTest = 15 | describe "camelize" 16 | [ fuzz string "It does not contain dashes" <| 17 | \s -> 18 | camelize s 19 | |> String.contains "-" 20 | |> Expect.false "Camelize should remove dashes" 21 | , fuzz string "It does not contain underscores" <| 22 | \s -> 23 | camelize s 24 | |> String.contains "-" 25 | |> Expect.false "Camelize should remove underscores" 26 | , fuzz string "It is the same lowercased string after removing the dashes and spaces" <| 27 | \s -> 28 | let 29 | expected = 30 | replace "-" "" 31 | >> replace "_" "" 32 | >> Regex.replace (Regex.fromString "\\s+" |> Maybe.withDefault Regex.never) (\_ -> "") 33 | >> String.toLower 34 | in 35 | camelize s 36 | |> String.toLower 37 | |> Expect.equal (expected s) 38 | , fuzz (validWords '-') "The first letter after each dash is capitalized" <| 39 | \s -> 40 | camelize s 41 | |> Expect.equal (runCamelize "-" s) 42 | , fuzz (validWords ' ') "The first letter after each space is capitalized" <| 43 | \s -> 44 | camelize s 45 | |> Expect.equal (runCamelize " " s) 46 | ] 47 | 48 | 49 | runCamelize : String -> String -> String 50 | runCamelize separator string = 51 | string 52 | |> String.trim 53 | |> replace (separator ++ separator) separator 54 | |> String.split separator 55 | |> List.indexedMap capitalizeOdds 56 | |> String.join "" 57 | 58 | 59 | capitalizeOdds : Int -> String -> String 60 | capitalizeOdds pos str = 61 | if pos > 0 then 62 | toSentenceCase str 63 | 64 | else 65 | str 66 | 67 | 68 | validWords : Char -> Fuzzer String 69 | validWords ch = 70 | TestData.randomStringsWithChars [ ch ] 71 | -------------------------------------------------------------------------------- /tests/ClassifyTest.elm: -------------------------------------------------------------------------------- 1 | module ClassifyTest exposing (classifyTest) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import Random 7 | import Regex 8 | import String exposing (replace, uncons) 9 | import String.Extra exposing (..) 10 | import Test exposing (..) 11 | import TestData 12 | import Tuple exposing (first, second) 13 | 14 | 15 | classifyTest : Test 16 | classifyTest = 17 | describe "classify" 18 | [ fuzz string "It does not contain non-word characters" <| 19 | \string -> 20 | classify string 21 | |> Regex.contains (Regex.fromString "[\\W]" |> Maybe.withDefault Regex.never) 22 | |> Expect.false "Non word characters detected" 23 | , fuzz TestData.randomStrings "It starts with an uppercase letter" <| 24 | \string -> 25 | string 26 | |> classify 27 | |> uncons 28 | |> Maybe.map first 29 | |> Expect.equal (string |> String.trim |> String.toUpper |> uncons |> Maybe.map first) 30 | , fuzz validWords "It is camelized once replaced non word charactes with a compatible string" <| 31 | \string -> 32 | string 33 | |> classify 34 | |> uncons 35 | |> Maybe.map second 36 | |> Expect.equal (string |> replace "." "-" |> camelize |> uncons |> Maybe.map second) 37 | ] 38 | 39 | 40 | validWords : Fuzzer String 41 | validWords = 42 | TestData.randomStringsWithCharGenerators 43 | [ Random.map Char.fromCode (Random.int 45 46) 44 | , Random.constant (Char.fromCode 95) 45 | ] 46 | -------------------------------------------------------------------------------- /tests/DasherizeTest.elm: -------------------------------------------------------------------------------- 1 | module DasherizeTest exposing (dasherizeTest) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import String exposing (replace, uncons) 7 | import String.Extra exposing (..) 8 | import Test exposing (..) 9 | import TestData 10 | 11 | 12 | dasherizeTest : Test 13 | dasherizeTest = 14 | describe "dasherize" 15 | [ fuzz string "It is a lowercased string" <| 16 | \s -> 17 | dasherize s 18 | |> String.toLower 19 | |> Expect.equal (dasherize s) 20 | , fuzz string "It replaces spaces and underscores with a dash" <| 21 | \s -> 22 | let 23 | expected = 24 | String.toLower 25 | >> String.trim 26 | >> replace " " " " 27 | >> replace " " "-" 28 | >> replace "_" "-" 29 | >> replace "--" "-" 30 | >> replace "--" "-" 31 | in 32 | dasherize (String.toLower s) 33 | |> String.toLower 34 | |> Expect.equal (expected s) 35 | , fuzz TestData.randomStrings "It puts dash before every single uppercase character" <| 36 | \s -> 37 | dasherize s 38 | |> Expect.equal (replaceUppercase s |> String.toLower) 39 | ] 40 | 41 | 42 | replaceUppercase : String -> String 43 | replaceUppercase string = 44 | string 45 | |> String.toList 46 | |> List.map 47 | (\c -> 48 | if Char.isUpper c then 49 | "-" ++ String.fromChar c 50 | 51 | else 52 | String.fromChar c 53 | ) 54 | |> String.join "" 55 | -------------------------------------------------------------------------------- /tests/HumanizeTest.elm: -------------------------------------------------------------------------------- 1 | module HumanizeTest exposing (humanizeTest) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import Regex 7 | import String 8 | import String.Extra exposing (..) 9 | import Test exposing (..) 10 | import TestData 11 | import Tuple exposing (first, second) 12 | 13 | 14 | humanizeTest : Test 15 | humanizeTest = 16 | describe "humanize" 17 | [ test "All uppercase" <| 18 | \_ -> 19 | humanize "ALL_UPPERCASE IS FINE" 20 | |> Expect.equal "All uppercase is fine" 21 | , test "Some uppercase" <| 22 | \_ -> 23 | humanize "I like HTML" 24 | |> Expect.equal "I like html" 25 | , test "Snake case" <| 26 | \_ -> 27 | humanize "this_is_great" 28 | |> Expect.equal "This is great" 29 | , test "Capitalized" <| 30 | \_ -> 31 | humanize "ThisIsGreat" 32 | |> Expect.equal "This is great" 33 | , test "Kebab case" <| 34 | \_ -> 35 | humanize "this-is-great" 36 | |> Expect.equal "This is great" 37 | , test "Id suffix" <| 38 | \_ -> 39 | humanize "author_id" 40 | |> Expect.equal "Author" 41 | , fuzz (validWords []) "It starts with an uppercase letter after trimming" <| 42 | \s -> 43 | let 44 | expected = 45 | String.trim 46 | >> toSentenceCase 47 | >> String.uncons 48 | >> Maybe.map (first >> String.fromChar) 49 | >> Maybe.withDefault "" 50 | in 51 | humanize s 52 | |> String.uncons 53 | |> Maybe.map (first >> String.fromChar) 54 | |> Maybe.withDefault "" 55 | |> Expect.equal (expected s) 56 | , fuzz (validWords []) "The tail of the string is lowercased" <| 57 | \s -> 58 | humanize s 59 | |> String.uncons 60 | |> Maybe.map second 61 | |> Maybe.withDefault "a" 62 | |> String.filter ((/=) ' ') 63 | |> String.all Char.isLower 64 | |> Expect.true "Not all characters in the string are lowercased" 65 | , fuzz (validWords [ '_', '-' ]) "It removes a trailing `_id` & replaces underscores and dashes with a single whitespace" <| 66 | \s -> 67 | let 68 | expected = 69 | String.toLower 70 | >> Regex.replaceAtMost 1 (regex "_id$") (\_ -> "") 71 | >> String.replace "-" " " 72 | >> String.replace "_" " " 73 | >> Regex.replace (regex "\\s+") (\_ -> " ") 74 | >> String.trim 75 | in 76 | humanize (String.toLower s) 77 | |> String.toLower 78 | |> Expect.equal (expected s) 79 | , fuzz string "It yields the same string after removing underscores, dashes and spaces" <| 80 | \s -> 81 | let 82 | expected = 83 | String.replace "-" "" 84 | >> String.replace "_" "" 85 | >> Regex.replace (regex "\\s+") (\_ -> "") 86 | >> String.toLower 87 | in 88 | humanize s 89 | |> String.replace " " "" 90 | |> String.toLower 91 | |> Expect.equal (expected s) 92 | , fuzz (validWords []) "It adds a space before each group of uppercase letter" <| 93 | \s -> 94 | let 95 | expected = 96 | Regex.replace (regex "[A-Z]+") (\{ match } -> " " ++ match) 97 | >> String.toLower 98 | >> String.trim 99 | in 100 | humanize s 101 | |> String.toLower 102 | |> Expect.equal (expected s) 103 | , fuzz string "It does not leave double spaces around" <| 104 | \s -> 105 | let 106 | expected = 107 | replaceUppercase >> String.toLower >> String.trim 108 | in 109 | humanize s 110 | |> String.contains " " 111 | |> Expect.false "The string contains double spaces" 112 | , fuzz idString "It strips the _id at the end" <| 113 | \s -> 114 | humanize s 115 | |> String.endsWith "id" 116 | |> Expect.false "The string should not end with id" 117 | ] 118 | 119 | 120 | idString : Fuzzer String 121 | idString = 122 | validWords [ '-', '_' ] 123 | |> map (\s -> s ++ "s_id") 124 | 125 | 126 | validWords : List Char -> Fuzzer String 127 | validWords ch = 128 | TestData.randomStringsWithChars ch 129 | 130 | 131 | replaceUppercase : String -> String 132 | replaceUppercase string = 133 | string 134 | |> String.toList 135 | |> List.map 136 | (\c -> 137 | if Char.isUpper c then 138 | " " ++ String.fromChar c 139 | 140 | else 141 | String.fromChar c 142 | ) 143 | |> String.join "" 144 | 145 | 146 | regex str = 147 | Maybe.withDefault Regex.never <| 148 | Regex.fromString str 149 | -------------------------------------------------------------------------------- /tests/NonEmptyTest.elm: -------------------------------------------------------------------------------- 1 | module NonEmptyTest exposing (nonEmptyTest) 2 | 3 | import Expect 4 | import String.Extra exposing (nonEmpty) 5 | import Test exposing (..) 6 | 7 | 8 | nonEmptyTest : Test 9 | nonEmptyTest = 10 | describe "nonEmpty" 11 | [ test "Should result in a just when string has greater length than 0" <| 12 | \() -> 13 | nonEmpty "Hello world" 14 | |> Expect.equal (Just "Hello world") 15 | , test "Should result in Nothing when an empty string is passed in" <| 16 | \() -> 17 | nonEmpty "" 18 | |> Expect.equal Nothing 19 | ] 20 | -------------------------------------------------------------------------------- /tests/RemoveAccentsTest.elm: -------------------------------------------------------------------------------- 1 | module RemoveAccentsTest exposing (removeAccentsTest) 2 | 3 | import Expect 4 | import String.Extra exposing (removeAccents) 5 | import Test exposing (..) 6 | 7 | 8 | removeAccentsTest : Test 9 | removeAccentsTest = 10 | describe "removeAccents" 11 | [ test "Should result string without accents" <| 12 | \() -> 13 | removeAccents "áàãâäéèêëíìîïóòõôöúùûüçÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ" 14 | |> Expect.equal "aaaaaeeeeiiiiooooouuuucAAAAAEEEEIIIIOOOOOUUUUC" 15 | , test "Should result in phrase without accents" <| 16 | \() -> 17 | removeAccents "andré JOÂO" 18 | |> Expect.equal "andre JOAO" 19 | ] 20 | -------------------------------------------------------------------------------- /tests/ReplaceSliceTest.elm: -------------------------------------------------------------------------------- 1 | module ReplaceSliceTest exposing (replaceSliceTest) 2 | 3 | import Expect 4 | import Fuzz exposing (..) 5 | import Random 6 | import Shrink 7 | import String 8 | import String.Extra exposing (..) 9 | import Test exposing (..) 10 | import TestData 11 | 12 | 13 | replaceSliceTest : Test 14 | replaceSliceTest = 15 | describe "replaceSlice" 16 | [ fuzz replaceSliceProducer "Result contains the substitution string" <| 17 | \( ( string, sub ), ( start, end ) ) -> 18 | case string of 19 | "" -> 20 | replaceSlice sub start end string 21 | |> Expect.equal sub 22 | 23 | _ -> 24 | replaceSlice sub start end string 25 | |> String.contains sub 26 | |> Expect.true "The slice was not subtituted" 27 | , fuzz replaceSliceProducer "Result string has the length of the substitution + string after removing the slice" <| 28 | \( ( string, sub ), ( start, end ) ) -> 29 | case string of 30 | "" -> 31 | replaceSlice sub start end string 32 | |> String.length 33 | |> Expect.equal (String.length sub) 34 | 35 | _ -> 36 | replaceSlice sub start end string 37 | |> String.length 38 | |> Expect.equal ((String.length string - (end - start)) + String.length sub) 39 | , fuzz replaceSliceProducer "Start of the original string remains the same" <| 40 | \( ( string, sub ), ( start, end ) ) -> 41 | case string of 42 | "" -> 43 | replaceSlice sub start end string 44 | |> Expect.equal sub 45 | 46 | _ -> 47 | replaceSlice sub start end string 48 | |> String.slice 0 start 49 | |> Expect.equal (String.slice 0 start string) 50 | , fuzz replaceSliceProducer "End of the original string remains the same" <| 51 | \( ( string, sub ), ( start, end ) ) -> 52 | let 53 | replaced = 54 | replaceSlice sub start end string 55 | in 56 | case string of 57 | "" -> 58 | replaced 59 | |> Expect.equal sub 60 | 61 | _ -> 62 | replaced 63 | |> String.slice (start + String.length sub) (String.length replaced) 64 | |> Expect.equal (String.slice end (String.length string) string) 65 | ] 66 | 67 | 68 | replaceSliceProducer : Fuzzer ( ( String, String ), ( Int, Int ) ) 69 | replaceSliceProducer = 70 | let 71 | producer = 72 | Random.map2 Tuple.pair TestData.randomString TestData.randomString 73 | |> Random.andThen (\( str, sub ) -> Random.pair (Random.constant ( str, sub )) (Random.int 0 <| String.length str)) 74 | |> Random.andThen (\( ( str, sub ), start ) -> Random.pair (Random.constant ( str, sub )) (Random.pair (Random.constant start) (Random.int start <| String.length str))) 75 | in 76 | Fuzz.custom producer Shrink.noShrink 77 | -------------------------------------------------------------------------------- /tests/TestData.elm: -------------------------------------------------------------------------------- 1 | module TestData exposing 2 | ( randomString 3 | , randomStrings 4 | , randomStringsWithCharGenerators 5 | , randomStringsWithChars 6 | ) 7 | 8 | import Fuzz exposing (Fuzzer) 9 | import Random 10 | import Shrink 11 | 12 | 13 | withChar : List Char -> Random.Generator Char 14 | withChar ch = 15 | withCharGenerators <| List.map Random.constant ch 16 | 17 | 18 | withCharGenerators : List (Random.Generator Char) -> Random.Generator Char 19 | withCharGenerators charGenerators = 20 | Random.andThen identity <| 21 | Random.uniform (Random.map Char.fromCode (Random.int 97 122)) <| 22 | Random.map Char.fromCode (Random.int 65 90) 23 | :: charGenerators 24 | 25 | 26 | randomString : Random.Generator String 27 | randomString = 28 | randomStringWithCharGenerators [ withChar [] ] 29 | 30 | 31 | randomStringWithCharGenerators : List (Random.Generator Char) -> Random.Generator String 32 | randomStringWithCharGenerators charGenerators = 33 | Random.int 1 10 34 | |> Random.andThen (\i -> Random.map String.fromList <| Random.list i (withCharGenerators charGenerators)) 35 | 36 | 37 | randomStrings : Fuzzer String 38 | randomStrings = 39 | randomStringsWithChars [] 40 | 41 | 42 | randomStringsWithChars : List Char -> Fuzzer String 43 | randomStringsWithChars chars = 44 | randomStringsWithCharGenerators [ withChar chars ] 45 | 46 | 47 | randomStringsWithCharGenerators : List (Random.Generator Char) -> Fuzzer String 48 | randomStringsWithCharGenerators charGenerators = 49 | Fuzz.custom (randomStringWithCharGenerators charGenerators) Shrink.string 50 | -------------------------------------------------------------------------------- /tests/Tests.elm: -------------------------------------------------------------------------------- 1 | module Tests exposing (breakTest, cleanTest, countOccurrencesTest, decapitalizeTest, ellipsisTest, insertAtProducer, insertAtTest, isBlankTest, nonBlankTest, pluralizeTest, softBreakTest, surroundTest, tail, toSentenceCaseTest, toTitleCaseTest, unquoteTest, wrapTest) 2 | 3 | import Expect 4 | import Fuzz exposing (..) 5 | import Json.Encode exposing (Value) 6 | import String exposing (fromChar, replace, toLower, toUpper, uncons) 7 | import String.Extra exposing (..) 8 | import Test exposing (..) 9 | import Tuple exposing (first, second) 10 | 11 | 12 | tail : String -> String 13 | tail = 14 | uncons >> Maybe.map second >> Maybe.withDefault "" 15 | 16 | 17 | toSentenceCaseTest : Test 18 | toSentenceCaseTest = 19 | describe "toSentenceCase" 20 | [ fuzz string "It converts the first char of the string to uppercase" <| 21 | \string -> 22 | let 23 | result = 24 | string 25 | |> toSentenceCase 26 | |> uncons 27 | |> Maybe.map (first >> fromChar) 28 | |> Maybe.withDefault "" 29 | 30 | expected = 31 | string 32 | |> uncons 33 | |> Maybe.map (first >> fromChar >> toUpper) 34 | |> Maybe.withDefault "" 35 | in 36 | Expect.equal expected result 37 | , fuzz string "The tail of the string remains untouched" <| 38 | \string -> 39 | let 40 | result = 41 | (toSentenceCase >> tail) string 42 | 43 | expected = 44 | tail string 45 | in 46 | Expect.equal expected result 47 | ] 48 | 49 | 50 | decapitalizeTest : Test 51 | decapitalizeTest = 52 | describe "decapitalize" 53 | [ fuzz string "It only converst the first char in the string to lowercase" <| 54 | \string -> 55 | let 56 | result = 57 | string 58 | |> decapitalize 59 | |> uncons 60 | |> Maybe.map (first >> fromChar) 61 | |> Maybe.withDefault "" 62 | 63 | expected = 64 | string 65 | |> uncons 66 | |> Maybe.map (first >> fromChar >> toLower) 67 | |> Maybe.withDefault "" 68 | in 69 | Expect.equal expected result 70 | , fuzz string "It does not change the tail of the string" <| 71 | \string -> 72 | let 73 | result = 74 | (decapitalize >> tail) string 75 | 76 | expected = 77 | tail string 78 | in 79 | Expect.equal expected result 80 | ] 81 | 82 | 83 | toTitleCaseTest : Test 84 | toTitleCaseTest = 85 | describe "toTitleCase" 86 | [ fuzz (list string) "It converts the first letter of each word to uppercase" <| 87 | \strings -> 88 | let 89 | result = 90 | strings 91 | |> String.join " " 92 | |> toTitleCase 93 | |> String.words 94 | 95 | expected = 96 | strings 97 | |> String.join " " 98 | |> String.words 99 | |> List.map toSentenceCase 100 | in 101 | Expect.equal expected result 102 | , fuzz (list string) "It does not change the length of the string" <| 103 | \strings -> 104 | let 105 | result = 106 | strings 107 | |> String.join " " 108 | |> toTitleCase 109 | |> String.length 110 | 111 | expected = 112 | strings 113 | |> String.join " " 114 | |> String.length 115 | in 116 | Expect.equal expected result 117 | ] 118 | 119 | 120 | breakTest : Test 121 | breakTest = 122 | describe "break" 123 | [ fuzz2 string (intRange 0 100) "The list should have as many elements as the ceil division of the length" <| 124 | \string width -> 125 | case ( string, width ) of 126 | ( "", _ ) -> 127 | break width string 128 | |> List.length 129 | |> Expect.equal 1 130 | 131 | ( _, 0 ) -> 132 | break width string 133 | |> List.length 134 | |> Expect.equal 1 135 | 136 | _ -> 137 | break width string 138 | |> List.length 139 | |> Expect.equal (ceiling <| (toFloat << String.length) string / toFloat width) 140 | , fuzz2 string (intRange 1 10) "Concatenating the result yields the original string" <| 141 | \string width -> 142 | break width string 143 | |> String.concat 144 | |> Expect.equal string 145 | , fuzz2 string (intRange 1 10) "No element in the list should have more than `width` chars" <| 146 | \string width -> 147 | break width string 148 | |> List.map String.length 149 | |> List.filter ((<) width) 150 | |> List.isEmpty 151 | |> Expect.true "The list has some long elements" 152 | ] 153 | 154 | 155 | softBreakTest : Test 156 | softBreakTest = 157 | describe "softBreak" 158 | [ fuzz2 string (intRange 1 10) "Concatenating the result yields the original string" <| 159 | \string width -> 160 | softBreak width (String.trim string) 161 | |> String.concat 162 | |> Expect.equal (String.trim string) 163 | , fuzz2 string (intRange 1 10) "The list should not have more elements than words" <| 164 | \string width -> 165 | softBreak width string 166 | |> List.length 167 | |> Expect.atMost (String.words string |> List.length) 168 | ] 169 | 170 | 171 | cleanTest : Test 172 | cleanTest = 173 | describe "clean" 174 | [ fuzz string "The String.split result is the same as String.words" <| 175 | \string -> 176 | let 177 | result = 178 | string 179 | |> clean 180 | |> String.split " " 181 | 182 | expected = 183 | String.words string 184 | in 185 | Expect.equal expected result 186 | , fuzz string "It trims the string on the left side" <| 187 | \string -> 188 | string 189 | |> clean 190 | |> String.startsWith " " 191 | |> Expect.false "Did not trim the start of the string" 192 | , fuzz string "It trims the string on the right side" <| 193 | \string -> 194 | string 195 | |> clean 196 | |> String.endsWith " " 197 | |> Expect.false "Did not trim the end of the string" 198 | ] 199 | 200 | 201 | insertAtTest : Test 202 | insertAtTest = 203 | describe "insertAt" 204 | [ fuzz insertAtProducer "Result contains the substitution string" <| 205 | \( sub, at, string ) -> 206 | string 207 | |> insertAt sub at 208 | |> String.contains sub 209 | |> Expect.true "Could not find substitution string in result" 210 | , fuzz insertAtProducer "Resulting string has length as the sum of both arguments" <| 211 | \( sub, at, string ) -> 212 | insertAt sub at string 213 | |> String.length 214 | |> Expect.equal (String.length sub + String.length string) 215 | , fuzz insertAtProducer "Start of the string remains the same" <| 216 | \( sub, at, string ) -> 217 | insertAt sub at string 218 | |> String.slice 0 at 219 | |> Expect.equal (String.slice 0 at string) 220 | , fuzz insertAtProducer "End of the string remains the same" <| 221 | \( sub, at, string ) -> 222 | insertAt sub at string 223 | |> String.slice (at + String.length sub) (String.length string + String.length sub) 224 | |> Expect.equal (String.slice at (String.length string) string) 225 | ] 226 | 227 | 228 | insertAtProducer : Fuzzer ( String, Int, String ) 229 | insertAtProducer = 230 | tuple3 ( intRange 0 10, intRange 1 10, string ) 231 | |> map (\( a, b, s ) -> ( "b" ++ s, b, String.repeat (a + b) "a" )) 232 | 233 | 234 | isBlankTest : Test 235 | isBlankTest = 236 | describe "isBlank" 237 | [ test "Returns true if the given string is blank" <| 238 | \_ -> 239 | isBlank "" 240 | |> Expect.true "Did not return true" 241 | , test "Returns false if the given string is not blank" <| 242 | \_ -> 243 | isBlank " Slartibartfast" 244 | |> Expect.false "Did not return false" 245 | ] 246 | 247 | 248 | nonBlankTest : Test 249 | nonBlankTest = 250 | describe "nonBlank" 251 | [ test "Returns Nothing if the given string is blank" <| 252 | \_ -> 253 | nonBlank "" 254 | |> Expect.equal Nothing 255 | , test "Returns just the string if the given string is not blank" <| 256 | \_ -> 257 | nonBlank " Slartibartfast" 258 | |> Expect.equal (Just " Slartibartfast") 259 | ] 260 | 261 | 262 | surroundTest : Test 263 | surroundTest = 264 | describe "surround" 265 | [ fuzz2 string string "It starts with the wrapping string" <| 266 | \string wrap -> 267 | string 268 | |> surround wrap 269 | |> String.startsWith wrap 270 | |> Expect.true "Did not start with the wrapping string" 271 | , fuzz2 string string "It ends with the wrapping string" <| 272 | \string wrap -> 273 | string 274 | |> surround wrap 275 | |> String.endsWith wrap 276 | |> Expect.true "Did not end with the wrapping string" 277 | , fuzz2 string string "It contains the original string" <| 278 | \string wrap -> 279 | string 280 | |> surround wrap 281 | |> String.contains string 282 | |> Expect.true "Did not contain the string" 283 | , fuzz2 string string "It does not have anything else inside" <| 284 | \string wrap -> 285 | let 286 | result = 287 | String.length (surround wrap string) 288 | 289 | expected = 290 | String.length string + (2 * String.length wrap) 291 | in 292 | Expect.equal expected result 293 | ] 294 | 295 | 296 | 297 | -- TODO: ensure this test only gets strings that contain the needle in the 298 | -- haystack? 299 | 300 | 301 | countOccurrencesTest : Test 302 | countOccurrencesTest = 303 | describe "countOccurrences" 304 | [ fuzz2 string string "Removing the occurences should yield the right length" <| 305 | \needle haystack -> 306 | let 307 | times = 308 | countOccurrences needle haystack 309 | 310 | result = 311 | String.length haystack - (times * String.length needle) 312 | 313 | expected = 314 | String.length (replace needle "" haystack) 315 | in 316 | Expect.equal expected result 317 | ] 318 | 319 | 320 | ellipsisTest : Test 321 | ellipsisTest = 322 | describe "ellipsis" 323 | [ fuzz2 (intRange 3 20) string "The resulting string length does not exceed the specified length" <| 324 | \howLong string -> 325 | ellipsis howLong string 326 | |> String.length 327 | |> (>=) howLong 328 | |> Expect.true "Resulting string exceeds specified length" 329 | , fuzz2 (intRange 3 20) string "The resulting string contains three dots at the end if necessary" <| 330 | \howLong string -> 331 | let 332 | result = 333 | ellipsis howLong string 334 | in 335 | result 336 | |> String.endsWith "..." 337 | |> (if String.length string > howLong then 338 | Expect.true "Should add ellipsis to this string" 339 | 340 | else 341 | Expect.false "Should not add ellipsis" 342 | ) 343 | , fuzz2 (intRange 3 20) string "It starts with the left of the original string" <| 344 | \howLong string -> 345 | let 346 | result = 347 | ellipsis howLong string 348 | 349 | resultLeft = 350 | String.dropRight 3 result 351 | in 352 | string 353 | |> String.startsWith resultLeft 354 | |> Expect.true "Should start with the original left" 355 | ] 356 | 357 | 358 | unquoteTest : Test 359 | unquoteTest = 360 | describe "unquote" 361 | [ test "Removes quotes from the start of the string" <| 362 | \_ -> 363 | unquote "\"Magrathea\"" 364 | |> Expect.equal "Magrathea" 365 | ] 366 | 367 | 368 | wrapTest : Test 369 | wrapTest = 370 | describe "wrap" 371 | [ fuzz2 (intRange 1 20) string "Wraps given string at the requested length" <| 372 | \howLong string -> 373 | wrap howLong string 374 | |> String.split "\n" 375 | |> List.map (\str -> String.length str <= howLong) 376 | |> List.all ((==) True) 377 | |> Expect.true "Given string was not wrapped at requested length" 378 | , test "Does not wrap string shorter than the requested length" <| 379 | \_ -> 380 | wrap 50 "Heart of Gold" 381 | |> String.contains "\n" 382 | |> Expect.false "Short string was wrapped" 383 | ] 384 | 385 | 386 | pluralizeTest : Test 387 | pluralizeTest = 388 | describe "pluralize" 389 | [ test "It uses the singular version when the count is one" <| 390 | \() -> 391 | pluralize "elf" "elves" 1 392 | |> Expect.equal "1 elf" 393 | , test "It uses the plural version for > 1 count" <| 394 | \() -> 395 | pluralize "elf" "elves" 4 396 | |> Expect.equal "4 elves" 397 | , test "It uses the plural version for 0 count" <| 398 | \() -> 399 | pluralize "elf" "elves" 0 400 | |> Expect.equal "0 elves" 401 | ] 402 | -------------------------------------------------------------------------------- /tests/UnderscoredTest.elm: -------------------------------------------------------------------------------- 1 | module UnderscoredTest exposing (underscoredTest) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import String exposing (replace, uncons) 7 | import String.Extra exposing (..) 8 | import Test exposing (..) 9 | import TestData 10 | 11 | 12 | underscoredTest : Test 13 | underscoredTest = 14 | describe "underscored" 15 | [ fuzz string "It is a lowercased string" <| 16 | \s -> 17 | underscored s 18 | |> String.toLower 19 | |> Expect.equal (underscored s |> String.toLower) 20 | , fuzz string "It replaces spaces and dashes with an underscore" <| 21 | \s -> 22 | let 23 | expected = 24 | String.toLower 25 | >> String.trim 26 | >> replace " " " " 27 | >> replace " " "-" 28 | >> replace "-" "_" 29 | >> replace "__" "_" 30 | >> replace "__" "_" 31 | in 32 | underscored (String.toLower s) 33 | |> Expect.equal (expected s) 34 | , fuzz TestData.randomStrings "It puts an underscore before each uppercase characters group unless it starts with uppercase" <| 35 | \s -> 36 | underscored s 37 | |> Expect.equal (replaceUppercase s |> String.toLower) 38 | ] 39 | 40 | 41 | replaceUppercase : String -> String 42 | replaceUppercase string = 43 | string 44 | |> String.toList 45 | |> List.indexedMap Tuple.pair 46 | |> List.foldr recordUpperCasePositions [] 47 | |> List.foldl reduceList [] 48 | |> List.foldl replacePositions string 49 | 50 | 51 | recordUpperCasePositions : ( Int, Char ) -> List ( Int, Char ) -> List ( Int, Char ) 52 | recordUpperCasePositions ( index, char ) acc = 53 | if Char.isUpper char then 54 | ( index, char ) :: acc 55 | 56 | else 57 | acc 58 | 59 | 60 | reduceList : ( Int, Char ) -> List ( Int, Int, Char ) -> List ( Int, Int, Char ) 61 | reduceList ( index, char ) acc = 62 | case acc of 63 | ( start, end, c ) :: rest -> 64 | if index == end + 1 then 65 | ( start, index, c ) :: rest 66 | 67 | else 68 | ( index, index, char ) :: acc 69 | 70 | [] -> 71 | ( index, index, char ) :: acc 72 | 73 | 74 | replacePositions : ( Int, Int, Char ) -> String -> String 75 | replacePositions ( start, _, c ) string = 76 | if start == 0 then 77 | string 78 | 79 | else 80 | replaceSlice ("_" ++ String.fromChar c) start (start + 1) string 81 | -------------------------------------------------------------------------------- /tests/UnicodeTests.elm: -------------------------------------------------------------------------------- 1 | module UnicodeTests exposing (unicodeTests) 2 | 3 | import Char 4 | import Expect 5 | import Fuzz exposing (..) 6 | import String 7 | import String.Extra exposing (..) 8 | import Test exposing (..) 9 | 10 | 11 | bmpCodePointFuzzer : Fuzzer Int 12 | bmpCodePointFuzzer = 13 | frequency 14 | [ ( 1, intRange 0 0xD7FF ) 15 | , ( 1, intRange 0xE000 0xFFFF ) 16 | ] 17 | 18 | 19 | unicodeStringFuzzer : Fuzzer String 20 | unicodeStringFuzzer = 21 | let 22 | singletonFuzzer = 23 | bmpCodePointFuzzer |> map (\codePoint -> [ codePoint ]) 24 | 25 | leadingSurrogateFuzzer = 26 | intRange 0xD800 0xDBFF 27 | 28 | trailingSurrogateFuzzer = 29 | intRange 0xDC00 0xDFFF 30 | 31 | surrogatePairFuzzer = 32 | tuple ( leadingSurrogateFuzzer, trailingSurrogateFuzzer ) 33 | |> map (\( leading, trailing ) -> [ leading, trailing ]) 34 | 35 | sublistFuzzer = 36 | frequency 37 | [ ( 1, singletonFuzzer ) 38 | , ( 1, surrogatePairFuzzer ) 39 | ] 40 | in 41 | list sublistFuzzer 42 | |> map List.concat 43 | |> map (List.map Char.fromCode) 44 | |> map String.fromList 45 | 46 | 47 | codePointFuzzer : Fuzzer Int 48 | codePointFuzzer = 49 | let 50 | astralCodePointFuzzer = 51 | intRange 0x00010000 0x0010FFFF 52 | in 53 | frequency 54 | [ ( 1, bmpCodePointFuzzer ) 55 | , ( 1, astralCodePointFuzzer ) 56 | ] 57 | 58 | 59 | expectedStringLength : List Int -> Int 60 | expectedStringLength codePoints = 61 | let 62 | numCodeUnits codePoint = 63 | if codePoint <= 0xFFFF then 64 | 1 65 | 66 | else 67 | 2 68 | in 69 | codePoints |> List.map numCodeUnits |> List.sum 70 | 71 | 72 | hardCodedTestCases : List ( String, List Int ) 73 | hardCodedTestCases = 74 | [ ( "", [] ) 75 | , ( "©§π", [ 169, 167, 960 ] ) 76 | , ( "💩!", [ 128169, 33 ] ) 77 | , ( "abc", [ 97, 98, 99 ] ) 78 | ] 79 | 80 | 81 | unicodeTests : Test 82 | unicodeTests = 83 | describe "unicode" 84 | [ fuzz unicodeStringFuzzer "fromCodePoints is inverse of toCodePoints" <| 85 | \string -> 86 | fromCodePoints (toCodePoints string) 87 | |> Expect.equal string 88 | , fuzz (list codePointFuzzer) "toCodePoints is inverse of fromCodePoints" <| 89 | \codePoints -> 90 | toCodePoints (fromCodePoints codePoints) 91 | |> Expect.equal codePoints 92 | , fuzz (list codePointFuzzer) "string length is greater than or equal to number of code points" <| 93 | \codePoints -> 94 | String.length (fromCodePoints codePoints) 95 | |> Expect.atLeast (List.length codePoints) 96 | , fuzz unicodeStringFuzzer "number of code points is less than or equal to string length" <| 97 | \string -> 98 | List.length (toCodePoints string) 99 | |> Expect.atMost (String.length string) 100 | , fuzz (list codePointFuzzer) "encoded string length is as expected" <| 101 | \codePoints -> 102 | String.length (fromCodePoints codePoints) 103 | |> Expect.equal (expectedStringLength codePoints) 104 | , describe "toCodePoints works as expected on hard-coded test cases" 105 | (hardCodedTestCases 106 | |> List.indexedMap 107 | (\index ( string, codePoints ) -> 108 | test ("toCodePoints works properly - test case " ++ Debug.toString index) 109 | (\() -> toCodePoints string |> Expect.equal codePoints) 110 | ) 111 | ) 112 | , describe "fromCodePoints works as expected on hard-coded test cases" 113 | (hardCodedTestCases 114 | |> List.indexedMap 115 | (\index ( string, codePoints ) -> 116 | test ("fromCodePoints works properly - test case " ++ Debug.toString index) 117 | (\() -> fromCodePoints codePoints |> Expect.equal string) 118 | ) 119 | ) 120 | ] 121 | -------------------------------------------------------------------------------- /tests/UnindentTest.elm: -------------------------------------------------------------------------------- 1 | module UnindentTest exposing (unindentTest) 2 | 3 | import Expect 4 | import Fuzz exposing (..) 5 | import String exposing (uncons) 6 | import String.Extra exposing (..) 7 | import Test exposing (..) 8 | import Tuple exposing (first) 9 | 10 | 11 | unindentTest : Test 12 | unindentTest = 13 | describe "unindent" 14 | [ fuzz multilineProducerString "It produces the same trimmed string" <| 15 | \s -> 16 | let 17 | expected = 18 | String.lines >> List.map String.trimLeft 19 | in 20 | unindent s 21 | |> String.lines 22 | |> List.map String.trimLeft 23 | |> Expect.equal (expected s) 24 | , fuzz multilineProducerString "It produces at least one line with no leading whitespace" <| 25 | \s -> 26 | unindent s 27 | |> String.lines 28 | |> List.map (not << String.startsWith " ") 29 | |> List.any ((==) True) 30 | |> Expect.true "No lines with leading whitespace detected" 31 | , fuzz multilineProducer "All lines' length have been reduced by exactly the minimum indentation" <| 32 | \( s, spaces ) -> 33 | let 34 | expected = 35 | String.lines s 36 | |> List.map String.length 37 | |> List.map (\i -> i - spaces) 38 | in 39 | unindent s 40 | |> String.lines 41 | |> List.map String.length 42 | |> Expect.equal expected 43 | ] 44 | 45 | 46 | multilineProducerString : Fuzzer String 47 | multilineProducerString = 48 | map (convertToMultiline >> first) 49 | (tuple3 ( intRange 0 10, intRange 0 10, intRange 0 10 )) 50 | 51 | 52 | multilineProducer : Fuzzer ( String, Int ) 53 | multilineProducer = 54 | map convertToMultiline 55 | (tuple3 ( intRange 0 10, intRange 0 10, intRange 0 10 )) 56 | 57 | 58 | convertToMultiline : ( Int, Int, Int ) -> ( String, Int ) 59 | convertToMultiline ( a, b, c ) = 60 | ( [ String.repeat a " " ++ "aaaa aaa " 61 | , String.repeat b " " ++ "aaaa aaa" 62 | , String.repeat c " " ++ "ccc " 63 | ] 64 | |> String.join "\n" 65 | , min (min a b) c 66 | ) 67 | -------------------------------------------------------------------------------- /tests/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "summary": "String Addons library tests", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | ".", 8 | "../src" 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "elm-community/elm-test": "4.0.0 <= v < 5.0.0", 13 | "elm-community/shrink": "2.0.0 <= v < 3.0.0", 14 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 15 | "mgold/elm-random-pcg": "4.0.2 <= v < 5.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | --------------------------------------------------------------------------------