source-map-url.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Copyright 2014 Simon Lydell
  2. // X11 (“MIT”) Licensed. (See LICENSE.)
  3. var expect = require("expect.js")
  4. var sourceMappingURL = require("../")
  5. var comments = {
  6. universal: [
  7. "/*# sourceMappingURL=foo.js.map */"
  8. ],
  9. js: [
  10. "//# sourceMappingURL=foo.js.map"
  11. ],
  12. block: [
  13. "/*",
  14. "# sourceMappingURL=foo.js.map",
  15. "*/"
  16. ],
  17. mix: [
  18. "/*",
  19. "//# sourceMappingURL=foo.js.map",
  20. "*/"
  21. ]
  22. }
  23. function forEachComment(fn) {
  24. forOf(comments, function(name, comment) {
  25. var description = "the '" + name + "' syntax with "
  26. fn(comment.join("\n"), description + "regular newlines")
  27. fn(comment.join("\r\n"), description + "Windows newlines")
  28. })
  29. }
  30. function forOf(obj, fn) {
  31. for (var key in obj) {
  32. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  33. fn(key, obj[key])
  34. }
  35. }
  36. }
  37. describe("sourceMappingURL", function() {
  38. describe(".getFrom", function() {
  39. forEachComment(function(comment, description) {
  40. it("gets the url from " + description, function() {
  41. expect(sourceMappingURL.getFrom("code\n" + comment))
  42. .to.equal("foo.js.map")
  43. expect(sourceMappingURL.getFrom("code" + comment))
  44. .to.equal("foo.js.map")
  45. expect(sourceMappingURL.getFrom(comment))
  46. .to.equal("foo.js.map")
  47. })
  48. })
  49. it("returns null if no comment", function() {
  50. expect(sourceMappingURL.getFrom("code"))
  51. .to.equal(null)
  52. })
  53. it("can return an empty string as url", function() {
  54. expect(sourceMappingURL.getFrom("/*# sourceMappingURL= */"))
  55. .to.equal("")
  56. })
  57. it("is detachable", function() {
  58. var get = sourceMappingURL.getFrom
  59. expect(get("/*# sourceMappingURL=foo */"))
  60. .to.equal("foo")
  61. })
  62. })
  63. describe(".existsIn", function() {
  64. forEachComment(function(comment, description) {
  65. it("returns true for " + description, function() {
  66. expect(sourceMappingURL.existsIn("code\n" + comment))
  67. .to.equal(true)
  68. expect(sourceMappingURL.existsIn("code" + comment))
  69. .to.equal(true)
  70. expect(sourceMappingURL.existsIn(comment))
  71. .to.equal(true)
  72. })
  73. })
  74. it("returns false if no comment", function() {
  75. expect(sourceMappingURL.existsIn("code"))
  76. .to.equal(false)
  77. })
  78. it("is detachable", function() {
  79. var has = sourceMappingURL.existsIn
  80. expect(has("/*# sourceMappingURL=foo */"))
  81. .to.equal(true)
  82. })
  83. })
  84. describe(".removeFrom", function() {
  85. forEachComment(function(comment, description) {
  86. it("removes the comment for " + description, function() {
  87. expect(sourceMappingURL.removeFrom("code\n" + comment))
  88. .to.equal("code\n")
  89. expect(sourceMappingURL.removeFrom("code" + comment))
  90. .to.equal("code")
  91. expect(sourceMappingURL.removeFrom(comment))
  92. .to.equal("")
  93. })
  94. })
  95. it("does nothing if no comment", function() {
  96. expect(sourceMappingURL.removeFrom("code\n"))
  97. .to.equal("code\n")
  98. })
  99. it("is detachable", function() {
  100. var remove = sourceMappingURL.removeFrom
  101. expect(remove("/*# sourceMappingURL=foo */"))
  102. .to.equal("")
  103. })
  104. })
  105. describe(".insertBefore", function() {
  106. forEachComment(function(comment, description) {
  107. it("inserts a string before the comment for " + description, function() {
  108. expect(sourceMappingURL.insertBefore("code\n" + comment, "more code\n"))
  109. .to.equal("code\nmore code\n" + comment)
  110. expect(sourceMappingURL.insertBefore("code" + comment, "\nmore code"))
  111. .to.equal("code\nmore code" + comment)
  112. expect(sourceMappingURL.insertBefore(comment, "some code"))
  113. .to.equal("some code" + comment)
  114. })
  115. })
  116. it("appends if no comment", function() {
  117. expect(sourceMappingURL.insertBefore("code", "\nmore code"))
  118. .to.equal("code\nmore code")
  119. })
  120. it("is detachable", function() {
  121. var insertBefore = sourceMappingURL.insertBefore
  122. expect(insertBefore("/*# sourceMappingURL=foo */", "bar"))
  123. .to.equal("bar/*# sourceMappingURL=foo */")
  124. })
  125. })
  126. describe(".regex", function() {
  127. it("includes ._innerRegex", function() {
  128. expect(sourceMappingURL.regex.source)
  129. .to.contain(sourceMappingURL._innerRegex.source)
  130. })
  131. var match = function(code) {
  132. expect(code)
  133. .to.match(sourceMappingURL.regex)
  134. }
  135. var noMatch = function(code) {
  136. expect(code)
  137. .not.to.match(sourceMappingURL.regex)
  138. }
  139. forEachComment(function(comment, description) {
  140. it("matches " + description, function() {
  141. match("code\n" + comment)
  142. match("code" + comment)
  143. match(comment)
  144. })
  145. it("matches " + description + ", with trailing whitespace", function() {
  146. match(comment + " ")
  147. match(comment + "\n")
  148. match(comment + "\n\n\t\n \t ")
  149. })
  150. it("only matches " + description + " at the end of files", function() {
  151. noMatch("code\n" + comment + " code")
  152. noMatch("code" + comment + " code")
  153. noMatch("code\n" + comment + "\ncode")
  154. noMatch("code" + comment + "\ncode")
  155. noMatch("code\n" + comment + "\n// Generated by foobar")
  156. noMatch("code" + comment + "\n// Generated by foobar")
  157. noMatch("alert\n('\\" + comment + "')")
  158. noMatch("alert('\\" + comment + "')")
  159. noMatch('alert\n("\\' + comment + '")')
  160. noMatch('alert("\\' + comment + '")')
  161. })
  162. })
  163. it("does not match some cases that are easy to mess up", function() {
  164. noMatch(
  165. "/* # sourceMappingURL=foo */"
  166. )
  167. noMatch(
  168. "/*\n" +
  169. " //# sourceMappingURL=foo\n" +
  170. "*/"
  171. )
  172. noMatch(
  173. "/*//# sourceMappingURL=foo\n" +
  174. "*/"
  175. )
  176. noMatch(
  177. "// # sourceMappingURL=foo"
  178. )
  179. })
  180. it("is liberal regarding inner whitespace", function() {
  181. match(
  182. "/*# sourceMappingURL=foo*/"
  183. )
  184. match(
  185. "/*# sourceMappingURL=foo */"
  186. )
  187. match(
  188. "/*# sourceMappingURL=foo \t\n" +
  189. "*/"
  190. )
  191. match(
  192. "/* \n" +
  193. "# sourceMappingURL=foo\n" +
  194. "*/"
  195. )
  196. match(
  197. "/*\n" +
  198. "# sourceMappingURL=foo\n" +
  199. " */"
  200. )
  201. match(
  202. "/*\n" +
  203. "# sourceMappingURL=foo\n" +
  204. "\n" +
  205. "\t\n" +
  206. "*/"
  207. )
  208. })
  209. })
  210. describe("._innerRegex", function() {
  211. it("matches the contents of sourceMappingURL comments", function() {
  212. expect("# sourceMappingURL=http://www.example.com/foo/bar.js.map")
  213. .to.match(sourceMappingURL._innerRegex)
  214. })
  215. it("captures the url in the first capture group", function() {
  216. expect(sourceMappingURL._innerRegex.exec("# sourceMappingURL=foo")[1])
  217. .to.equal("foo")
  218. })
  219. it("supports the legacy syntax", function() {
  220. expect("@ sourceMappingURL=http://www.example.com/foo/bar.js.map")
  221. .to.match(sourceMappingURL._innerRegex)
  222. })
  223. })
  224. })