| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | // Copyright 2014 Simon Lydell |
| 2 | // X11 (“MIT”) Licensed. (See LICENSE.) |
| 3 | |
| 4 | var expect = require("expect.js") |
| 5 | |
| 6 | var sourceMappingURL = require("../") |
| 7 | |
| 8 | var comments = { |
| 9 | |
| 10 | universal: [ |
| 11 | "/*# sourceMappingURL=foo.js.map */" |
| 12 | ], |
| 13 | |
| 14 | js: [ |
| 15 | "//# sourceMappingURL=foo.js.map" |
| 16 | ], |
| 17 | |
| 18 | block: [ |
| 19 | "/*", |
| 20 | "# sourceMappingURL=foo.js.map", |
| 21 | "*/" |
| 22 | ], |
| 23 | |
| 24 | mix: [ |
| 25 | "/*", |
| 26 | "//# sourceMappingURL=foo.js.map", |
| 27 | "*/" |
| 28 | ] |
| 29 | |
| 30 | } |
| 31 | |
| 32 | var nonTrailingComments = { |
| 33 | |
| 34 | jsLeading: { |
| 35 | contents: [ |
| 36 | "//# sourceMappingURL=foo.js.map", |
| 37 | "(function(){})" |
| 38 | ], |
| 39 | solution: [ |
| 40 | "(function(){})" |
| 41 | ] |
| 42 | }, |
| 43 | |
| 44 | mixEmbedded: { |
| 45 | contents: [ |
| 46 | "/*! Library Name v1.0.0", |
| 47 | "//# sourceMappingURL=foo.js.map", |
| 48 | "*/", |
| 49 | "(function(){})" |
| 50 | ], |
| 51 | solution: [ |
| 52 | "/*! Library Name v1.0.0", |
| 53 | "*/", |
| 54 | "(function(){})" |
| 55 | ] |
| 56 | } |
| 57 | |
| 58 | } |
| 59 | |
| 60 | function forEachComment(fn) { |
| 61 | forOf(comments, function(name, comment) { |
| 62 | var description = "the '" + name + "' syntax with " |
| 63 | fn(comment.join("\n"), description + "regular newlines") |
| 64 | fn(comment.join("\r\n"), description + "Windows newlines") |
| 65 | }) |
| 66 | } |
| 67 | |
| 68 | function forEachNonTrailingComment(fn) { |
| 69 | forOf(nonTrailingComments, function(name, comment) { |
| 70 | |
| 71 | var description = "the '" + name + "' syntax with " |
| 72 | |
| 73 | fn({ |
| 74 | contents: comment.contents.join("\n"), |
| 75 | solution: comment.solution.join("\n") |
| 76 | }, description + "regular newlines") |
| 77 | |
| 78 | fn({ |
| 79 | contents: comment.contents.join("\r\n"), |
| 80 | solution: comment.solution.join("\r\n") |
| 81 | }, description + "Windows newlines") |
| 82 | }) |
| 83 | } |
| 84 | |
| 85 | function forOf(obj, fn) { |
| 86 | for (var key in obj) { |
| 87 | if (Object.prototype.hasOwnProperty.call(obj, key)) { |
| 88 | fn(key, obj[key]) |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | |
| 94 | describe("sourceMappingURL", function() { |
| 95 | |
| 96 | describe(".getFrom", function() { |
| 97 | |
| 98 | forEachComment(function(comment, description) { |
| 99 | |
| 100 | it("gets the url from " + description, function() { |
| 101 | expect(sourceMappingURL.getFrom("code\n" + comment)) |
| 102 | .to.equal("foo.js.map") |
| 103 | |
| 104 | expect(sourceMappingURL.getFrom("code" + comment)) |
| 105 | .to.equal("foo.js.map") |
| 106 | |
| 107 | expect(sourceMappingURL.getFrom(comment)) |
| 108 | .to.equal("foo.js.map") |
| 109 | }) |
| 110 | |
| 111 | }) |
| 112 | |
| 113 | forEachNonTrailingComment(function(comment, description) { |
| 114 | |
| 115 | it("gets the url from " + description, function() { |
| 116 | expect(sourceMappingURL.getFrom("code\n" + comment.contents)) |
| 117 | .to.equal("foo.js.map") |
| 118 | |
| 119 | expect(sourceMappingURL.getFrom("code" + comment.contents)) |
| 120 | .to.equal("foo.js.map") |
| 121 | |
| 122 | expect(sourceMappingURL.getFrom(comment.contents)) |
| 123 | .to.equal("foo.js.map") |
| 124 | }) |
| 125 | |
| 126 | }) |
| 127 | |
| 128 | |
| 129 | it("returns null if no comment", function() { |
| 130 | expect(sourceMappingURL.getFrom("code")) |
| 131 | .to.equal(null) |
| 132 | }) |
| 133 | |
| 134 | |
| 135 | it("can return an empty string as url", function() { |
| 136 | expect(sourceMappingURL.getFrom("/*# sourceMappingURL= */")) |
| 137 | .to.equal("") |
| 138 | }) |
| 139 | |
| 140 | |
| 141 | it("is detachable", function() { |
| 142 | var get = sourceMappingURL.getFrom |
| 143 | expect(get("/*# sourceMappingURL=foo */")) |
| 144 | .to.equal("foo") |
| 145 | }) |
| 146 | |
| 147 | }) |
| 148 | |
| 149 | |
| 150 | describe(".existsIn", function() { |
| 151 | |
| 152 | forEachComment(function(comment, description) { |
| 153 | |
| 154 | it("returns true for " + description, function() { |
| 155 | expect(sourceMappingURL.existsIn("code\n" + comment)) |
| 156 | .to.equal(true) |
| 157 | |
| 158 | expect(sourceMappingURL.existsIn("code" + comment)) |
| 159 | .to.equal(true) |
| 160 | |
| 161 | expect(sourceMappingURL.existsIn(comment)) |
| 162 | .to.equal(true) |
| 163 | }) |
| 164 | |
| 165 | }) |
| 166 | |
| 167 | forEachNonTrailingComment(function(comment, description) { |
| 168 | |
| 169 | it("returns true for " + description, function() { |
| 170 | expect(sourceMappingURL.existsIn("code\n" + comment.contents)) |
| 171 | .to.equal(true) |
| 172 | |
| 173 | expect(sourceMappingURL.existsIn("code" + comment.contents)) |
| 174 | .to.equal(true) |
| 175 | |
| 176 | expect(sourceMappingURL.existsIn(comment.contents)) |
| 177 | .to.equal(true) |
| 178 | }) |
| 179 | |
| 180 | }) |
| 181 | |
| 182 | |
| 183 | it("returns false if no comment", function() { |
| 184 | expect(sourceMappingURL.existsIn("code")) |
| 185 | .to.equal(false) |
| 186 | }) |
| 187 | |
| 188 | |
| 189 | it("is detachable", function() { |
| 190 | var has = sourceMappingURL.existsIn |
| 191 | expect(has("/*# sourceMappingURL=foo */")) |
| 192 | .to.equal(true) |
| 193 | }) |
| 194 | |
| 195 | }) |
| 196 | |
| 197 | |
| 198 | describe(".removeFrom", function() { |
| 199 | |
| 200 | forEachComment(function(comment, description) { |
| 201 | |
| 202 | it("removes the comment for " + description, function() { |
| 203 | expect(sourceMappingURL.removeFrom("code\n" + comment)) |
| 204 | .to.equal("code\n") |
| 205 | |
| 206 | expect(sourceMappingURL.removeFrom("code" + comment)) |
| 207 | .to.equal("code") |
| 208 | |
| 209 | expect(sourceMappingURL.removeFrom(comment)) |
| 210 | .to.equal("") |
| 211 | }) |
| 212 | |
| 213 | }) |
| 214 | |
| 215 | forEachNonTrailingComment(function(comment, description) { |
| 216 | |
| 217 | it("removes the comment for " + description, function() { |
| 218 | expect(sourceMappingURL.removeFrom("code\n" + comment.contents)) |
| 219 | .to.equal("code\n" + comment.solution) |
| 220 | |
| 221 | expect(sourceMappingURL.removeFrom("code" + comment.contents)) |
| 222 | .to.equal("code" + comment.solution) |
| 223 | |
| 224 | expect(sourceMappingURL.removeFrom(comment.contents)) |
| 225 | .to.equal(comment.solution) |
| 226 | }) |
| 227 | |
| 228 | }) |
| 229 | |
| 230 | |
| 231 | it("does nothing if no comment", function() { |
| 232 | expect(sourceMappingURL.removeFrom("code\n")) |
| 233 | .to.equal("code\n") |
| 234 | }) |
| 235 | |
| 236 | |
| 237 | it("is detachable", function() { |
| 238 | var remove = sourceMappingURL.removeFrom |
| 239 | expect(remove("/*# sourceMappingURL=foo */")) |
| 240 | .to.equal("") |
| 241 | }) |
| 242 | |
| 243 | }) |
| 244 | |
| 245 | |
| 246 | describe(".insertBefore", function() { |
| 247 | |
| 248 | forEachComment(function(comment, description) { |
| 249 | |
| 250 | it("inserts a string before the comment for " + description, function() { |
| 251 | expect(sourceMappingURL.insertBefore("code\n" + comment, "more code\n")) |
| 252 | .to.equal("code\nmore code\n" + comment) |
| 253 | |
| 254 | expect(sourceMappingURL.insertBefore("code" + comment, "\nmore code")) |
| 255 | .to.equal("code\nmore code" + comment) |
| 256 | |
| 257 | expect(sourceMappingURL.insertBefore(comment, "some code")) |
| 258 | .to.equal("some code" + comment) |
| 259 | }) |
| 260 | |
| 261 | }) |
| 262 | |
| 263 | |
| 264 | it("inserts a string before an embedded comment", function() { |
| 265 | expect(sourceMappingURL.insertBefore("/*! Library Name v1.0.0\n" + |
| 266 | "//# sourceMappingURL=foo.js.map\n*/\n(function(){})", "code\n")) |
| 267 | .to.equal("/*! Library Name v1.0.0\ncode\n" + |
| 268 | "//# sourceMappingURL=foo.js.map\n*/\n(function(){})") |
| 269 | }) |
| 270 | |
| 271 | |
| 272 | it("inserts a string before a leading comment", function() { |
| 273 | expect(sourceMappingURL.insertBefore("//# sourceMappingURL=foo.js.map\n" + |
| 274 | "(function(){})", "code\n")) |
| 275 | .to.equal("code\n//# sourceMappingURL=foo.js.map\n" + |
| 276 | "(function(){})") |
| 277 | }) |
| 278 | |
| 279 | |
| 280 | it("appends if no comment", function() { |
| 281 | expect(sourceMappingURL.insertBefore("code", "\nmore code")) |
| 282 | .to.equal("code\nmore code") |
| 283 | }) |
| 284 | |
| 285 | |
| 286 | it("is detachable", function() { |
| 287 | var insertBefore = sourceMappingURL.insertBefore |
| 288 | expect(insertBefore("/*# sourceMappingURL=foo */", "bar")) |
| 289 | .to.equal("bar/*# sourceMappingURL=foo */") |
| 290 | }) |
| 291 | |
| 292 | }) |
| 293 | |
| 294 | |
| 295 | describe(".regex", function() { |
| 296 | |
| 297 | it("includes ._innerRegex", function() { |
| 298 | expect(sourceMappingURL.regex.source) |
| 299 | .to.contain(sourceMappingURL._innerRegex.source) |
| 300 | }) |
| 301 | |
| 302 | |
| 303 | var match = function(code) { |
| 304 | expect(code) |
| 305 | .to.match(sourceMappingURL.regex) |
| 306 | } |
| 307 | |
| 308 | var noMatch = function(code) { |
| 309 | expect(code) |
| 310 | .not.to.match(sourceMappingURL.regex) |
| 311 | } |
| 312 | |
| 313 | |
| 314 | forEachComment(function(comment, description) { |
| 315 | |
| 316 | it("matches " + description, function() { |
| 317 | match("code\n" + comment) |
| 318 | match("code" + comment) |
| 319 | match(comment) |
| 320 | }) |
| 321 | |
| 322 | |
| 323 | it("matches " + description + ", with trailing whitespace", function() { |
| 324 | match(comment + " ") |
| 325 | match(comment + "\n") |
| 326 | match(comment + "\n\n\t\n \t ") |
| 327 | }) |
| 328 | |
| 329 | }) |
| 330 | |
| 331 | |
| 332 | it("does not match some cases that are easy to mess up", function() { |
| 333 | noMatch( |
| 334 | "/* # sourceMappingURL=foo */" |
| 335 | ) |
| 336 | |
| 337 | noMatch( |
| 338 | "// # sourceMappingURL=foo" |
| 339 | ) |
| 340 | }) |
| 341 | |
| 342 | |
| 343 | it("is liberal regarding inner whitespace", function() { |
| 344 | match( |
| 345 | "/*# sourceMappingURL=foo*/" |
| 346 | ) |
| 347 | |
| 348 | match( |
| 349 | "/*# sourceMappingURL=foo */" |
| 350 | ) |
| 351 | |
| 352 | match( |
| 353 | "/*# sourceMappingURL=foo \t\n" + |
| 354 | "*/" |
| 355 | ) |
| 356 | |
| 357 | match( |
| 358 | "/* \n" + |
| 359 | "# sourceMappingURL=foo\n" + |
| 360 | "*/" |
| 361 | ) |
| 362 | |
| 363 | match( |
| 364 | "/*\n" + |
| 365 | "# sourceMappingURL=foo\n" + |
| 366 | " */" |
| 367 | ) |
| 368 | |
| 369 | match( |
| 370 | "/*\n" + |
| 371 | "# sourceMappingURL=foo\n" + |
| 372 | "\n" + |
| 373 | "\t\n" + |
| 374 | "*/" |
| 375 | ) |
| 376 | }) |
| 377 | |
| 378 | }) |
| 379 | |
| 380 | |
| 381 | describe("._innerRegex", function() { |
| 382 | |
| 383 | it("matches the contents of sourceMappingURL comments", function() { |
| 384 | expect("# sourceMappingURL=http://www.example.com/foo/bar.js.map") |
| 385 | .to.match(sourceMappingURL._innerRegex) |
| 386 | }) |
| 387 | |
| 388 | |
| 389 | it("captures the url in the first capture group", function() { |
| 390 | expect(sourceMappingURL._innerRegex.exec("# sourceMappingURL=foo")[1]) |
| 391 | .to.equal("foo") |
| 392 | }) |
| 393 | |
| 394 | |
| 395 | it("supports the legacy syntax", function() { |
| 396 | expect("@ sourceMappingURL=http://www.example.com/foo/bar.js.map") |
| 397 | .to.match(sourceMappingURL._innerRegex) |
| 398 | }) |
| 399 | |
| 400 | }) |
| 401 | |
| 402 | }) |