@angular-wave/angular.ts 0.9.4 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (645) hide show
  1. package/@types/index.d.ts +1 -84
  2. package/{src/index.ts → @types/namespace.d.ts} +4 -24
  3. package/@types/router/template-factory.d.ts +2 -2
  4. package/dist/angular-ts.esm.js +3 -3
  5. package/dist/angular-ts.umd.js +3 -3
  6. package/dist/angular-ts.umd.min.js +1 -1
  7. package/package.json +8 -1
  8. package/.github/workflows/ci.yml +0 -104
  9. package/.github/workflows/gh-pages.yml +0 -75
  10. package/.husky/pre-commit +0 -5
  11. package/.prettierignore +0 -9
  12. package/CHANGELOG.md +0 -17667
  13. package/CODE_OF_CONDUCT.md +0 -3
  14. package/CONTRIBUTING.md +0 -247
  15. package/DEVELOPERS.md +0 -499
  16. package/Makefile +0 -60
  17. package/RELEASE.md +0 -86
  18. package/TRIAGING.md +0 -127
  19. package/docs/.cspell.yml +0 -8
  20. package/docs/.github/dependabot.yml +0 -14
  21. package/docs/.nvmrc +0 -1
  22. package/docs/CONTRIBUTING.md +0 -28
  23. package/docs/Dockerfile +0 -4
  24. package/docs/LICENSE +0 -201
  25. package/docs/README.md +0 -217
  26. package/docs/assets/icons/logo.svg +0 -1
  27. package/docs/assets/scss/_variables_project.scss +0 -12
  28. package/docs/assets/scss/_variables_project_after_bs.scss +0 -8
  29. package/docs/assets/scss/index.scss +0 -48
  30. package/docs/config.yaml +0 -15
  31. package/docs/content/_index.md +0 -28
  32. package/docs/content/docs/_index.md +0 -61
  33. package/docs/content/docs/directive/_index.md +0 -4
  34. package/docs/content/docs/directive/app.md +0 -11
  35. package/docs/content/docs/directive/aria.md +0 -0
  36. package/docs/content/docs/directive/bind.md +0 -72
  37. package/docs/content/docs/directive/blur.md +0 -38
  38. package/docs/content/docs/directive/channel.md +0 -37
  39. package/docs/content/docs/directive/class-even.md +0 -47
  40. package/docs/content/docs/directive/class-odd.md +0 -48
  41. package/docs/content/docs/directive/class.md +0 -64
  42. package/docs/content/docs/directive/click.md +0 -41
  43. package/docs/content/docs/directive/cloak.md +0 -74
  44. package/docs/content/docs/directive/copy.md +0 -38
  45. package/docs/content/docs/directive/cut.md +0 -40
  46. package/docs/content/docs/directive/dblclick.md +0 -41
  47. package/docs/content/docs/directive/focus.md +0 -38
  48. package/docs/content/docs/directive/get.md +0 -203
  49. package/docs/content/docs/directive/include.md +0 -7
  50. package/docs/content/docs/directive/keydown.md +0 -38
  51. package/docs/content/docs/directive/keyup.md +0 -38
  52. package/docs/content/docs/directive/load.md +0 -43
  53. package/docs/content/docs/directive/mousedown.md +0 -38
  54. package/docs/content/docs/directive/mouseenter.md +0 -38
  55. package/docs/content/docs/directive/mouseleave.md +0 -38
  56. package/docs/content/docs/directive/mousemove.md +0 -38
  57. package/docs/content/docs/directive/mouseout.md +0 -38
  58. package/docs/content/docs/directive/mouseover.md +0 -38
  59. package/docs/content/docs/directive/mouseup.md +0 -38
  60. package/docs/content/docs/directive/non-bindable.md +0 -28
  61. package/docs/content/docs/filter/_index.md +0 -4
  62. package/docs/content/docs/filter/filter.md +0 -78
  63. package/docs/content/docs/filter/json.md +0 -19
  64. package/docs/content/docs/filter/limit-to.md +0 -30
  65. package/docs/content/docs/filter/order-by.md +0 -123
  66. package/docs/content/docs/provider/_index.md +0 -4
  67. package/docs/content/docs/provider/eventBusProvider.md +0 -35
  68. package/docs/content/docs/provider/locationProvider.md +0 -26
  69. package/docs/content/docs/provider/logProvider.md +0 -59
  70. package/docs/content/docs/provider/sceProvider.md +0 -194
  71. package/docs/content/docs/provider/templateCacheProvider.md +0 -100
  72. package/docs/content/docs/provider/templateRequestProvider.md +0 -5
  73. package/docs/content/docs/service/_index.md +0 -4
  74. package/docs/content/docs/service/compile.md +0 -5
  75. package/docs/content/docs/service/controller.md +0 -5
  76. package/docs/content/docs/service/eventBus.md +0 -56
  77. package/docs/content/docs/service/http.md +0 -161
  78. package/docs/content/docs/service/interpolation.md +0 -5
  79. package/docs/content/docs/service/location.md +0 -57
  80. package/docs/content/docs/service/log.md +0 -113
  81. package/docs/content/docs/service/parse.md +0 -5
  82. package/docs/content/docs/service/rootElement.md +0 -5
  83. package/docs/content/docs/service/rootScope.md +0 -5
  84. package/docs/content/docs/service/sce.md +0 -194
  85. package/docs/content/docs/service/templateCache.md +0 -64
  86. package/docs/content/docs/service/templateRequest.md +0 -5
  87. package/docs/content/docs/service/url.md +0 -5
  88. package/docs/content/docs/values/_index.md +0 -4
  89. package/docs/content/docs/values/document.md +0 -29
  90. package/docs/content/docs/values/window.md +0 -29
  91. package/docs/docker-compose.yaml +0 -12
  92. package/docs/docsy.work +0 -5
  93. package/docs/docsy.work.sum +0 -0
  94. package/docs/go.mod +0 -5
  95. package/docs/go.sum +0 -6
  96. package/docs/hugo-disabled.toml +0 -220
  97. package/docs/hugo.yaml +0 -200
  98. package/docs/layouts/404.html +0 -13
  99. package/docs/layouts/_markup/render-heading.html +0 -1
  100. package/docs/layouts/partials/hooks/head-end.html +0 -3
  101. package/docs/layouts/shortcodes/showcss.html +0 -2
  102. package/docs/layouts/shortcodes/showhtml.html +0 -2
  103. package/docs/layouts/shortcodes/showjs.html +0 -2
  104. package/docs/layouts/shortcodes/showraw.html +0 -1
  105. package/docs/layouts/shortcodes/version.html +0 -1
  106. package/docs/package-lock.json +0 -2293
  107. package/docs/package.json +0 -53
  108. package/docs/static/examples/counter/counter-test.html +0 -13
  109. package/docs/static/examples/counter/counter.html +0 -5
  110. package/docs/static/examples/counter/counter.test.js +0 -28
  111. package/docs/static/examples/document/document.html +0 -3
  112. package/docs/static/examples/eventbus/eventbus-test.html +0 -15
  113. package/docs/static/examples/eventbus/eventbus.html +0 -13
  114. package/docs/static/examples/eventbus/eventbus.js +0 -15
  115. package/docs/static/examples/eventbus/eventbus.test.js +0 -19
  116. package/docs/static/examples/i18n/i18n.html +0 -77
  117. package/docs/static/examples/ng-bind/ng-bind.html +0 -9
  118. package/docs/static/examples/ng-blur/ng-blur.html +0 -9
  119. package/docs/static/examples/ng-channel/ng-channel-test.html +0 -17
  120. package/docs/static/examples/ng-channel/ng-channel.html +0 -24
  121. package/docs/static/examples/ng-channel/ng-channel.test.js +0 -31
  122. package/docs/static/examples/ng-class/ng-class.html +0 -71
  123. package/docs/static/examples/ng-class-even/ng-class-even.html +0 -8
  124. package/docs/static/examples/ng-class-odd/ng-class-odd.html +0 -8
  125. package/docs/static/examples/ng-click/ng-click.html +0 -6
  126. package/docs/static/examples/ng-copy/ng-copy.html +0 -6
  127. package/docs/static/examples/ng-cut/ng-cut.html +0 -6
  128. package/docs/static/examples/ng-dblclick/ng-dblclick.html +0 -10
  129. package/docs/static/examples/ng-focus/ng-focus.html +0 -9
  130. package/docs/static/examples/ng-keydown/ng-keydown.html +0 -9
  131. package/docs/static/examples/ng-keyup/ng-keyup.html +0 -9
  132. package/docs/static/examples/ng-load/ng-load.html +0 -8
  133. package/docs/static/examples/ng-mousedown/ng-mousedown.html +0 -6
  134. package/docs/static/examples/ng-mouseenter/ng-mouseenter.html +0 -4
  135. package/docs/static/examples/ng-mouseleave/ng-mouseleave.html +0 -4
  136. package/docs/static/examples/ng-mousemove/ng-mousemove.html +0 -4
  137. package/docs/static/examples/ng-mouseout/ng-mouseout.html +0 -4
  138. package/docs/static/examples/ng-mouseover/ng-mouseover.html +0 -4
  139. package/docs/static/examples/ng-mouseup/ng-mouseup.html +0 -4
  140. package/docs/static/examples/ng-non-bindable/ng-non-bindable-test.html +0 -13
  141. package/docs/static/examples/ng-non-bindable/ng-non-bindable.html +0 -3
  142. package/docs/static/examples/ng-non-bindable/ng-non-bindable.test.js +0 -11
  143. package/docs/static/examples/window/window.html +0 -4
  144. package/docs/static/typedoc/.nojekyll +0 -1
  145. package/docs/static/typedoc/assets/hierarchy.js +0 -1
  146. package/docs/static/typedoc/assets/highlight.css +0 -29
  147. package/docs/static/typedoc/assets/icons.js +0 -18
  148. package/docs/static/typedoc/assets/icons.svg +0 -1
  149. package/docs/static/typedoc/assets/main.js +0 -60
  150. package/docs/static/typedoc/assets/navigation.js +0 -1
  151. package/docs/static/typedoc/assets/search.js +0 -1
  152. package/docs/static/typedoc/assets/style.css +0 -1633
  153. package/docs/static/typedoc/classes/Location.html +0 -55
  154. package/docs/static/typedoc/classes/LocationProvider.html +0 -20
  155. package/docs/static/typedoc/classes/LogProvider.html +0 -6
  156. package/docs/static/typedoc/classes/PubSub.html +0 -71
  157. package/docs/static/typedoc/classes/PubSubProvider.html +0 -4
  158. package/docs/static/typedoc/classes/TemplateCacheProvider.html +0 -5
  159. package/docs/static/typedoc/hierarchy.html +0 -1
  160. package/docs/static/typedoc/index.html +0 -1
  161. package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
  162. package/docs/static/typedoc/interfaces/Html5Mode.html +0 -23
  163. package/docs/static/typedoc/interfaces/HttpHeadersGetter.html +0 -1
  164. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +0 -31
  165. package/docs/static/typedoc/interfaces/HttpRequestConfigHeaders.html +0 -6
  166. package/docs/static/typedoc/interfaces/HttpRequestTransformer.html +0 -1
  167. package/docs/static/typedoc/interfaces/HttpResponse.html +0 -7
  168. package/docs/static/typedoc/interfaces/HttpResponseTransformer.html +0 -1
  169. package/docs/static/typedoc/interfaces/HttpService.html +0 -38
  170. package/docs/static/typedoc/interfaces/LogService.html +0 -12
  171. package/docs/static/typedoc/interfaces/RequestConfig.html +0 -48
  172. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +0 -38
  173. package/docs/static/typedoc/interfaces/ServiceProvider.html +0 -5
  174. package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
  175. package/docs/static/typedoc/types/HttpParamSerializer.html +0 -2
  176. package/docs/static/typedoc/types/HttpParams.html +0 -2
  177. package/docs/static/typedoc/types/HttpPromise.html +0 -1
  178. package/docs/static/typedoc/types/HttpResponseStatus.html +0 -1
  179. package/docs/static/typedoc/types/LogCall.html +0 -2
  180. package/docs/static/typedoc/types/LogServiceFactory.html +0 -2
  181. package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
  182. package/docs/static/typedoc/variables/EventBus.html +0 -1
  183. package/docs/static/version.js +0 -13
  184. package/docs/test-results/.last-run.json +0 -4
  185. package/docs/test-results/static-examples-counter-counter-counter-example/error-context.md +0 -50
  186. package/eslint.config.js +0 -26
  187. package/images/android-chrome-192x192.png +0 -0
  188. package/images/android-chrome-512x512.png +0 -0
  189. package/images/apple-touch-icon.png +0 -0
  190. package/images/favicon-16x16.png +0 -0
  191. package/images/favicon-32x32.png +0 -0
  192. package/images/favicon.ico +0 -0
  193. package/images/site.webmanifest +0 -19
  194. package/index.html +0 -86
  195. package/legacy.d.ts +0 -1678
  196. package/playwright.config.ts +0 -81
  197. package/public/jasmine/boot0.js +0 -66
  198. package/public/jasmine/boot1.js +0 -134
  199. package/public/jasmine/jasmine-html.js +0 -970
  200. package/public/jasmine/jasmine.css +0 -323
  201. package/public/jasmine/jasmine.js +0 -11406
  202. package/public/public/README.md +0 -1
  203. package/public/public/circle.html +0 -1
  204. package/public/public/jasmine-helper.css +0 -9
  205. package/public/public/my_child_directive.html +0 -1
  206. package/public/public/my_directive.html +0 -1
  207. package/public/public/my_other_directive.html +0 -1
  208. package/public/public/test.html +0 -1
  209. package/rollup.config.js +0 -51
  210. package/src/angular.js +0 -286
  211. package/src/angular.spec.js +0 -1191
  212. package/src/animations/animate-cache.js +0 -80
  213. package/src/animations/animate-children-directive.js +0 -32
  214. package/src/animations/animate-children-directive.md +0 -80
  215. package/src/animations/animate-css-driver.js +0 -284
  216. package/src/animations/animate-css.html +0 -58
  217. package/src/animations/animate-css.js +0 -915
  218. package/src/animations/animate-css.md +0 -263
  219. package/src/animations/animate-js-driver.js +0 -60
  220. package/src/animations/animate-js.html +0 -47
  221. package/src/animations/animate-js.js +0 -371
  222. package/src/animations/animate-queue.js +0 -859
  223. package/src/animations/animate-runner.js +0 -193
  224. package/src/animations/animate-swap.js +0 -33
  225. package/src/animations/animate-swap.md +0 -88
  226. package/src/animations/animate.html +0 -19
  227. package/src/animations/animate.js +0 -546
  228. package/src/animations/animate.md +0 -933
  229. package/src/animations/animate.spec.js +0 -490
  230. package/src/animations/animation.js +0 -519
  231. package/src/animations/animations.test.js +0 -10
  232. package/src/animations/interface.ts +0 -19
  233. package/src/animations/raf-scheduler.html +0 -19
  234. package/src/animations/raf-scheduler.js +0 -92
  235. package/src/animations/raf-scheduler.spec.js +0 -98
  236. package/src/animations/shared.js +0 -341
  237. package/src/binding.html +0 -19
  238. package/src/binding.spec.js +0 -474
  239. package/src/binding.test.js +0 -10
  240. package/src/core/compile/attributes.js +0 -337
  241. package/src/core/compile/compile.html +0 -19
  242. package/src/core/compile/compile.js +0 -3271
  243. package/src/core/compile/compile.md +0 -1128
  244. package/src/core/compile/compile.spec.js +0 -15574
  245. package/src/core/compile/compile.test.js +0 -12
  246. package/src/core/controller/controller.html +0 -22
  247. package/src/core/controller/controller.js +0 -193
  248. package/src/core/controller/controller.spec.js +0 -334
  249. package/src/core/controller/controller.test.js +0 -12
  250. package/src/core/controller/interface.ts +0 -6
  251. package/src/core/core.html +0 -20
  252. package/src/core/core.test.js +0 -12
  253. package/src/core/di/injector.html +0 -19
  254. package/src/core/di/injector.js +0 -307
  255. package/src/core/di/injector.md +0 -740
  256. package/src/core/di/injector.spec.js +0 -2310
  257. package/src/core/di/injector.test.js +0 -12
  258. package/src/core/di/internal-injector.js +0 -286
  259. package/src/core/di/ng-module.html +0 -19
  260. package/src/core/di/ng-module.js +0 -229
  261. package/src/core/di/ng-module.spec.js +0 -263
  262. package/src/core/di/ng-module.test.js +0 -12
  263. package/src/core/filter/filter.html +0 -19
  264. package/src/core/filter/filter.js +0 -55
  265. package/src/core/filter/filter.md +0 -132
  266. package/src/core/filter/filter.spec.js +0 -149
  267. package/src/core/filter/filter.test.js +0 -12
  268. package/src/core/interpolate/interface.ts +0 -14
  269. package/src/core/interpolate/interpolate.html +0 -22
  270. package/src/core/interpolate/interpolate.js +0 -410
  271. package/src/core/interpolate/interpolate.spec.js +0 -601
  272. package/src/core/interpolate/interpolate.test.js +0 -12
  273. package/src/core/parse/ast/ast-node.ts +0 -81
  274. package/src/core/parse/ast/ast.html +0 -19
  275. package/src/core/parse/ast/ast.js +0 -574
  276. package/src/core/parse/ast/ast.spec.js +0 -1453
  277. package/src/core/parse/ast/ast.test.js +0 -10
  278. package/src/core/parse/ast-type.js +0 -23
  279. package/src/core/parse/interface.ts +0 -84
  280. package/src/core/parse/interpreter.js +0 -915
  281. package/src/core/parse/lexer/lexer.html +0 -19
  282. package/src/core/parse/lexer/lexer.js +0 -338
  283. package/src/core/parse/lexer/lexer.spec.js +0 -303
  284. package/src/core/parse/lexer/lexer.test.js +0 -10
  285. package/src/core/parse/lexer/token.ts +0 -22
  286. package/src/core/parse/parse.html +0 -19
  287. package/src/core/parse/parse.js +0 -337
  288. package/src/core/parse/parse.md +0 -57
  289. package/src/core/parse/parse.spec.js +0 -2107
  290. package/src/core/parse/parse.test.js +0 -10
  291. package/src/core/parse/parser/parser.html +0 -19
  292. package/src/core/parse/parser/parser.js +0 -64
  293. package/src/core/parse/parser/parser.spec.js +0 -8
  294. package/src/core/parse/parser/parser.test.js +0 -10
  295. package/src/core/prop.spec.js +0 -775
  296. package/src/core/root-element.spec.js +0 -14
  297. package/src/core/sanitize/interface.ts +0 -10
  298. package/src/core/sanitize/sanitize-uri.js +0 -75
  299. package/src/core/sanitize/sanitize-uri.spec.js +0 -249
  300. package/src/core/sanitize/sanitize-uri.test.js +0 -12
  301. package/src/core/sanitize/sanitize.html +0 -22
  302. package/src/core/scope/scope.html +0 -19
  303. package/src/core/scope/scope.js +0 -1252
  304. package/src/core/scope/scope.spec.js +0 -3000
  305. package/src/core/scope/scope.test.js +0 -12
  306. package/src/directive/aria/aria.html +0 -19
  307. package/src/directive/aria/aria.js +0 -382
  308. package/src/directive/aria/aria.md +0 -145
  309. package/src/directive/aria/aria.spec.js +0 -1241
  310. package/src/directive/aria/aria.test.js +0 -12
  311. package/src/directive/attrs/attrs.html +0 -19
  312. package/src/directive/attrs/attrs.js +0 -106
  313. package/src/directive/attrs/attrs.md +0 -224
  314. package/src/directive/attrs/attrs.spec.js +0 -71
  315. package/src/directive/attrs/attrs.test.js +0 -12
  316. package/src/directive/attrs/boolean.html +0 -19
  317. package/src/directive/attrs/boolean.spec.js +0 -137
  318. package/src/directive/attrs/boolean.test.js +0 -12
  319. package/src/directive/attrs/element-style.html +0 -22
  320. package/src/directive/attrs/element-style.spec.js +0 -85
  321. package/src/directive/attrs/element-style.test.js +0 -12
  322. package/src/directive/attrs/src.html +0 -19
  323. package/src/directive/attrs/src.spec.js +0 -163
  324. package/src/directive/attrs/src.test.js +0 -12
  325. package/src/directive/bind/bind-html.spec.js +0 -36
  326. package/src/directive/bind/bind.html +0 -20
  327. package/src/directive/bind/bind.js +0 -78
  328. package/src/directive/bind/bind.md +0 -142
  329. package/src/directive/bind/bind.spec.js +0 -314
  330. package/src/directive/bind/bind.test.js +0 -12
  331. package/src/directive/channel/channel.html +0 -19
  332. package/src/directive/channel/channel.js +0 -30
  333. package/src/directive/channel/channel.spec.js +0 -67
  334. package/src/directive/channel/channel.test.js +0 -10
  335. package/src/directive/class/class-test.html +0 -23
  336. package/src/directive/class/class.html +0 -19
  337. package/src/directive/class/class.js +0 -184
  338. package/src/directive/class/class.spec.js +0 -704
  339. package/src/directive/class/class.test.js +0 -12
  340. package/src/directive/cloak/cloak.html +0 -19
  341. package/src/directive/cloak/cloak.js +0 -11
  342. package/src/directive/cloak/cloak.spec.js +0 -44
  343. package/src/directive/cloak/cloak.test.js +0 -12
  344. package/src/directive/controller/controller.html +0 -22
  345. package/src/directive/controller/controller.js +0 -11
  346. package/src/directive/controller/controller.md +0 -46
  347. package/src/directive/controller/controller.spec.js +0 -175
  348. package/src/directive/controller/controller.test.js +0 -12
  349. package/src/directive/events/click.spec.js +0 -35
  350. package/src/directive/events/event.spec.js +0 -267
  351. package/src/directive/events/events-test.html +0 -36
  352. package/src/directive/events/events.html +0 -20
  353. package/src/directive/events/events.js +0 -65
  354. package/src/directive/events/events.md +0 -125
  355. package/src/directive/events/events.test.js +0 -12
  356. package/src/directive/form/form.html +0 -19
  357. package/src/directive/form/form.js +0 -669
  358. package/src/directive/form/form.spec.js +0 -1515
  359. package/src/directive/form/form.test.js +0 -12
  360. package/src/directive/http/delete.spec.js +0 -23
  361. package/src/directive/http/form-router-test.html +0 -44
  362. package/src/directive/http/form-test.html +0 -18
  363. package/src/directive/http/get.spec.js +0 -488
  364. package/src/directive/http/http.html +0 -22
  365. package/src/directive/http/http.js +0 -342
  366. package/src/directive/http/http.test.js +0 -12
  367. package/src/directive/http/interface.ts +0 -36
  368. package/src/directive/http/post-example.html +0 -30
  369. package/src/directive/http/post.spec.js +0 -521
  370. package/src/directive/http/put.spec.js +0 -23
  371. package/src/directive/if/if-animate-css.html +0 -57
  372. package/src/directive/if/if-animate-svg.html +0 -25
  373. package/src/directive/if/if.html +0 -19
  374. package/src/directive/if/if.js +0 -72
  375. package/src/directive/if/if.md +0 -76
  376. package/src/directive/if/if.spec.js +0 -293
  377. package/src/directive/if/if.test.js +0 -114
  378. package/src/directive/include/include.html +0 -19
  379. package/src/directive/include/include.js +0 -151
  380. package/src/directive/include/include.md +0 -87
  381. package/src/directive/include/include.spec.js +0 -734
  382. package/src/directive/include/include.test.js +0 -12
  383. package/src/directive/init/init.html +0 -19
  384. package/src/directive/init/init.js +0 -22
  385. package/src/directive/init/init.md +0 -41
  386. package/src/directive/init/init.spec.js +0 -68
  387. package/src/directive/init/init.test.js +0 -12
  388. package/src/directive/inject/inject.html +0 -19
  389. package/src/directive/inject/inject.js +0 -35
  390. package/src/directive/inject/inject.spec.js +0 -108
  391. package/src/directive/inject/inject.test.js +0 -12
  392. package/src/directive/input/input-example.html +0 -15
  393. package/src/directive/input/input.html +0 -19
  394. package/src/directive/input/input.js +0 -1078
  395. package/src/directive/input/input.md +0 -706
  396. package/src/directive/input/input.spec.js +0 -3700
  397. package/src/directive/input/input.test.js +0 -12
  398. package/src/directive/messages/messages.html +0 -22
  399. package/src/directive/messages/messages.js +0 -349
  400. package/src/directive/messages/messages.md +0 -543
  401. package/src/directive/messages/messages.spec.js +0 -1083
  402. package/src/directive/messages/messages.test.js +0 -12
  403. package/src/directive/model/change.md +0 -25
  404. package/src/directive/model/model.html +0 -19
  405. package/src/directive/model/model.js +0 -1170
  406. package/src/directive/model/model.spec.js +0 -1976
  407. package/src/directive/model/model.test.js +0 -12
  408. package/src/directive/model-options/model-option.test.js +0 -12
  409. package/src/directive/model-options/model-options.html +0 -22
  410. package/src/directive/model-options/model-options.js +0 -142
  411. package/src/directive/model-options/model-options.md +0 -407
  412. package/src/directive/model-options/model-options.spec.js +0 -1022
  413. package/src/directive/non-bindable/non-bindable.html +0 -22
  414. package/src/directive/non-bindable/non-bindable.js +0 -9
  415. package/src/directive/non-bindable/non-bindable.spec.js +0 -59
  416. package/src/directive/non-bindable/non-bindable.test.js +0 -12
  417. package/src/directive/observe/observe-demo.html +0 -184
  418. package/src/directive/observe/observe.html +0 -19
  419. package/src/directive/observe/observe.js +0 -41
  420. package/src/directive/observe/observe.spec.js +0 -106
  421. package/src/directive/observe/observe.test.js +0 -10
  422. package/src/directive/on/on.html +0 -19
  423. package/src/directive/on/on.spec.js +0 -215
  424. package/src/directive/on/on.test.js +0 -12
  425. package/src/directive/options/options-example.html +0 -17
  426. package/src/directive/options/options.html +0 -22
  427. package/src/directive/options/options.js +0 -542
  428. package/src/directive/options/options.md +0 -179
  429. package/src/directive/options/options.spec.js +0 -3554
  430. package/src/directive/options/options.test.js +0 -12
  431. package/src/directive/ref/href.html +0 -19
  432. package/src/directive/ref/href.spec.js +0 -141
  433. package/src/directive/ref/href.test.js +0 -19
  434. package/src/directive/ref/ref.html +0 -19
  435. package/src/directive/ref/ref.js +0 -89
  436. package/src/directive/ref/ref.spec.js +0 -546
  437. package/src/directive/repeat/repeat.html +0 -19
  438. package/src/directive/repeat/repeat.js +0 -333
  439. package/src/directive/repeat/repeat.md +0 -330
  440. package/src/directive/repeat/repeat.spec.js +0 -1209
  441. package/src/directive/repeat/repeat.test.js +0 -12
  442. package/src/directive/script/script.html +0 -19
  443. package/src/directive/script/script.js +0 -17
  444. package/src/directive/script/script.md +0 -11
  445. package/src/directive/script/script.spec.js +0 -47
  446. package/src/directive/script/script.test.js +0 -12
  447. package/src/directive/select/select.html +0 -19
  448. package/src/directive/select/select.js +0 -594
  449. package/src/directive/select/select.md +0 -74
  450. package/src/directive/select/select.spec.js +0 -2566
  451. package/src/directive/select/select.test.js +0 -12
  452. package/src/directive/setter/setter.html +0 -19
  453. package/src/directive/setter/setter.js +0 -59
  454. package/src/directive/setter/setter.spec.js +0 -100
  455. package/src/directive/setter/setter.test.js +0 -12
  456. package/src/directive/show-hide/show-hide.html +0 -22
  457. package/src/directive/show-hide/show-hide.js +0 -65
  458. package/src/directive/show-hide/show-hide.md +0 -255
  459. package/src/directive/show-hide/show-hide.spec.js +0 -268
  460. package/src/directive/show-hide/show-hide.test.js +0 -12
  461. package/src/directive/style/style.html +0 -19
  462. package/src/directive/style/style.js +0 -27
  463. package/src/directive/style/style.md +0 -23
  464. package/src/directive/style/style.spec.js +0 -183
  465. package/src/directive/style/style.test.js +0 -12
  466. package/src/directive/switch/switch.html +0 -19
  467. package/src/directive/switch/switch.js +0 -133
  468. package/src/directive/switch/switch.md +0 -66
  469. package/src/directive/switch/switch.spec.js +0 -509
  470. package/src/directive/switch/switch.test.js +0 -12
  471. package/src/directive/transclude/transclude.js +0 -122
  472. package/src/directive/validators/validators.html +0 -22
  473. package/src/directive/validators/validators.js +0 -346
  474. package/src/directive/validators/validators.spec.js +0 -740
  475. package/src/directive/validators/validators.test.js +0 -12
  476. package/src/filters/filter.js +0 -213
  477. package/src/filters/filter.spec.js +0 -719
  478. package/src/filters/filters.html +0 -22
  479. package/src/filters/filters.js +0 -239
  480. package/src/filters/filters.spec.js +0 -36
  481. package/src/filters/filters.test.js +0 -12
  482. package/src/filters/interface.ts +0 -9
  483. package/src/filters/limit-to.js +0 -55
  484. package/src/filters/limit-to.spec.js +0 -252
  485. package/src/filters/order-by.js +0 -181
  486. package/src/filters/order-by.spec.js +0 -883
  487. package/src/index.js +0 -6
  488. package/src/index.spec.js +0 -11
  489. package/src/injection-tokens.js +0 -81
  490. package/src/interface.ts +0 -430
  491. package/src/ng.js +0 -291
  492. package/src/ng.spec.js +0 -45
  493. package/src/router/common/trace.js +0 -240
  494. package/src/router/directives/component-example.html +0 -37
  495. package/src/router/directives/state-directives.html +0 -22
  496. package/src/router/directives/state-directives.js +0 -393
  497. package/src/router/directives/state-directives.md +0 -435
  498. package/src/router/directives/state-directives.spec.js +0 -1091
  499. package/src/router/directives/state-directives.test.js +0 -10
  500. package/src/router/directives/view-directive.js +0 -489
  501. package/src/router/directives/view-directive.spec.js +0 -1921
  502. package/src/router/directives/view-directive.test.js +0 -10
  503. package/src/router/directives/view-directives.html +0 -22
  504. package/src/router/glob/glob.html +0 -19
  505. package/src/router/glob/glob.js +0 -102
  506. package/src/router/glob/glob.spec.js +0 -108
  507. package/src/router/glob/glob.test.js +0 -12
  508. package/src/router/hooks/core-resolvables.js +0 -38
  509. package/src/router/hooks/ignored-transition.js +0 -25
  510. package/src/router/hooks/invalid-transition.js +0 -14
  511. package/src/router/hooks/lazy-load.js +0 -104
  512. package/src/router/hooks/on-enter-exit-retain.js +0 -55
  513. package/src/router/hooks/redirect-to.js +0 -38
  514. package/src/router/hooks/resolve.js +0 -57
  515. package/src/router/hooks/update-globals.js +0 -34
  516. package/src/router/hooks/url.js +0 -34
  517. package/src/router/hooks/views.js +0 -41
  518. package/src/router/params/interface.ts +0 -626
  519. package/src/router/params/param-factory.js +0 -23
  520. package/src/router/params/param-type.js +0 -133
  521. package/src/router/params/param-types.js +0 -153
  522. package/src/router/params/param.js +0 -243
  523. package/src/router/params/state-params.js +0 -36
  524. package/src/router/path/path-node.js +0 -78
  525. package/src/router/path/path-utils.js +0 -207
  526. package/src/router/resolve/interface.ts +0 -208
  527. package/src/router/resolve/resolvable.js +0 -123
  528. package/src/router/resolve/resolve-context.js +0 -190
  529. package/src/router/router-test-hashbang.html +0 -45
  530. package/src/router/router-test.html +0 -41
  531. package/src/router/router.html +0 -22
  532. package/src/router/router.js +0 -54
  533. package/src/router/router.test.js +0 -12
  534. package/src/router/services.spec.js +0 -52
  535. package/src/router/state/interface.ts +0 -1007
  536. package/src/router/state/state-builder.js +0 -376
  537. package/src/router/state/state-builder.spec.js +0 -86
  538. package/src/router/state/state-matcher.js +0 -64
  539. package/src/router/state/state-object.js +0 -118
  540. package/src/router/state/state-queue-manager.js +0 -95
  541. package/src/router/state/state-registry.js +0 -262
  542. package/src/router/state/state-service.js +0 -687
  543. package/src/router/state/state.html +0 -23
  544. package/src/router/state/state.spec.js +0 -1002
  545. package/src/router/state/state.test.js +0 -12
  546. package/src/router/state/target-state.js +0 -162
  547. package/src/router/state/views.js +0 -195
  548. package/src/router/state-filter.spec.js +0 -139
  549. package/src/router/state-filters.js +0 -46
  550. package/src/router/template-factory.html +0 -19
  551. package/src/router/template-factory.js +0 -249
  552. package/src/router/template-factory.spec.js +0 -146
  553. package/src/router/template-factory.test.js +0 -12
  554. package/src/router/transition/hook-builder.js +0 -137
  555. package/src/router/transition/hook-registry.js +0 -181
  556. package/src/router/transition/interface.js +0 -18
  557. package/src/router/transition/interface.ts +0 -922
  558. package/src/router/transition/reject-factory.js +0 -122
  559. package/src/router/transition/transition-event-type.js +0 -26
  560. package/src/router/transition/transition-hook.js +0 -199
  561. package/src/router/transition/transition-service.js +0 -297
  562. package/src/router/transition/transition.js +0 -653
  563. package/src/router/url/url-config.js +0 -155
  564. package/src/router/url/url-matcher.js +0 -532
  565. package/src/router/url/url-rule.js +0 -231
  566. package/src/router/url/url-rules.js +0 -350
  567. package/src/router/url/url-service.js +0 -446
  568. package/src/router/url/url-service.spec.js +0 -1288
  569. package/src/router/url/url.html +0 -19
  570. package/src/router/url/url.test.js +0 -12
  571. package/src/router/view/interface.ts +0 -51
  572. package/src/router/view/view.html +0 -19
  573. package/src/router/view/view.js +0 -262
  574. package/src/router/view/view.spec.js +0 -100
  575. package/src/router/view/view.test.js +0 -12
  576. package/src/router/view-hook.spec.js +0 -215
  577. package/src/router/view-scroll.js +0 -33
  578. package/src/router/view-scroll.spec.js +0 -72
  579. package/src/services/anchor-scroll/anchor-scroll.html +0 -76
  580. package/src/services/anchor-scroll/anchor-scroll.js +0 -147
  581. package/src/services/exception/exception-handler.js +0 -75
  582. package/src/services/exception/interface.ts +0 -7
  583. package/src/services/http/http.html +0 -23
  584. package/src/services/http/http.js +0 -1109
  585. package/src/services/http/http.spec.js +0 -4320
  586. package/src/services/http/http.test.js +0 -11
  587. package/src/services/http/interface.ts +0 -256
  588. package/src/services/http/template-request.spec.js +0 -220
  589. package/src/services/location/interface.ts +0 -70
  590. package/src/services/location/location.html +0 -22
  591. package/src/services/location/location.js +0 -1006
  592. package/src/services/location/location.spec.js +0 -3792
  593. package/src/services/location/location.test.js +0 -12
  594. package/src/services/log/interface.ts +0 -39
  595. package/src/services/log/log.html +0 -19
  596. package/src/services/log/log.js +0 -74
  597. package/src/services/log/log.spec.js +0 -64
  598. package/src/services/log/log.test.js +0 -12
  599. package/src/services/pubsub/pubsub.html +0 -19
  600. package/src/services/pubsub/pubsub.js +0 -349
  601. package/src/services/pubsub/pubsub.spec.js +0 -400
  602. package/src/services/pubsub/pubsub.test.js +0 -12
  603. package/src/services/sce/sce.html +0 -19
  604. package/src/services/sce/sce.js +0 -852
  605. package/src/services/sce/sce.spec.js +0 -617
  606. package/src/services/sce/sce.test.js +0 -12
  607. package/src/services/template-cache/template-cache.html +0 -22
  608. package/src/services/template-cache/template-cache.js +0 -15
  609. package/src/services/template-cache/template-cache.spec.js +0 -134
  610. package/src/services/template-cache/template-cache.test.js +0 -12
  611. package/src/services/template-request/interface.ts +0 -23
  612. package/src/services/template-request/template-request.js +0 -142
  613. package/src/shared/cache.js +0 -7
  614. package/src/shared/common.js +0 -365
  615. package/src/shared/common.spec.js +0 -294
  616. package/src/shared/constants.js +0 -21
  617. package/src/shared/dom.js +0 -716
  618. package/src/shared/hof.js +0 -157
  619. package/src/shared/hof.spec.js +0 -60
  620. package/src/shared/interface.ts +0 -21
  621. package/src/shared/min-err.spec.js +0 -178
  622. package/src/shared/noderef.js +0 -225
  623. package/src/shared/predicates.js +0 -34
  624. package/src/shared/queue.js +0 -105
  625. package/src/shared/queue.spec.js +0 -80
  626. package/src/shared/shared.html +0 -24
  627. package/src/shared/shared.test.js +0 -12
  628. package/src/shared/strings.js +0 -142
  629. package/src/shared/strings.spec.js +0 -40
  630. package/src/shared/test-utils.js +0 -47
  631. package/src/shared/url-utils/interface.ts +0 -54
  632. package/src/shared/url-utils/url-utils.html +0 -22
  633. package/src/shared/url-utils/url-utils.js +0 -122
  634. package/src/shared/url-utils/url-utils.spec.js +0 -148
  635. package/src/shared/url-utils/url-utils.test.js +0 -12
  636. package/src/shared/utils.js +0 -1255
  637. package/src/shared/utils.spec.js +0 -178
  638. package/src/src.html +0 -21
  639. package/src/src.test.js +0 -10
  640. package/tsconfig.json +0 -19
  641. package/tsconfig.types.json +0 -14
  642. package/typedoc.json +0 -8
  643. package/utils/express.js +0 -203
  644. package/utils/version.cjs +0 -23
  645. package/vite.config.js +0 -14
@@ -1,3271 +0,0 @@
1
- import {
2
- createElementFromHTML,
3
- createNodelistFromHTML,
4
- emptyElement,
5
- getBooleanAttrName,
6
- getCacheData,
7
- getInheritedData,
8
- isTextNode,
9
- setCacheData,
10
- setIsolateScope,
11
- setScope,
12
- startingTag,
13
- } from "../../shared/dom.js";
14
- import { NodeRef } from "../../shared/noderef.js";
15
- import { identifierForController } from "../controller/controller.js";
16
- import {
17
- minErr,
18
- assertArg,
19
- assertNotHasOwnProperty,
20
- isDefined,
21
- isFunction,
22
- isObject,
23
- isString,
24
- lowercase,
25
- extend,
26
- isScope,
27
- inherit,
28
- isUndefined,
29
- getNodeName,
30
- bind,
31
- trim,
32
- isBoolean,
33
- equals,
34
- simpleCompare,
35
- isError,
36
- directiveNormalize,
37
- isProxy,
38
- hasOwn,
39
- } from "../../shared/utils.js";
40
- import { SCE_CONTEXTS } from "../../services/sce/sce.js";
41
- import { PREFIX_REGEXP } from "../../shared/constants.js";
42
- import { createEventDirective } from "../../directive/events/events.js";
43
- import { Attributes } from "./attributes.js";
44
- import { ngObserveDirective } from "../../directive/observe/observe.js";
45
- import { $injectTokens as $t } from "../../injection-tokens.js";
46
-
47
- /**
48
- * A function passed as the fifth argument to a {@type PublicLinkFn} link function.
49
- * It behaves like a linking function, with the `scope` argument automatically created
50
- * as a new child of the transcluded parent scope.
51
- *
52
- * The function returns the DOM content to be injected (transcluded) into the directive.
53
- *
54
- * @callback TranscludeFn
55
- * @param {Element | Node | ChildNode | NodeList | Node[]} [clone] - The DOM node to be inserted into the transcluded directive.
56
- * @param {import("../scope/scope.js").Scope} [scope] - The new child scope created from the transcluded parent.
57
- * @returns void
58
-
59
- /**
60
- * A specialized version of {@link TranscludeFn} with the scope argument already bound.
61
- * This function requires no parameters and returns the same result as {@link TranscludeFn}.
62
- *
63
- * @typedef {() => Element|Node} BoundTranscludeFn
64
- */
65
-
66
- /**
67
- * @typedef {Object} SimpleChange
68
- * @property {any} currentValue
69
- * @property {boolean} firstChange
70
- */
71
-
72
- /**
73
- * @description A function returned by the '$compile' service that links a compiled template to a scope.
74
- *
75
- * @callback PublicLinkFn
76
- * @param {import('../scope/scope.js').Scope} scope - Scope to link with element
77
- * @param {TranscludeFn} [cloneConnectFn]
78
- * @param {*} [options]
79
- * @return {Element|Node|ChildNode|Node[]} The nodes to be linked.
80
- */
81
-
82
- /**
83
- * @description Entry point for the '$compile' service.
84
- *
85
- * @callback CompileFn
86
- * @param {string|Element|Node|ChildNode|NodeList} compileNode - The node to be compiled.
87
- * @param {TranscludeFn} [transcludeFn] - An optional transclusion function to be used during compilation.
88
- * @param {number} [maxPriority] - An optional maximum priority for directives.
89
- * @param {string} [ignoreDirective] - An optional directive to ignore during compilation.
90
- * @param {*} [previousCompileContext] - An optional context from a previous compilation. TODO
91
- * @returns {PublicLinkFn} A public link function.
92
- */
93
-
94
- /**
95
- * @typedef {Object} LinkFnMapping
96
- * @property {number} index
97
- * @property {NodeLinkFnCtx} [nodeLinkFnCtx]
98
- * @property {CompositeLinkFn} [childLinkFn]
99
- */
100
-
101
- /**
102
- * @typedef {function(): CompositeLinkFn} CompileNodesFn
103
- */
104
-
105
- /**
106
- * @callback NodeLinkFn
107
- * @returns {Node|Element|NodeList}
108
- */
109
-
110
- /**
111
- * @typedef {Object} NodeLinkFnCtx
112
- * @property {NodeLinkFn} nodeLinkFn
113
- * @property {boolean} terminal
114
- * @property {TranscludeFn} transclude
115
- * @property {boolean} transcludeOnThisElement
116
- * @property {boolean} templateOnThisElement
117
- * @property {boolean} newScope
118
- */
119
-
120
- /**
121
- * @typedef {function(): NodeLinkFn} ApplyDirectivesToNodeFn
122
- */
123
-
124
- /**
125
- * @description Function that aggregates all linking fns for a compilation root (nodeList)
126
- * @callback CompositeLinkFn
127
- * @param {import('../scope/scope.js').Scope} scope - The scope to be linked to the template
128
- * @param {NodeRef} $linkNode - wrapper around a nodeList
129
- * @param {Function} [parentBoundTranscludeFn]
130
- */
131
-
132
- const $compileMinErr = minErr("$compile");
133
- const EXCLUDED_DIRECTIVES = ["ngIf", "ngRepeat"];
134
- const ALL_OR_NOTHING_ATTRS = ["ngSrc", "ngSrcset", "src", "srcset"];
135
- const REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
136
- // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
137
- // The assumption is that future DOM event attribute names will begin with
138
- // 'on' and be composed of only English letters.
139
- const EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
140
- export const DirectiveSuffix = "Directive";
141
-
142
- export class CompileProvider {
143
- /* @ignore */ static $inject = [$t.$provide, $t.$$sanitizeUriProvider];
144
-
145
- /**
146
- * @param {import('../../interface.js').Provider} $provide
147
- * @param {import('../sanitize/sanitize-uri.js').SanitizeUriProvider} $$sanitizeUriProvider
148
- */
149
- constructor($provide, $$sanitizeUriProvider) {
150
- const hasDirectives = {};
151
-
152
- const bindingCache = Object.create(null);
153
-
154
- /**
155
- *
156
- * @param {import("../scope/scope.js").Scope} scope
157
- * @param {string} directiveName
158
- * @param {boolean} isController
159
- * @returns {Object} a configuration object for attribute bindings
160
- */
161
- function parseIsolateBindings(scope, directiveName, isController) {
162
- const LOCAL_REGEXP = /^([@&]|[=<]())(\??)\s*([\w$]*)$/;
163
-
164
- const bindings = Object.create(null);
165
-
166
- Object.entries(scope).forEach(([scopeName, definition]) => {
167
- definition = definition.trim();
168
-
169
- if (definition in bindingCache) {
170
- bindings[scopeName] = bindingCache[definition];
171
- return;
172
- }
173
- const match = definition.match(LOCAL_REGEXP);
174
-
175
- if (!match) {
176
- throw $compileMinErr(
177
- "iscp",
178
- "Invalid {3} for directive '{0}'." +
179
- " Definition: {... {1}: '{2}' ...}",
180
- directiveName,
181
- scopeName,
182
- definition,
183
- isController
184
- ? "controller bindings definition"
185
- : "isolate scope definition",
186
- );
187
- }
188
-
189
- bindings[scopeName] = {
190
- mode: match[1][0],
191
- collection: match[2] === "*",
192
- optional: match[3] === "?",
193
- attrName: match[4] || scopeName,
194
- };
195
- if (match[4]) {
196
- bindingCache[definition] = bindings[scopeName];
197
- }
198
- });
199
-
200
- return bindings;
201
- }
202
-
203
- function parseDirectiveBindings(directive, directiveName) {
204
- const bindings = {
205
- isolateScope: null,
206
- bindToController: null,
207
- };
208
- if (isObject(directive.scope)) {
209
- if (directive.bindToController === true) {
210
- bindings.bindToController = parseIsolateBindings(
211
- directive.scope,
212
- directiveName,
213
- true,
214
- );
215
- bindings.isolateScope = {};
216
- } else {
217
- bindings.isolateScope = parseIsolateBindings(
218
- directive.scope,
219
- directiveName,
220
- false,
221
- );
222
- }
223
- }
224
- if (isObject(directive.bindToController)) {
225
- bindings.bindToController = parseIsolateBindings(
226
- directive.bindToController,
227
- directiveName,
228
- true,
229
- );
230
- }
231
- if (bindings.bindToController && !directive.controller) {
232
- // There is no controller
233
- throw $compileMinErr(
234
- "noctrl",
235
- "Cannot bind to controller without directive '{0}'s controller.",
236
- directiveName,
237
- );
238
- }
239
- return bindings;
240
- }
241
-
242
- function getDirectiveRequire(directive) {
243
- const require =
244
- directive.require || (directive.controller && directive.name);
245
-
246
- if (!Array.isArray(require) && isObject(require)) {
247
- Object.entries(require).forEach(([key, value]) => {
248
- const match = value.match(REQUIRE_PREFIX_REGEXP);
249
- const name = value.substring(match[0].length);
250
- if (!name) {
251
- require[key] = match[0] + key;
252
- }
253
- });
254
- }
255
-
256
- return require;
257
- }
258
-
259
- function getDirectiveRestrict(restrict, name) {
260
- if (restrict && !(isString(restrict) && /[EA]/.test(restrict))) {
261
- throw $compileMinErr(
262
- "badrestrict",
263
- "Restrict property '{0}' of directive '{1}' is invalid",
264
- restrict,
265
- name,
266
- );
267
- }
268
- // Default is element or attribute
269
- return restrict || "EA";
270
- }
271
-
272
- /**
273
- * Register a new directive with the compiler.
274
- *
275
- * @param {string|Object} name Name of the directive in camel-case (i.e. `ngBind` which will match
276
- * as `ng-bind`), or an object map of directives where the keys are the names and the values
277
- * are the factories.
278
- * @param {Function|Array} directiveFactory An injectable directive factory function. See the
279
- * {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
280
- * @returns {CompileProvider} Self for chaining.
281
- */
282
- this.directive = function registerDirective(name, directiveFactory) {
283
- assertArg(name, "name");
284
- assertNotHasOwnProperty(name, "directive");
285
- if (isString(name)) {
286
- assertValidDirectiveName(name);
287
- assertArg(directiveFactory, "directiveFactory");
288
- if (!hasOwn(hasDirectives, name)) {
289
- hasDirectives[name] = [];
290
- $provide.factory(name + DirectiveSuffix, [
291
- "$injector",
292
- "$exceptionHandler",
293
- /**
294
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
295
- * @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
296
- */
297
- function ($injector, $exceptionHandler) {
298
- const directives = [];
299
- hasDirectives[name].forEach((directiveFactory, index) => {
300
- try {
301
- let directive = $injector.invoke(directiveFactory);
302
- const valueFn = (value) => () => value;
303
- if (isFunction(directive)) {
304
- directive = { compile: valueFn(directive) };
305
- } else if (!directive.compile && directive.link) {
306
- directive.compile = valueFn(directive.link);
307
- }
308
-
309
- directive.priority = directive.priority || 0;
310
- directive.index = index;
311
- directive.name = directive.name || name;
312
- directive.require = getDirectiveRequire(directive);
313
- directive.restrict = getDirectiveRestrict(
314
- directive.restrict,
315
- name,
316
- );
317
- directive.$$moduleName = directiveFactory.$$moduleName;
318
- directives.push(directive);
319
- } catch (e) {
320
- $exceptionHandler(e);
321
- }
322
- });
323
- return directives;
324
- },
325
- ]);
326
- }
327
- hasDirectives[name].push(directiveFactory);
328
- } else {
329
- Object.entries(name).forEach(([k, v]) => registerDirective(k, v));
330
- }
331
- return this;
332
- };
333
-
334
- /**
335
- * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
336
- * or an object map of components where the keys are the names and the values are the component definition objects.
337
- * @param {import("../../interface.js").Component} options Component definition object (a simplified
338
- * {directive definition object}),
339
- * with the following properties (all optional):
340
- *
341
- * - `controller` – `{(string|function()=}` – controller constructor function that should be
342
- * associated with newly created scope or the name of a {controller} if passed as a string. An empty `noop` function by default.
343
- * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
344
- * If present, the controller will be published to scope under the `controllerAs` name.
345
- * If not present, this will default to be `$ctrl`.
346
- * - `template` – `{string=|function()=}` – html template as a string or a function that
347
- * returns an html template as a string which should be used as the contents of this component.
348
- * Empty string by default.
349
- *
350
- * If `template` is a function, then it is {injected} with
351
- * the following locals:
352
- *
353
- * - `$element` - Current element
354
- * - `$attrs` - Current attributes object for the element
355
- *
356
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
357
- * template that should be used as the contents of this component.
358
- *
359
- * If `templateUrl` is a function, then it is {injected} with
360
- * the following locals:
361
- *
362
- * - `$element` - Current element
363
- * - `$attrs` - Current attributes object for the element
364
- *
365
- * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
366
- * Component properties are always bound to the component controller and not to the scope.
367
- * See {`bindToController`}.
368
- * - `transclude` – `{boolean=}` – whether {content transclusion} is enabled.
369
- * Disabled by default.
370
- * - `require` - `{Object<string, string>=}` - requires the controllers of other directives and binds them to
371
- * this component's controller. The object keys specify the property names under which the required
372
- * controllers (object values) will be bound. See {`require`}.
373
- * - `$...` – additional properties to attach to the directive factory function and the controller
374
- * constructor function. (This is used by the component router to annotate)
375
- *
376
- * @returns {CompileProvider} the compile provider itself, for chaining of function calls.
377
- */
378
- this.component = function (name, options) {
379
- if (!isString(name)) {
380
- Object.entries(name).forEach(([key, val]) => this.component(key, val));
381
- return this;
382
- }
383
-
384
- const controller = options.controller || function () {};
385
-
386
- function factory($injector) {
387
- function makeInjectable(fn) {
388
- if (isFunction(fn) || Array.isArray(fn)) {
389
- return function (tElement, tAttrs) {
390
- return $injector.invoke(fn, this, {
391
- $element: tElement,
392
- $attrs: tAttrs,
393
- });
394
- };
395
- }
396
- return fn;
397
- }
398
-
399
- const template =
400
- !options.template && !options.templateUrl ? "" : options.template;
401
- const ddo = {
402
- controller,
403
- controllerAs:
404
- identifierForController(options.controller) ||
405
- options.controllerAs ||
406
- "$ctrl",
407
- template: makeInjectable(template),
408
- templateUrl: makeInjectable(options.templateUrl),
409
- transclude: options.transclude,
410
- scope: {},
411
- bindToController: options.bindings || {},
412
- restrict: "E",
413
- require: options.require,
414
- };
415
-
416
- // Copy annotations (starting with $) over to the DDO
417
- Object.entries(options).forEach(([key, val]) => {
418
- if (key.charAt(0) === "$") {
419
- ddo[key] = val;
420
- }
421
- });
422
-
423
- return ddo;
424
- }
425
-
426
- // Copy any annotation properties (starting with $) over to the factory and controller constructor functions
427
- // These could be used by libraries such as the new component router
428
- Object.entries(options).forEach(([key, val]) => {
429
- if (key.charAt(0) === "$") {
430
- factory[key] = val;
431
- // Don't try to copy over annotations to named controller
432
- if (isFunction(controller)) {
433
- controller[key] = val;
434
- }
435
- }
436
- });
437
-
438
- factory.$inject = ["$injector"];
439
-
440
- return this.directive(name, factory);
441
- };
442
-
443
- /**
444
- * Retrieves or overrides the default regular expression that is used for determining trusted safe
445
- * urls during a[href] sanitization.
446
- *
447
- * The sanitization is a security measure aimed at preventing XSS attacks via html links.
448
- *
449
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
450
- * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationTrustedUrlList`
451
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
452
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
453
- *
454
- * @param {RegExp=} regexp New regexp to trust urls with.
455
- * @returns {RegExp|import('../sanitize/sanitize-uri.js').SanitizeUriProvider} Current RegExp if called without value or self for
456
- * chaining otherwise.
457
- */
458
- this.aHrefSanitizationTrustedUrlList = function (regexp) {
459
- if (isDefined(regexp)) {
460
- $$sanitizeUriProvider.aHrefSanitizationTrustedUrlList(regexp);
461
- return;
462
- }
463
- return $$sanitizeUriProvider.aHrefSanitizationTrustedUrlList();
464
- };
465
-
466
- /**
467
- * Retrieves or overrides the default regular expression that is used for determining trusted safe
468
- * urls during img[src] sanitization.
469
- *
470
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
471
- *
472
- * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
473
- * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationTrustedUrlList`
474
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
475
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
476
- *
477
- * @param {RegExp=} regexp New regexp to trust urls with.
478
- * @returns {RegExp|import('../sanitize/sanitize-uri.js').SanitizeUriProvider} Current RegExp if called without value or self for
479
- * chaining otherwise.
480
- */
481
- this.imgSrcSanitizationTrustedUrlList = function (regexp) {
482
- if (isDefined(regexp)) {
483
- $$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList(regexp);
484
- return;
485
- }
486
- return $$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList();
487
- };
488
-
489
- /**
490
- * @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided,
491
- * otherwise return the current strictComponentBindingsEnabled state.
492
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
493
- *
494
- * Call this method to enable / disable the strict component bindings check. If enabled, the
495
- * compiler will enforce that all scope / controller bindings of a
496
- * {@link $compileProvider#directive directive} / {@link $compileProvider#component component}
497
- * that are not set as optional with `?`, must be provided when the directive is instantiated.
498
- * If not provided, the compiler will throw the
499
- * {@link error/$compile/missingattr $compile:missingattr error}.
500
- *
501
- * The default value is false.
502
- */
503
- let strictComponentBindingsEnabled = false;
504
- this.strictComponentBindingsEnabled = function (enabled) {
505
- if (isDefined(enabled)) {
506
- strictComponentBindingsEnabled = enabled;
507
- return this;
508
- }
509
- return strictComponentBindingsEnabled;
510
- };
511
-
512
- /**
513
- * The security context of DOM Properties.
514
- */
515
- const PROP_CONTEXTS = Object.create(null);
516
-
517
- /**
518
- * Defines the security context for DOM properties bound by ng-prop-*.
519
- *
520
- * @param {string} elementName The element name or '*' to match any element.
521
- * @param {string} propertyName The DOM property name.
522
- * @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL`
523
- * @returns {object} `this` for chaining
524
- */
525
- this.addPropertySecurityContext = function (
526
- elementName,
527
- propertyName,
528
- ctx,
529
- ) {
530
- const key = `${elementName.toLowerCase()}|${propertyName.toLowerCase()}`;
531
-
532
- if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) {
533
- throw $compileMinErr(
534
- "ctxoverride",
535
- "Property context '{0}.{1}' already set to '{2}', cannot override to '{3}'.",
536
- elementName,
537
- propertyName,
538
- PROP_CONTEXTS[key],
539
- ctx,
540
- );
541
- }
542
-
543
- PROP_CONTEXTS[key] = ctx;
544
- return this;
545
- };
546
-
547
- /* Default property contexts.
548
- *
549
- * Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58
550
- * Changing:
551
- * - SecurityContext.* => SCE_CONTEXTS/$sce.*
552
- * - STYLE => CSS
553
- * - various URL => MEDIA_URL
554
- * - *|formAction, form|action URL => RESOURCE_URL (like the attribute)
555
- */
556
- (function registerNativePropertyContexts() {
557
- function registerContext(ctx, values) {
558
- values.forEach((v) => {
559
- PROP_CONTEXTS[v.toLowerCase()] = ctx;
560
- });
561
- }
562
-
563
- registerContext(SCE_CONTEXTS.HTML, [
564
- "iframe|srcdoc",
565
- "*|innerHTML",
566
- "*|outerHTML",
567
- ]);
568
- registerContext(SCE_CONTEXTS.CSS, ["*|style"]);
569
- registerContext(SCE_CONTEXTS.URL, [
570
- "area|href",
571
- "area|ping",
572
- "a|href",
573
- "a|ping",
574
- "blockquote|cite",
575
- "body|background",
576
- "del|cite",
577
- "input|src",
578
- "ins|cite",
579
- "q|cite",
580
- ]);
581
- registerContext(SCE_CONTEXTS.MEDIA_URL, [
582
- "audio|src",
583
- "img|src",
584
- "img|srcset",
585
- "source|src",
586
- "source|srcset",
587
- "track|src",
588
- "video|src",
589
- "video|poster",
590
- ]);
591
- registerContext(SCE_CONTEXTS.RESOURCE_URL, [
592
- "*|formAction",
593
- "applet|code",
594
- "applet|codebase",
595
- "base|href",
596
- "embed|src",
597
- "frame|src",
598
- "form|action",
599
- "head|profile",
600
- "html|manifest",
601
- "iframe|src",
602
- "link|href",
603
- "media|src",
604
- "object|codebase",
605
- "object|data",
606
- "script|src",
607
- ]);
608
- })();
609
-
610
- this.$get = [
611
- "$injector",
612
- "$interpolate",
613
- "$exceptionHandler",
614
- "$templateRequest",
615
- "$parse",
616
- "$controller",
617
- "$rootScope",
618
- "$sce",
619
- "$animate",
620
- /**
621
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
622
- * @param {*} $interpolate
623
- * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
624
- * @param {*} $templateRequest
625
- * @param {import("../parse/interface.ts").ParseService} $parse
626
- * @param {*} $controller
627
- * @param {import('../scope/scope.js').Scope} $rootScope
628
- * @param {*} $sce
629
- * @param {*} $animate
630
- * @returns
631
- */
632
- function (
633
- $injector,
634
- $interpolate,
635
- $exceptionHandler,
636
- $templateRequest,
637
- $parse,
638
- $controller,
639
- $rootScope,
640
- $sce,
641
- $animate,
642
- ) {
643
- // The onChanges hooks should all be run together in a single digest
644
- // When changes occur, the call to trigger their hooks will be added to this queue
645
- let onChangesQueue;
646
-
647
- // This function is called in a $postUpdate to trigger all the onChanges hooks in a single digest
648
- function flushOnChangesQueue() {
649
- for (let i = 0, ii = onChangesQueue.length; i < ii; ++i) {
650
- try {
651
- onChangesQueue[i]();
652
- } catch (e) {
653
- $exceptionHandler(e);
654
- }
655
- }
656
- // Reset the queue to trigger a new schedule next time there is a change
657
- onChangesQueue = undefined;
658
- }
659
-
660
- const startSymbol = $interpolate.startSymbol();
661
- const endSymbol = $interpolate.endSymbol();
662
- /** @type {(string) => string} */
663
- const denormalizeTemplate =
664
- startSymbol === "{{" && endSymbol === "}}"
665
- ? (x) => x
666
- : (x) => x.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
667
-
668
- const NG_PREFIX_BINDING = /^ng(Attr|Prop|On|Observe)([A-Z].*)$/;
669
- return compile;
670
-
671
- //= ===============================
672
- /**
673
- * @type {CompileFn}
674
- */
675
- function compile(
676
- element,
677
- transcludeFn,
678
- maxPriority,
679
- ignoreDirective,
680
- previousCompileContext,
681
- ) {
682
- /** @type {NodeRef | null } */
683
- let nodeRef = new NodeRef(element);
684
- /**
685
- * The composite link function is a composite of individual node linking functions.
686
- * It will be invoke by the public link function below.
687
- * @type {CompositeLinkFn}
688
- */
689
- let compositeLinkFn = compileNodes(
690
- nodeRef,
691
- transcludeFn,
692
- maxPriority,
693
- ignoreDirective,
694
- previousCompileContext,
695
- );
696
-
697
- let namespace = null;
698
- return publicLinkFn;
699
-
700
- /** @type {PublicLinkFn} */
701
- function publicLinkFn(scope, cloneConnectFn, options) {
702
- if (!nodeRef) {
703
- throw $compileMinErr(
704
- "multilink",
705
- "This element has already been linked.",
706
- );
707
- }
708
-
709
- assertArg(scope, "scope");
710
- // could be empty nodelist
711
- if (nodeRef.getAny()) {
712
- setScope(nodeRef.getAny(), scope);
713
- }
714
-
715
- if (
716
- previousCompileContext &&
717
- previousCompileContext.needsNewScope
718
- ) {
719
- // A parent directive did a replace and a directive on this element asked
720
- // for transclusion, which caused us to lose a layer of element on which
721
- // we could hold the new transclusion scope, so we will create it manually
722
- // here.
723
- scope = scope.$parent.$new();
724
- }
725
-
726
- options = options || {};
727
- let {
728
- transcludeControllers,
729
- parentBoundTranscludeFn,
730
- futureParentElement,
731
- } = options;
732
-
733
- // When `parentBoundTranscludeFn` is passed, it is a
734
- // `controllersBoundTransclude` function (it was previously passed
735
- // as `transclude` to directive.link) so we must unwrap it to get
736
- // its `boundTranscludeFn`
737
- if (
738
- parentBoundTranscludeFn &&
739
- parentBoundTranscludeFn.$$boundTransclude
740
- ) {
741
- parentBoundTranscludeFn =
742
- parentBoundTranscludeFn.$$boundTransclude;
743
- }
744
-
745
- if (!namespace) {
746
- namespace = detectNamespaceForChildElements(futureParentElement);
747
- }
748
- /** @type {NodeRef} */
749
- let $linkNode;
750
-
751
- if (namespace !== "html") {
752
- // When using a directive with replace:true and templateUrl the jqCompileNodes
753
- // (or a child element inside of them)
754
- // might change, so we need to recreate the namespace adapted compileNodes
755
- // for call to the link function.
756
- // Note: This will already clone the nodes...
757
- const fragment = createElementFromHTML("<div></div>");
758
- fragment.append(nodeRef.node);
759
- const wrappedTemplate = wrapTemplate(
760
- namespace,
761
- fragment.innerHTML,
762
- );
763
- $linkNode = new NodeRef(wrappedTemplate[0]);
764
- } else if (cloneConnectFn) {
765
- $linkNode = nodeRef.clone();
766
- } else {
767
- $linkNode = nodeRef;
768
- }
769
-
770
- if (transcludeControllers) {
771
- for (const controllerName in transcludeControllers) {
772
- assertArg($linkNode.element, "element");
773
- setCacheData(
774
- $linkNode.element,
775
- `$${controllerName}Controller`,
776
- transcludeControllers[controllerName].instance,
777
- );
778
- }
779
- }
780
- if (cloneConnectFn) {
781
- cloneConnectFn($linkNode.dom, scope);
782
- }
783
-
784
- if (compositeLinkFn) {
785
- compositeLinkFn(scope, $linkNode, parentBoundTranscludeFn);
786
- }
787
-
788
- if (!cloneConnectFn) {
789
- nodeRef = compositeLinkFn = null;
790
- }
791
-
792
- $linkNode.linked = true;
793
-
794
- return $linkNode.getAll();
795
- }
796
- }
797
-
798
- function detectNamespaceForChildElements(parentElement) {
799
- // TODO: Make this detect MathML as well...
800
- const node = parentElement;
801
- if (!node) {
802
- return "html";
803
- }
804
- return getNodeName(node) !== "foreignobject" &&
805
- toString.call(node).match(/SVG/)
806
- ? "svg"
807
- : "html";
808
- }
809
-
810
- /**
811
- * Compile function matches each node in nodeList against the directives. Once all directives
812
- * for a particular node are collected their compile functions are executed. The compile
813
- * functions return values - the linking functions - are combined into a composite linking
814
- * function, which is a linking function for the node.
815
- *
816
- * @param {NodeRef} nodeRefList a node or an array of nodes or NodeList to compile
817
- * @param {*} transcludeFn A linking function, where the
818
- * scope argument is auto-generated to the new child of the transcluded parent scope.
819
- * @param {number=} [maxPriority] Max directive priority.
820
- * @param {*} [ignoreDirective]
821
- * @param {*} [previousCompileContext]
822
- * @returns {CompositeLinkFn} A composite linking function of all of the matched directives or null.
823
- */
824
- function compileNodes(
825
- nodeRefList,
826
- transcludeFn,
827
- maxPriority,
828
- ignoreDirective,
829
- previousCompileContext,
830
- ) {
831
- /**
832
- * Aggregates for the composite linking function, where a node in a node list is mapped
833
- * to a corresponding link function. For single elements, the node should be mapped to
834
- * a single node link function.
835
- * @type {LinkFnMapping[]}
836
- */
837
- const linkFnsList = []; // An array to hold node indices and their linkFns
838
- let nodeLinkFnFound;
839
- let linkFnFound = false;
840
- for (let i = 0; i < nodeRefList.size; i++) {
841
- const attrs = new Attributes(
842
- $rootScope,
843
- $animate,
844
- $exceptionHandler,
845
- $sce,
846
- );
847
-
848
- const directives = collectDirectives(
849
- /** @type Element */ (nodeRefList.getIndex(i)),
850
- attrs,
851
- i === 0 ? maxPriority : undefined,
852
- ignoreDirective,
853
- );
854
-
855
- /** @type {NodeLinkFnCtx} */
856
- let nodeLinkFnCtx;
857
-
858
- if (directives.length) {
859
- nodeLinkFnCtx = applyDirectivesToNode(
860
- directives,
861
- nodeRefList.getIndex(i),
862
- attrs,
863
- transcludeFn,
864
- null,
865
- [],
866
- [],
867
- Object.assign({}, previousCompileContext, {
868
- index: i,
869
- parentNodeRef: nodeRefList,
870
- ctxNodeRef: nodeRefList,
871
- }),
872
- );
873
- }
874
-
875
- let childLinkFn;
876
- let childNodes;
877
- let nodeLinkFn = nodeLinkFnCtx?.nodeLinkFn;
878
- if (
879
- (nodeLinkFn && nodeLinkFnCtx.terminal) ||
880
- !(childNodes = nodeRefList.getIndex(i).childNodes) ||
881
- !childNodes.length
882
- ) {
883
- childLinkFn = null;
884
- } else {
885
- let transcluded = nodeLinkFn
886
- ? (nodeLinkFnCtx.transcludeOnThisElement ||
887
- !nodeLinkFnCtx.templateOnThisElement) &&
888
- nodeLinkFnCtx.transclude
889
- : transcludeFn;
890
- // recursive call
891
- const childNodeRef = new NodeRef(childNodes);
892
- childLinkFn = compileNodes(childNodeRef, transcluded);
893
- }
894
-
895
- if (nodeLinkFn || childLinkFn) {
896
- linkFnsList.push({
897
- index: i,
898
- nodeLinkFnCtx: nodeLinkFnCtx,
899
- childLinkFn: childLinkFn,
900
- });
901
- linkFnFound = true;
902
- nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
903
- }
904
-
905
- // use the previous context only for the first element in the virtual group
906
- previousCompileContext = null;
907
- }
908
-
909
- // return a composite linking function if we have found anything, null otherwise
910
- return linkFnFound ? compositeLinkFn : null;
911
-
912
- /**
913
- * The composite link function links all the individual nodes
914
- *
915
- * @param {import("../scope/scope.js").Scope} scope
916
- * @param {NodeRef} nodeRef
917
- * @param {*} [parentBoundTranscludeFn]
918
- */
919
- function compositeLinkFn(scope, nodeRef, parentBoundTranscludeFn) {
920
- assertArg(nodeRef, "nodeRef");
921
- let stableNodeList = [];
922
- if (nodeLinkFnFound) {
923
- // create a stable copy of the nodeList, only copying elements with linkFns
924
- const stableLength = nodeRef.isList ? nodeRef.nodes.length : 1;
925
- stableNodeList = new Array(stableLength);
926
- // create a sparse array by only copying the elements which have a linkFn
927
- linkFnsList.forEach((val) => {
928
- let idx = val.index;
929
- if (idx === 0) {
930
- stableNodeList[idx] = nodeRef.isList
931
- ? nodeRef.nodes[idx]
932
- : nodeRef.node;
933
- } else {
934
- if (nodeRefList.getIndex(idx)) {
935
- stableNodeList[idx] = nodeRef.nodes[idx];
936
- }
937
- }
938
- });
939
- } else {
940
- if (nodeRef.isList) {
941
- nodeRef.nodes.forEach((elem) => stableNodeList.push(elem));
942
- } else {
943
- stableNodeList.push(nodeRef.node);
944
- }
945
- }
946
-
947
- linkFnsList.forEach(({ index, nodeLinkFnCtx, childLinkFn }) => {
948
- const node = stableNodeList[index];
949
- node.stable = true;
950
- let childScope;
951
- let childBoundTranscludeFn;
952
-
953
- if (nodeLinkFnCtx?.nodeLinkFn) {
954
- childScope = nodeLinkFnCtx.newScope ? scope.$new() : scope;
955
-
956
- if (nodeLinkFnCtx.transcludeOnThisElement) {
957
- // bind proper scope for the translusion function
958
- childBoundTranscludeFn = createBoundTranscludeFn(
959
- scope,
960
- nodeLinkFnCtx.transclude,
961
- parentBoundTranscludeFn,
962
- );
963
- } else if (
964
- !nodeLinkFnCtx.templateOnThisElement &&
965
- parentBoundTranscludeFn
966
- ) {
967
- childBoundTranscludeFn = parentBoundTranscludeFn;
968
- } else if (!parentBoundTranscludeFn && transcludeFn) {
969
- childBoundTranscludeFn = createBoundTranscludeFn(
970
- scope,
971
- transcludeFn,
972
- );
973
- } else {
974
- childBoundTranscludeFn = null;
975
- }
976
-
977
- // attach new scope to element
978
- if (nodeLinkFnCtx?.newScope) {
979
- setScope(node, childScope);
980
- }
981
- // @ts-ignore
982
- nodeLinkFnCtx.nodeLinkFn(
983
- // @ts-ignore
984
- childLinkFn,
985
- childScope,
986
- node,
987
- childBoundTranscludeFn,
988
- );
989
- } else if (childLinkFn) {
990
- childLinkFn(
991
- scope,
992
- new NodeRef(node.childNodes),
993
- parentBoundTranscludeFn,
994
- );
995
- }
996
- });
997
- }
998
- }
999
-
1000
- /**
1001
- * Prebinds the transclusion function to a scope
1002
- * @param {import("../scope/scope.js").Scope} scope
1003
- * @param {*} transcludeFn
1004
- * @param {*} previousBoundTranscludeFn
1005
- * @returns {BoundTranscludeFn}
1006
- */
1007
- function createBoundTranscludeFn(
1008
- scope,
1009
- transcludeFn,
1010
- previousBoundTranscludeFn,
1011
- ) {
1012
- function boundTranscludeFn(
1013
- transcludedScope,
1014
- cloneFn,
1015
- controllers,
1016
- futureParentElement,
1017
- containingScope,
1018
- ) {
1019
- if (!transcludedScope) {
1020
- transcludedScope = scope.$transcluded(containingScope);
1021
- transcludedScope.$$transcluded = true;
1022
- }
1023
-
1024
- const transcludeRes = transcludeFn(transcludedScope, cloneFn, {
1025
- parentBoundTranscludeFn: previousBoundTranscludeFn,
1026
- transcludeControllers: controllers,
1027
- futureParentElement,
1028
- });
1029
-
1030
- return transcludeRes;
1031
- }
1032
-
1033
- // We need to attach the transclusion slots onto the `boundTranscludeFn`
1034
- // so that they are available inside the `controllersBoundTransclude` function
1035
- const boundSlots = (boundTranscludeFn.$$slots = Object.create(null));
1036
- for (const slotName in transcludeFn.$$slots) {
1037
- if (transcludeFn.$$slots[slotName]) {
1038
- boundSlots[slotName] = createBoundTranscludeFn(
1039
- scope,
1040
- transcludeFn.$$slots[slotName],
1041
- previousBoundTranscludeFn,
1042
- );
1043
- } else {
1044
- boundSlots[slotName] = null;
1045
- }
1046
- }
1047
-
1048
- return boundTranscludeFn;
1049
- }
1050
-
1051
- /**
1052
- * Looks for directives on the given node and adds them to the directive collection which is
1053
- * sorted.
1054
- *
1055
- * @param {Element} node Node to search.
1056
- * @param {Attributes|any} attrs The shared attrs object which is used to populate the normalized attributes.
1057
- * @param {number=} maxPriority Max directive priority.
1058
- * @param {string} [ignoreDirective]
1059
- * @return {import('../../interface.ts').Directive[]} An array to which the directives are added to. This array is sorted before the function returns.
1060
- */
1061
- function collectDirectives(node, attrs, maxPriority, ignoreDirective) {
1062
- /**
1063
- * @type {import('../../interface.ts').Directive[]}
1064
- */
1065
- const directives = [];
1066
- const { nodeType } = node;
1067
- const attrsMap = attrs.$attr;
1068
- let nodeName;
1069
-
1070
- switch (nodeType) {
1071
- case Node.ELEMENT_NODE /* Element */:
1072
- nodeName = node.nodeName.toLowerCase();
1073
- if (ignoreDirective !== directiveNormalize(nodeName)) {
1074
- // use the node name: <directive>
1075
- addDirective(
1076
- directives,
1077
- directiveNormalize(nodeName),
1078
- "E",
1079
- maxPriority,
1080
- );
1081
- }
1082
-
1083
- // iterate over the attributes
1084
- for (let j = 0; j < node.attributes?.length; j++) {
1085
- let isNgAttr = false;
1086
- let isNgProp = false;
1087
- let isNgEvent = false;
1088
- let isNgObserve = false;
1089
-
1090
- let attr = node.attributes[j];
1091
- let name = attr.name;
1092
- let value = attr.value;
1093
- let nName = directiveNormalize(name.toLowerCase());
1094
-
1095
- // Support ng-attr-*, ng-prop-* and ng-on-*
1096
- const ngPrefixMatch = nName.match(NG_PREFIX_BINDING);
1097
- if (ngPrefixMatch) {
1098
- isNgAttr = ngPrefixMatch[1] === "Attr";
1099
- isNgProp = ngPrefixMatch[1] === "Prop";
1100
- isNgEvent = ngPrefixMatch[1] === "On";
1101
- isNgObserve = ngPrefixMatch[1] === "Observe";
1102
-
1103
- // Normalize the non-prefixed name
1104
- name = name
1105
- .replace(PREFIX_REGEXP, "")
1106
- .toLowerCase()
1107
- .substring(4 + ngPrefixMatch[1].length)
1108
- .replace(/_(.)/g, (match, letter) => letter.toUpperCase());
1109
- }
1110
-
1111
- if (isNgProp || isNgEvent) {
1112
- attrs[nName] = value;
1113
- attrsMap[nName] = attr.name;
1114
-
1115
- if (isNgProp) {
1116
- addPropertyDirective(node, directives, nName, name);
1117
- } else {
1118
- directives.push(
1119
- createEventDirective(
1120
- $parse,
1121
- $exceptionHandler,
1122
- nName,
1123
- name,
1124
- ),
1125
- );
1126
- }
1127
- } else if (isNgObserve) {
1128
- directives.push(ngObserveDirective(name, value));
1129
- } else {
1130
- // Update nName for cases where a prefix was removed
1131
- // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-*
1132
- nName = directiveNormalize(name.toLowerCase());
1133
- attrsMap[nName] = name;
1134
-
1135
- if (isNgAttr || !hasOwn(attrs, nName)) {
1136
- attrs[nName] = value;
1137
- if (getBooleanAttrName(node, nName)) {
1138
- attrs[nName] = true; // presence means true
1139
- }
1140
- }
1141
-
1142
- addAttrInterpolateDirective(
1143
- node,
1144
- directives,
1145
- value,
1146
- nName,
1147
- isNgAttr,
1148
- );
1149
-
1150
- if (nName !== ignoreDirective) {
1151
- addDirective(directives, nName, "A", maxPriority);
1152
- }
1153
- }
1154
- }
1155
-
1156
- if (
1157
- nodeName === "input" &&
1158
- node.getAttribute("type") === "hidden"
1159
- ) {
1160
- // Hidden input elements can have strange behaviour when navigating back to the page
1161
- // This tells the browser not to try to cache and reinstate previous values
1162
- node.setAttribute("autocomplete", "off");
1163
- }
1164
-
1165
- break;
1166
- case Node.TEXT_NODE:
1167
- addTextInterpolateDirective(directives, node.nodeValue);
1168
- break;
1169
- default:
1170
- break;
1171
- }
1172
-
1173
- directives.sort(byPriority);
1174
- return directives;
1175
- }
1176
-
1177
- /**
1178
- * A function generator that is used to support both eager and lazy compilation
1179
- * linking function.
1180
- * @param eager
1181
- * @param {NodeList|Node} compileNodes
1182
- * @param transcludeFn
1183
- * @param maxPriority
1184
- * @param ignoreDirective
1185
- * @param previousCompileContext
1186
- * @returns {PublicLinkFn|TranscludeFn}
1187
- */
1188
- function compilationGenerator(
1189
- eager,
1190
- compileNodes,
1191
- transcludeFn,
1192
- maxPriority,
1193
- ignoreDirective,
1194
- previousCompileContext,
1195
- ) {
1196
- let compiled;
1197
- if (eager) {
1198
- return compile(
1199
- compileNodes,
1200
- transcludeFn,
1201
- maxPriority,
1202
- ignoreDirective,
1203
- previousCompileContext,
1204
- );
1205
- }
1206
-
1207
- return function lazyCompilation() {
1208
- if (!compiled) {
1209
- compiled = compile(
1210
- compileNodes,
1211
- transcludeFn,
1212
- maxPriority,
1213
- ignoreDirective,
1214
- previousCompileContext,
1215
- );
1216
-
1217
- // Null out all of these references for garbage collection
1218
- compileNodes = transcludeFn = previousCompileContext = null;
1219
- }
1220
- return compiled.apply(this, arguments);
1221
- };
1222
- }
1223
-
1224
- /**
1225
- * Once the directives have been collected, their compile functions are executed. This method
1226
- * is responsible for inlining directive templates as well as terminating the application
1227
- * of the directives if the terminal directive has been reached.
1228
- *
1229
- * @param {Array} directives Array of collected directives to execute their compile function.
1230
- * this needs to be pre-sorted by priority order.
1231
- * @param {Node | Element} compileNode DOM node to apply the compile functions to
1232
- * @param {Attributes} templateAttrs The shared attribute function
1233
- * @param {TranscludeFn} transcludeFn
1234
- * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
1235
- * compiling the transclusion.
1236
- * @param {Array.<Function>} [preLinkFns]
1237
- * @param {Array.<Function>} [postLinkFns]
1238
- * @param {Object} [previousCompileContext] Context used for previous compilation of the current
1239
- * node
1240
- * @returns {NodeLinkFnCtx} node link function
1241
- */
1242
- function applyDirectivesToNode(
1243
- directives,
1244
- compileNode,
1245
- templateAttrs,
1246
- transcludeFn,
1247
- originalReplaceDirective,
1248
- preLinkFns,
1249
- postLinkFns,
1250
- previousCompileContext,
1251
- ) {
1252
- previousCompileContext = previousCompileContext || {};
1253
-
1254
- let terminalPriority = -Number.MAX_VALUE;
1255
- let terminal = false;
1256
- let {
1257
- newScopeDirective,
1258
- controllerDirectives,
1259
- newIsolateScopeDirective,
1260
- templateDirective,
1261
- nonTlbTranscludeDirective,
1262
- hasElementTranscludeDirective,
1263
- ctxNodeRef,
1264
- parentNodeRef,
1265
- } = previousCompileContext;
1266
- let hasTranscludeDirective = false;
1267
- let hasTemplate = false;
1268
- let compileNodeRef = new NodeRef(compileNode);
1269
- const index = previousCompileContext.index;
1270
- templateAttrs.$nodeRef = compileNodeRef;
1271
- let directive;
1272
- let directiveName;
1273
- let $template;
1274
- let replaceDirective = originalReplaceDirective;
1275
- /** @type {TranscludeFn} */
1276
- let childTranscludeFn = transcludeFn;
1277
-
1278
- let didScanForMultipleTransclusion = false;
1279
- let mightHaveMultipleTransclusionError = false;
1280
- let directiveValue;
1281
-
1282
- /**
1283
- * Links all the directives of a single node.
1284
- * @type {NodeLinkFn}
1285
- */
1286
- // @ts-ignore
1287
- let nodeLinkFn = function (
1288
- childLinkFn,
1289
- scope,
1290
- linkNode,
1291
- boundTranscludeFn,
1292
- ) {
1293
- let i;
1294
- let ii;
1295
- let isolateScope;
1296
- let controllerScope;
1297
- let elementControllers;
1298
- let transcludeFn;
1299
- let scopeToChild = scope;
1300
-
1301
- /** @type {NodeRef} */
1302
- let $element;
1303
- /** @type {Attributes} */
1304
- let attrs;
1305
- let scopeBindingInfo;
1306
-
1307
- if (compileNode === linkNode) {
1308
- attrs = templateAttrs;
1309
- $element = templateAttrs.$nodeRef;
1310
- } else {
1311
- $element = new NodeRef(linkNode);
1312
- attrs = new Attributes(
1313
- $rootScope,
1314
- $animate,
1315
- $exceptionHandler,
1316
- $sce,
1317
- $element,
1318
- templateAttrs,
1319
- );
1320
- }
1321
-
1322
- controllerScope = scope;
1323
- if (newIsolateScopeDirective) {
1324
- isolateScope = scope.$newIsolate();
1325
- } else if (newScopeDirective) {
1326
- controllerScope = scope.$parent;
1327
- }
1328
-
1329
- if (boundTranscludeFn) {
1330
- // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
1331
- // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
1332
- transcludeFn = controllersBoundTransclude;
1333
- transcludeFn["$$boundTransclude"] = boundTranscludeFn;
1334
- // expose the slots on the `$transclude` function
1335
- transcludeFn["isSlotFilled"] = function (slotName) {
1336
- return !!boundTranscludeFn.$$slots[slotName];
1337
- };
1338
- }
1339
-
1340
- if (controllerDirectives) {
1341
- elementControllers = setupControllers(
1342
- $element,
1343
- attrs,
1344
- transcludeFn,
1345
- controllerDirectives,
1346
- isolateScope,
1347
- scope,
1348
- newIsolateScopeDirective,
1349
- );
1350
- }
1351
-
1352
- if (newIsolateScopeDirective) {
1353
- isolateScope.$target.$$isolateBindings =
1354
- newIsolateScopeDirective.$$isolateBindings;
1355
- scopeBindingInfo = initializeDirectiveBindings(
1356
- scope,
1357
- attrs,
1358
- isolateScope,
1359
- isolateScope.$$isolateBindings,
1360
- newIsolateScopeDirective,
1361
- );
1362
- if (scopeBindingInfo.removeWatches) {
1363
- isolateScope.$on("$destroy", scopeBindingInfo.removeWatches);
1364
- }
1365
- }
1366
-
1367
- // Initialize bindToController bindings
1368
- for (const name in elementControllers) {
1369
- const controllerDirective = controllerDirectives[name];
1370
- const controller = elementControllers[name];
1371
- const bindings = controllerDirective.$$bindings.bindToController;
1372
-
1373
- // Controller instance is bound to the scope
1374
- const controllerInstance = controller();
1375
- controller.instance = controllerScope.$new(controllerInstance);
1376
- setCacheData(
1377
- $element.node,
1378
- `$${controllerDirective.name}Controller`,
1379
- controller.instance,
1380
- );
1381
- controller.bindingInfo = initializeDirectiveBindings(
1382
- controllerScope,
1383
- attrs,
1384
- controller.instance,
1385
- bindings,
1386
- controllerDirective,
1387
- );
1388
- }
1389
-
1390
- // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
1391
- if (controllerDirectives) {
1392
- Object.entries(controllerDirectives).forEach(
1393
- ([name, controllerDirective]) => {
1394
- const { require } = controllerDirective;
1395
- if (
1396
- controllerDirective.bindToController &&
1397
- !Array.isArray(require) &&
1398
- isObject(require)
1399
- ) {
1400
- extend(
1401
- elementControllers[name].instance,
1402
- getControllers(
1403
- name,
1404
- require,
1405
- $element.element,
1406
- elementControllers,
1407
- ),
1408
- );
1409
- }
1410
- },
1411
- );
1412
- }
1413
-
1414
- // Handle the init and destroy lifecycle hooks on all controllers that have them
1415
- if (elementControllers) {
1416
- Object.values(elementControllers).forEach((controller) => {
1417
- const controllerInstance = controller.instance;
1418
- if (isFunction(controllerInstance.$onChanges)) {
1419
- try {
1420
- controllerInstance.$onChanges(
1421
- controller.bindingInfo.initialChanges,
1422
- );
1423
- } catch (e) {
1424
- $exceptionHandler(e);
1425
- }
1426
- }
1427
- if (isFunction(controllerInstance.$onInit)) {
1428
- try {
1429
- controllerInstance.$target.$onInit();
1430
- } catch (e) {
1431
- $exceptionHandler(e);
1432
- }
1433
- }
1434
- if (isFunction(controllerInstance.$onDestroy)) {
1435
- controllerScope.$on("$destroy", () => {
1436
- controllerInstance.$onDestroy();
1437
- });
1438
- }
1439
- });
1440
- }
1441
-
1442
- // PRELINKING
1443
- for (i = 0, ii = preLinkFns.length; i < ii; i++) {
1444
- let preLinkFn = preLinkFns[i];
1445
- const controllers =
1446
- preLinkFn["require"] &&
1447
- getControllers(
1448
- preLinkFn["directiveName"],
1449
- preLinkFn["require"],
1450
- $element.element,
1451
- elementControllers,
1452
- );
1453
-
1454
- // invoke link function
1455
- try {
1456
- preLinkFn(
1457
- preLinkFn["isolateScope"] ? isolateScope : scope,
1458
- $element.node, // Prelink functions accept a Node
1459
- attrs,
1460
- controllers,
1461
- transcludeFn,
1462
- );
1463
- } catch (e) {
1464
- $exceptionHandler(e, startingTag($element.getAny()));
1465
- }
1466
- }
1467
-
1468
- // RECURSION
1469
- // We only pass the isolate scope, if the isolate directive has a template,
1470
- // otherwise the child elements do not belong to the isolate directive.
1471
-
1472
- if (
1473
- newIsolateScopeDirective &&
1474
- (newIsolateScopeDirective.template ||
1475
- newIsolateScopeDirective.templateUrl === null)
1476
- ) {
1477
- scopeToChild = isolateScope;
1478
- }
1479
- if (
1480
- childLinkFn &&
1481
- linkNode &&
1482
- linkNode.childNodes &&
1483
- linkNode.childNodes.length
1484
- ) {
1485
- childLinkFn(
1486
- scopeToChild,
1487
- new NodeRef(linkNode.childNodes),
1488
- boundTranscludeFn,
1489
- );
1490
- }
1491
- // POSTLINKING
1492
- for (i = postLinkFns.length - 1; i >= 0; i--) {
1493
- let postLinkFn = postLinkFns[i];
1494
- const controllers =
1495
- postLinkFn["require"] &&
1496
- getControllers(
1497
- postLinkFn["directiveName"],
1498
- postLinkFn["require"],
1499
- /** @type {Element} */ ($element.node),
1500
- elementControllers,
1501
- );
1502
-
1503
- // invoke link function
1504
- try {
1505
- if (postLinkFn["isolateScope"]) {
1506
- setIsolateScope($element.element, isolateScope);
1507
- }
1508
-
1509
- postLinkFn(
1510
- postLinkFn["isolateScope"] ? isolateScope : scope,
1511
- $element.node,
1512
- attrs,
1513
- controllers,
1514
- transcludeFn,
1515
- );
1516
- } catch (e) {
1517
- $exceptionHandler(e, startingTag($element.getAny()));
1518
- }
1519
- }
1520
-
1521
- if (elementControllers) {
1522
- // Trigger $postLink lifecycle hooks
1523
- Object.values(elementControllers).forEach((controller) => {
1524
- const controllerInstance = controller.instance;
1525
- if (isFunction(controllerInstance.$postLink)) {
1526
- controllerInstance.$postLink();
1527
- }
1528
- });
1529
- }
1530
-
1531
- // This is the function that is injected as `$transclude` or
1532
- // the fifth parameter to the link function.
1533
- // Example: function link (scope, element, attrs, ctrl, transclude) {}
1534
- // Note: all arguments are optional!
1535
- function controllersBoundTransclude(
1536
- scope,
1537
- cloneAttachFn,
1538
- futureParentElement,
1539
- slotName,
1540
- ) {
1541
- let transcludeControllers;
1542
- // No scope passed in:
1543
- if (!isScope(scope)) {
1544
- slotName = futureParentElement;
1545
- futureParentElement = cloneAttachFn;
1546
- cloneAttachFn = scope;
1547
- scope = undefined;
1548
- }
1549
- if (hasElementTranscludeDirective) {
1550
- transcludeControllers = elementControllers;
1551
- }
1552
- if (!futureParentElement) {
1553
- futureParentElement = hasElementTranscludeDirective
1554
- ? $element.node.parentElement
1555
- : $element.node;
1556
- }
1557
- if (slotName) {
1558
- // slotTranscludeFn can be one of three things:
1559
- // * a transclude function - a filled slot
1560
- // * `null` - an optional slot that was not filled
1561
- // * `undefined` - a slot that was not declared (i.e. invalid)
1562
- const slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
1563
- if (slotTranscludeFn) {
1564
- return slotTranscludeFn(
1565
- scope,
1566
- cloneAttachFn,
1567
- transcludeControllers,
1568
- futureParentElement,
1569
- scopeToChild,
1570
- );
1571
- }
1572
-
1573
- if (isUndefined(slotTranscludeFn)) {
1574
- throw $compileMinErr(
1575
- "noslot",
1576
- 'No parent directive that requires a transclusion with slot name "{0}". ' +
1577
- "Element: {1}",
1578
- slotName,
1579
- startingTag($element.element),
1580
- );
1581
- }
1582
- } else {
1583
- return boundTranscludeFn(
1584
- scope,
1585
- cloneAttachFn,
1586
- transcludeControllers,
1587
- futureParentElement,
1588
- scopeToChild,
1589
- );
1590
- }
1591
- }
1592
- };
1593
-
1594
- // executes all directives on the current element
1595
- for (let i = 0, ii = directives.length; i < ii; i++) {
1596
- directive = directives[i];
1597
- $template = undefined;
1598
-
1599
- if (terminalPriority > directive.priority) {
1600
- break; // prevent further processing of directives
1601
- }
1602
-
1603
- directiveValue = directive.scope;
1604
-
1605
- if (directiveValue) {
1606
- // skip the check for directives with async templates, we'll check the derived sync
1607
- // directive when the template arrives
1608
- if (!directive.templateUrl) {
1609
- if (isObject(directiveValue)) {
1610
- // This directive is trying to add an isolated scope.
1611
- // Check that there is no scope of any kind already
1612
- assertNoDuplicate(
1613
- "new/isolated scope",
1614
- newIsolateScopeDirective || newScopeDirective,
1615
- directive,
1616
- compileNodeRef,
1617
- );
1618
- newIsolateScopeDirective = directive;
1619
- } else {
1620
- // This directive is trying to add a child scope.
1621
- // Check that there is no isolated scope already
1622
- assertNoDuplicate(
1623
- "new/isolated scope",
1624
- newIsolateScopeDirective,
1625
- directive,
1626
- compileNodeRef,
1627
- );
1628
- }
1629
- }
1630
-
1631
- newScopeDirective = newScopeDirective || directive;
1632
- }
1633
-
1634
- directiveName = directive.name;
1635
-
1636
- // If we encounter a condition that can result in transclusion on the directive,
1637
- // then scan ahead in the remaining directives for others that may cause a multiple
1638
- // transclusion error to be thrown during the compilation process. If a matching directive
1639
- // is found, then we know that when we encounter a transcluded directive, we need to eagerly
1640
- // compile the `transclude` function rather than doing it lazily in order to throw
1641
- // exceptions at the correct time
1642
- const hasReplacedTemplate =
1643
- directive.replace &&
1644
- (directive.templateUrl || directive.template);
1645
- const shouldTransclude =
1646
- directive.transclude &&
1647
- !EXCLUDED_DIRECTIVES.includes(directive.name);
1648
- if (
1649
- !didScanForMultipleTransclusion &&
1650
- (hasReplacedTemplate || shouldTransclude)
1651
- ) {
1652
- let candidateDirective;
1653
-
1654
- for (
1655
- let scanningIndex = i + 1;
1656
- (candidateDirective = directives[scanningIndex++]);
1657
-
1658
- ) {
1659
- if (
1660
- (candidateDirective.transclude &&
1661
- !EXCLUDED_DIRECTIVES.includes(candidateDirective.name)) ||
1662
- (candidateDirective.replace &&
1663
- (candidateDirective.templateUrl ||
1664
- candidateDirective.template))
1665
- ) {
1666
- mightHaveMultipleTransclusionError = true;
1667
- break;
1668
- }
1669
- }
1670
-
1671
- didScanForMultipleTransclusion = true;
1672
- }
1673
-
1674
- if (!directive.templateUrl && directive.controller) {
1675
- controllerDirectives =
1676
- controllerDirectives || Object.create(null);
1677
- assertNoDuplicate(
1678
- `'${directiveName}' controller`,
1679
- controllerDirectives[directiveName],
1680
- directive,
1681
- compileNodeRef,
1682
- );
1683
- controllerDirectives[directiveName] = directive;
1684
- }
1685
-
1686
- directiveValue = directive.transclude;
1687
-
1688
- if (directiveValue) {
1689
- hasTranscludeDirective = true;
1690
-
1691
- // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
1692
- // This option should only be used by directives that know how to safely handle element transclusion,
1693
- // where the transcluded nodes are added or replaced after linking.
1694
- if (!EXCLUDED_DIRECTIVES.includes(directive.name)) {
1695
- assertNoDuplicate(
1696
- "transclusion",
1697
- nonTlbTranscludeDirective,
1698
- directive,
1699
- compileNodeRef,
1700
- );
1701
- nonTlbTranscludeDirective = directive;
1702
- }
1703
-
1704
- if (directiveValue === "element") {
1705
- hasElementTranscludeDirective = true;
1706
- terminalPriority = directive.priority;
1707
- $template = compileNodeRef;
1708
- compileNodeRef = new NodeRef(document.createComment(""));
1709
- templateAttrs.$nodeRef = compileNodeRef;
1710
- compileNode = compileNodeRef.node;
1711
- ctxNodeRef.node = compileNode;
1712
- replaceWith(
1713
- new NodeRef($template.getAny()),
1714
- compileNode,
1715
- index,
1716
- );
1717
-
1718
- // @ts-ignore
1719
- childTranscludeFn = compilationGenerator(
1720
- mightHaveMultipleTransclusionError,
1721
- $template.getAny(),
1722
- transcludeFn,
1723
- terminalPriority,
1724
- replaceDirective && replaceDirective.name,
1725
- {
1726
- // Don't pass in:
1727
- // - controllerDirectives - otherwise we'll create duplicates controllers
1728
- // - newIsolateScopeDirective or templateDirective - combining templates with
1729
- // element transclusion doesn't make sense.
1730
- //
1731
- // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
1732
- // on the same element more than once.
1733
- nonTlbTranscludeDirective,
1734
- },
1735
- );
1736
- } else {
1737
- const slots = Object.create(null);
1738
-
1739
- if (!isObject(directiveValue)) {
1740
- //
1741
- // Clone childnodes before clearing contents on transcluded directives
1742
- $template = compileNode.cloneNode(true).childNodes;
1743
- } else {
1744
- // We have transclusion slots,
1745
- // collect them up, compile them and store their transclusion functions
1746
- $template = document.createDocumentFragment();
1747
-
1748
- const slotMap = Object.create(null);
1749
- const filledSlots = Object.create(null);
1750
-
1751
- // Parse the element selectors
1752
- Object.entries(directiveValue).forEach(
1753
- ([slotName, elementSelector]) => {
1754
- // If an element selector starts with a ? then it is optional
1755
- const optional = elementSelector.charAt(0) === "?";
1756
- elementSelector = optional
1757
- ? elementSelector.substring(1)
1758
- : elementSelector;
1759
-
1760
- slotMap[elementSelector] = slotName;
1761
-
1762
- // We explicitly assign `null` since this implies that a slot was defined but not filled.
1763
- // Later when calling boundTransclusion functions with a slot name we only error if the
1764
- // slot is `undefined`
1765
- slots[slotName] = null;
1766
-
1767
- // filledSlots contains `true` for all slots that are either optional or have been
1768
- // filled. This is used to check that we have not missed any required slots
1769
- filledSlots[slotName] = optional;
1770
- },
1771
- );
1772
-
1773
- // Add the matching elements into their slot
1774
- compileNodeRef.element.childNodes.forEach((node) => {
1775
- const slotName =
1776
- slotMap[
1777
- directiveNormalize(
1778
- getNodeName(/** @type {Element} */ (node)),
1779
- )
1780
- ];
1781
- if (slotName) {
1782
- filledSlots[slotName] = true;
1783
- slots[slotName] =
1784
- slots[slotName] || document.createDocumentFragment();
1785
- slots[slotName].appendChild(node);
1786
- } else {
1787
- $template.appendChild(node);
1788
- }
1789
- });
1790
-
1791
- // Check for required slots that were not filled
1792
- Object.entries(filledSlots).forEach(([slotName, filled]) => {
1793
- if (!filled) {
1794
- throw $compileMinErr(
1795
- "reqslot",
1796
- "Required transclusion slot `{0}` was not filled.",
1797
- slotName,
1798
- );
1799
- }
1800
- });
1801
-
1802
- for (const slotName in slots) {
1803
- if (slots[slotName]) {
1804
- // Only define a transclusion function if the slot was filled
1805
- const slotCompileNodes = slots[slotName].childNodes;
1806
- slots[slotName] = compilationGenerator(
1807
- mightHaveMultipleTransclusionError,
1808
- slotCompileNodes,
1809
- transcludeFn,
1810
- );
1811
- }
1812
- }
1813
-
1814
- $template = $template.childNodes;
1815
- }
1816
-
1817
- emptyElement(/** @type {Element} */ (compileNode)); // clear contents on transcluded directives
1818
-
1819
- // lazily compile transcluded template and generate a transcluded link function
1820
- // @ts-ignore
1821
- childTranscludeFn = compilationGenerator(
1822
- mightHaveMultipleTransclusionError,
1823
- $template,
1824
- transcludeFn,
1825
- undefined,
1826
- undefined,
1827
- {
1828
- needsNewScope:
1829
- directive.$$isolateScope || directive.$$newScope,
1830
- },
1831
- );
1832
- childTranscludeFn["$$slots"] = slots;
1833
- }
1834
- }
1835
-
1836
- if (directive.template) {
1837
- hasTemplate = true;
1838
- assertNoDuplicate(
1839
- "template",
1840
- templateDirective,
1841
- directive,
1842
- compileNodeRef,
1843
- );
1844
- templateDirective = directive;
1845
-
1846
- directiveValue = isFunction(directive.template)
1847
- ? directive.template(compileNodeRef.node, templateAttrs)
1848
- : directive.template;
1849
-
1850
- directiveValue = denormalizeTemplate(directiveValue);
1851
- if (directive.replace) {
1852
- replaceDirective = directive;
1853
- if (isTextNode(directiveValue)) {
1854
- $template = [];
1855
- } else {
1856
- $template = removeComments(
1857
- wrapTemplate(
1858
- directive.templateNamespace,
1859
- trim(directiveValue),
1860
- ),
1861
- );
1862
- }
1863
-
1864
- if (isString($template)) {
1865
- $template = Array.from(
1866
- createNodelistFromHTML($template),
1867
- ).filter((x) => x.nodeType === Node.ELEMENT_NODE);
1868
- }
1869
- compileNode = $template[0];
1870
-
1871
- if (
1872
- $template.length !== 1 ||
1873
- compileNode.nodeType !== Node.ELEMENT_NODE
1874
- ) {
1875
- throw $compileMinErr(
1876
- "tplrt",
1877
- "Template for directive '{0}' must have exactly one root element. {1}",
1878
- directiveName,
1879
- "",
1880
- );
1881
- }
1882
-
1883
- replaceWith(compileNodeRef, compileNode);
1884
-
1885
- if (parentNodeRef) {
1886
- parentNodeRef.setIndex(index, compileNode);
1887
- }
1888
-
1889
- const newTemplateAttrs = { $attr: {} };
1890
-
1891
- // combine directives from the original node and from the template:
1892
- // - take the array of directives for this element
1893
- // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
1894
- // - collect directives from the template and sort them by priority
1895
- // - combine directives as: processed + template + unprocessed
1896
- const templateDirectives = collectDirectives(
1897
- /** @type {Element} */ (compileNode),
1898
- newTemplateAttrs,
1899
- );
1900
- const unprocessedDirectives = directives.splice(
1901
- i + 1,
1902
- directives.length - (i + 1),
1903
- );
1904
-
1905
- if (newIsolateScopeDirective || newScopeDirective) {
1906
- // The original directive caused the current element to be replaced but this element
1907
- // also needs to have a new scope, so we need to tell the template directives
1908
- // that they would need to get their scope from further up, if they require transclusion
1909
- markDirectiveScope(
1910
- templateDirectives,
1911
- newIsolateScopeDirective,
1912
- newScopeDirective,
1913
- );
1914
- }
1915
- directives = directives
1916
- .concat(templateDirectives)
1917
- .concat(unprocessedDirectives);
1918
-
1919
- mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
1920
-
1921
- ii = directives.length;
1922
- } else {
1923
- if (compileNodeRef.isElement()) {
1924
- compileNodeRef.element.innerHTML = directiveValue;
1925
- }
1926
- }
1927
- }
1928
-
1929
- if (directive.templateUrl) {
1930
- hasTemplate = true;
1931
- assertNoDuplicate(
1932
- "template",
1933
- templateDirective,
1934
- directive,
1935
- compileNodeRef,
1936
- );
1937
- templateDirective = directive;
1938
-
1939
- if (directive.replace) {
1940
- replaceDirective = directive;
1941
- }
1942
- // @ts-ignore
1943
- nodeLinkFn = compileTemplateUrl(
1944
- directives.splice(i, directives.length - i),
1945
- compileNodeRef,
1946
- templateAttrs,
1947
- /** @type {Element} */ (compileNode),
1948
- hasTranscludeDirective && childTranscludeFn,
1949
- preLinkFns,
1950
- postLinkFns,
1951
- {
1952
- index,
1953
- controllerDirectives,
1954
- newScopeDirective:
1955
- newScopeDirective !== directive && newScopeDirective,
1956
- newIsolateScopeDirective,
1957
- templateDirective,
1958
- nonTlbTranscludeDirective,
1959
- futureParentElement:
1960
- previousCompileContext.futureParentElement,
1961
- },
1962
- );
1963
- ii = directives.length;
1964
- } else if (directive.compile) {
1965
- try {
1966
- /** @type {PublicLinkFn} */
1967
- const linkFn = directive.compile(
1968
- compileNodeRef.getAny(),
1969
- templateAttrs,
1970
- childTranscludeFn,
1971
- );
1972
- const context = directive.$$originalDirective || directive;
1973
- if (isFunction(linkFn)) {
1974
- addLinkFns(null, bind(context, linkFn));
1975
- } else if (linkFn) {
1976
- addLinkFns(
1977
- bind(context, linkFn["pre"]),
1978
- bind(context, linkFn["post"]),
1979
- );
1980
- }
1981
- } catch (e) {
1982
- $exceptionHandler(e, startingTag(compileNodeRef.getAny()));
1983
- }
1984
- }
1985
-
1986
- if (directive.terminal) {
1987
- terminal = true;
1988
- terminalPriority = Math.max(terminalPriority, directive.priority);
1989
- }
1990
- }
1991
-
1992
- previousCompileContext.hasElementTranscludeDirective =
1993
- hasElementTranscludeDirective;
1994
-
1995
- // might be normal or delayed nodeLinkFn depending on if templateUrl is present
1996
- return {
1997
- nodeLinkFn,
1998
- terminal,
1999
- transclude: childTranscludeFn,
2000
- transcludeOnThisElement: hasTranscludeDirective,
2001
- templateOnThisElement: hasTemplate,
2002
- newScope: newScopeDirective && newScopeDirective.scope === true,
2003
- };
2004
-
2005
- /// /////////////////
2006
- function addLinkFns(pre, post) {
2007
- if (pre) {
2008
- pre.require = directive.require;
2009
- pre.directiveName = directiveName;
2010
- if (
2011
- newIsolateScopeDirective === directive ||
2012
- directive.$$isolateScope
2013
- ) {
2014
- pre = cloneAndAnnotateFn(pre, { isolateScope: true });
2015
- }
2016
- preLinkFns.push(pre);
2017
- }
2018
- if (post) {
2019
- post.require = directive.require;
2020
- post.directiveName = directiveName;
2021
- if (
2022
- newIsolateScopeDirective === directive ||
2023
- directive.$$isolateScope
2024
- ) {
2025
- post = cloneAndAnnotateFn(post, { isolateScope: true });
2026
- }
2027
- postLinkFns.push(post);
2028
- }
2029
- }
2030
- }
2031
-
2032
- /**
2033
- *
2034
- * @param {*} directiveName
2035
- * @param {*} require
2036
- * @param {Element} $element
2037
- * @param {*} elementControllers
2038
- * @returns
2039
- */
2040
- function getControllers(
2041
- directiveName,
2042
- require,
2043
- $element,
2044
- elementControllers,
2045
- ) {
2046
- let value;
2047
-
2048
- if (isString(require)) {
2049
- const match = require.match(REQUIRE_PREFIX_REGEXP);
2050
- const name = require.substring(match[0].length);
2051
- const inheritType = match[1] || match[3];
2052
- const optional = match[2] === "?";
2053
-
2054
- // If only parents then start at the parent element
2055
- if (inheritType === "^^") {
2056
- if ($element.parentElement) {
2057
- $element = $element.parentElement;
2058
- } else {
2059
- $element = undefined;
2060
- }
2061
- // Otherwise attempt getting the controller from elementControllers in case
2062
- // the element is transcluded (and has no data) and to avoid .data if possible
2063
- } else {
2064
- value = elementControllers && elementControllers[name];
2065
- value = value && value.instance;
2066
- }
2067
-
2068
- if (!value) {
2069
- const dataName = `$${name}Controller`;
2070
- if (
2071
- inheritType === "^^" &&
2072
- $element &&
2073
- $element.nodeType === Node.DOCUMENT_NODE
2074
- ) {
2075
- // inheritedData() uses the documentElement when it finds the document, so we would
2076
- // require from the element itself.
2077
- value = null;
2078
- } else {
2079
- value = $element
2080
- ? inheritType
2081
- ? getInheritedData($element, dataName)
2082
- : getCacheData($element, dataName)
2083
- : undefined;
2084
- }
2085
- }
2086
- if (!value && !optional) {
2087
- throw $compileMinErr(
2088
- "ctreq",
2089
- "Controller '{0}', required by directive '{1}', can't be found!",
2090
- name,
2091
- directiveName,
2092
- );
2093
- }
2094
- } else if (Array.isArray(require)) {
2095
- value = [];
2096
- for (let i = 0, ii = require.length; i < ii; i++) {
2097
- value[i] = getControllers(
2098
- directiveName,
2099
- require[i],
2100
- $element,
2101
- elementControllers,
2102
- );
2103
- }
2104
- } else if (isObject(require)) {
2105
- value = {};
2106
- Object.entries(require).forEach(([property, controller]) => {
2107
- value[property] = getControllers(
2108
- directiveName,
2109
- controller,
2110
- $element,
2111
- elementControllers,
2112
- );
2113
- });
2114
- }
2115
-
2116
- return value || null;
2117
- }
2118
-
2119
- /**
2120
- * @param {NodeRef} $element
2121
- * @param attrs
2122
- * @param transcludeFn
2123
- * @param controllerDirectives
2124
- * @param isolateScope
2125
- * @param scope
2126
- * @param newIsolateScopeDirective
2127
- * @returns {any}
2128
- */
2129
- function setupControllers(
2130
- $element,
2131
- attrs,
2132
- transcludeFn,
2133
- controllerDirectives,
2134
- isolateScope,
2135
- scope,
2136
- newIsolateScopeDirective,
2137
- ) {
2138
- const elementControllers = Object.create(null);
2139
- for (const controllerKey in controllerDirectives) {
2140
- const directive = controllerDirectives[controllerKey];
2141
- const locals = {
2142
- $scope:
2143
- directive === newIsolateScopeDirective ||
2144
- directive.$$isolateScope
2145
- ? isolateScope
2146
- : scope,
2147
- $element: $element.node,
2148
- $attrs: attrs,
2149
- $transclude: transcludeFn,
2150
- };
2151
-
2152
- let { controller } = directive;
2153
- if (controller === "@") {
2154
- controller = attrs[directive.name];
2155
- }
2156
-
2157
- const controllerInstance = $controller(
2158
- controller,
2159
- locals,
2160
- true,
2161
- directive.controllerAs,
2162
- );
2163
-
2164
- // For directives with element transclusion the element is a comment.
2165
- // In this case .data will not attach any data.
2166
- // Instead, we save the controllers for the element in a local hash and attach to .data
2167
- // later, once we have the actual element.
2168
- elementControllers[directive.name] = controllerInstance;
2169
- if ($element.isElement()) {
2170
- setCacheData(
2171
- $element.element,
2172
- `$${directive.name}Controller`,
2173
- controllerInstance.instance,
2174
- );
2175
- }
2176
- }
2177
- return elementControllers;
2178
- }
2179
-
2180
- // Depending upon the context in which a directive finds itself it might need to have a new isolated
2181
- // or child scope created. For instance:
2182
- // * if the directive has been pulled into a template because another directive with a higher priority
2183
- // asked for element transclusion
2184
- // * if the directive itself asks for transclusion but it is at the root of a template and the original
2185
- // element was replaced. See https://github.com/angular/angular.js/issues/12936
2186
- function markDirectiveScope(directives, isolateScope, newScope) {
2187
- for (let j = 0, jj = directives.length; j < jj; j++) {
2188
- directives[j] = inherit(directives[j], {
2189
- $$isolateScope: isolateScope,
2190
- $$newScope: newScope,
2191
- });
2192
- }
2193
- }
2194
-
2195
- /**
2196
- * looks up the directive and decorates it with exception handling and proper parameters. We
2197
- * call this the boundDirective.
2198
- *
2199
- * @param {string} name name of the directive to look up.
2200
- * @param {string} location The directive must be found in specific format.
2201
- * String containing any of these characters:
2202
- *
2203
- * * `E`: element name
2204
- * * `A': attribute
2205
- * @returns {boolean} true if directive was added.
2206
- */
2207
- function addDirective(tDirectives, name, location, maxPriority) {
2208
- let match = false;
2209
- if (hasOwn(hasDirectives, name)) {
2210
- for (
2211
- let directive,
2212
- directives = $injector.get(name + DirectiveSuffix),
2213
- i = 0,
2214
- ii = directives.length;
2215
- i < ii;
2216
- i++
2217
- ) {
2218
- directive = directives[i];
2219
- if (
2220
- (isUndefined(maxPriority) ||
2221
- maxPriority > directive.priority) &&
2222
- directive.restrict.indexOf(location) !== -1
2223
- ) {
2224
- if (!directive.$$bindings) {
2225
- const bindings = (directive.$$bindings =
2226
- parseDirectiveBindings(directive, directive.name));
2227
- if (isObject(bindings.isolateScope)) {
2228
- directive.$$isolateBindings = bindings.isolateScope;
2229
- }
2230
- }
2231
- tDirectives.push(directive);
2232
- match = directive;
2233
- }
2234
- }
2235
- }
2236
- return match;
2237
- }
2238
-
2239
- /**
2240
- * When the element is replaced with HTML template then the new attributes
2241
- * on the template need to be merged with the existing attributes in the DOM.
2242
- * The desired effect is to have both of the attributes present.
2243
- *
2244
- * @param {object} dst destination attributes (original DOM)
2245
- * @param {object} src source attributes (from the directive template)
2246
- */
2247
- function mergeTemplateAttributes(dst, src) {
2248
- const srcAttr = src.$attr;
2249
- const dstAttr = dst.$attr;
2250
-
2251
- // reapply the old attributes to the new element
2252
- Object.entries(dst).forEach(([key, value]) => {
2253
- if (key.charAt(0) !== "$") {
2254
- if (src[key] && src[key] !== value) {
2255
- if (value.length) {
2256
- value += (key === "style" ? ";" : " ") + src[key];
2257
- } else {
2258
- value = src[key];
2259
- }
2260
- }
2261
- dst.$set(key, value, true, srcAttr[key]);
2262
- }
2263
- });
2264
-
2265
- // copy the new attributes on the old attrs object
2266
- Object.entries(src).forEach(([key, value]) => {
2267
- // Check if we already set this attribute in the loop above.
2268
- // `dst` will never contain hasOwnProperty as DOM parser won't let it.
2269
- // You will get an "InvalidCharacterError: DOM Exception 5" error if you
2270
- // have an attribute like "has-own-property" or "data-has-own-property", etc.
2271
- if (!hasOwn(dst, key) && key.charAt(0) !== "$") {
2272
- dst[key] = value;
2273
-
2274
- if (key !== "class" && key !== "style") {
2275
- dstAttr[key] = srcAttr[key];
2276
- }
2277
- }
2278
- });
2279
- }
2280
-
2281
- /**
2282
- *
2283
- * @param {import("../../interface.ts").Directive[]} directives
2284
- * @param {NodeRef} $compileNode
2285
- * @param {Attributes} tAttrs
2286
- * @param {Element} $rootElement
2287
- * @param {*} childTranscludeFn
2288
- * @param {Array} preLinkFns
2289
- * @param {Array} postLinkFns
2290
- * @param {*} previousCompileContext
2291
- * @returns
2292
- */
2293
- function compileTemplateUrl(
2294
- directives,
2295
- $compileNode,
2296
- tAttrs,
2297
- $rootElement,
2298
- childTranscludeFn,
2299
- preLinkFns,
2300
- postLinkFns,
2301
- previousCompileContext,
2302
- ) {
2303
- let linkQueue = [];
2304
- /** @type {any} */
2305
- let afterTemplateNodeLinkFn;
2306
- let afterTemplateChildLinkFn;
2307
- let afterTemplateNodeLinkFnCtx;
2308
- const beforeTemplateCompileNode = $compileNode.getAny();
2309
- const origAsyncDirective = directives.shift();
2310
- const derivedSyncDirective = inherit(origAsyncDirective, {
2311
- templateUrl: null,
2312
- transclude: null,
2313
- replace: null,
2314
- $$originalDirective: origAsyncDirective,
2315
- });
2316
- const templateUrl = isFunction(origAsyncDirective.templateUrl)
2317
- ? /** @type { ((element: Element, tAttrs: Attributes) => string) } */ (
2318
- origAsyncDirective.templateUrl
2319
- )($compileNode.element, tAttrs)
2320
- : origAsyncDirective.templateUrl;
2321
- const { templateNamespace } = origAsyncDirective;
2322
-
2323
- emptyElement($compileNode.element);
2324
-
2325
- $templateRequest(templateUrl)
2326
- .then((content) => {
2327
- /** @type {Element} */
2328
- let compileNode;
2329
- let tempTemplateAttrs;
2330
- let $template;
2331
- let childBoundTranscludeFn;
2332
-
2333
- content = denormalizeTemplate(content);
2334
-
2335
- if (origAsyncDirective.replace) {
2336
- if (isTextNode(content)) {
2337
- $template = [];
2338
- } else if (isString(content)) {
2339
- $template = Array.from(
2340
- createNodelistFromHTML(content),
2341
- ).filter(
2342
- (node) =>
2343
- node.nodeType !== Node.COMMENT_NODE &&
2344
- node.nodeType !== Node.TEXT_NODE,
2345
- );
2346
- } else {
2347
- $template = removeComments(
2348
- wrapTemplate(templateNamespace, trim(content)),
2349
- );
2350
- }
2351
- compileNode = $template[0];
2352
- if (
2353
- $template.length !== 1 ||
2354
- compileNode.nodeType !== Node.ELEMENT_NODE
2355
- ) {
2356
- throw $compileMinErr(
2357
- "tplrt",
2358
- "Template for directive '{0}' must have exactly one root element. {1}",
2359
- origAsyncDirective.name,
2360
- templateUrl,
2361
- );
2362
- }
2363
-
2364
- tempTemplateAttrs = { $attr: {} };
2365
-
2366
- replaceWith(
2367
- $compileNode,
2368
- compileNode,
2369
- previousCompileContext.index,
2370
- );
2371
-
2372
- const templateDirectives = collectDirectives(
2373
- compileNode,
2374
- tempTemplateAttrs,
2375
- );
2376
-
2377
- if (isObject(origAsyncDirective.scope)) {
2378
- // the original directive that caused the template to be loaded async required
2379
- // an isolate scope
2380
- markDirectiveScope(templateDirectives, true);
2381
- }
2382
- directives = templateDirectives.concat(directives);
2383
-
2384
- mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
2385
- } else {
2386
- compileNode = /** @type {Element} */ (
2387
- beforeTemplateCompileNode
2388
- );
2389
- $compileNode.element.innerHTML = content;
2390
- }
2391
-
2392
- directives.unshift(derivedSyncDirective);
2393
- afterTemplateNodeLinkFnCtx = applyDirectivesToNode(
2394
- directives,
2395
- compileNode,
2396
- tAttrs,
2397
- childTranscludeFn,
2398
- origAsyncDirective,
2399
- preLinkFns,
2400
- postLinkFns,
2401
- { ...previousCompileContext, ctxNodeRef: $compileNode },
2402
- );
2403
-
2404
- afterTemplateNodeLinkFn = afterTemplateNodeLinkFnCtx?.nodeLinkFn;
2405
- if ($rootElement) {
2406
- Object.entries($rootElement).forEach(([i, node]) => {
2407
- if (node === compileNode) {
2408
- $rootElement[i] = $compileNode;
2409
- }
2410
- });
2411
- }
2412
- afterTemplateChildLinkFn = compileNodes(
2413
- new NodeRef($compileNode.getAny().childNodes),
2414
- childTranscludeFn,
2415
- );
2416
-
2417
- while (linkQueue.length) {
2418
- const scope = linkQueue.shift();
2419
- const beforeTemplateLinkNode = linkQueue.shift();
2420
- const boundTranscludeFn = linkQueue.shift();
2421
- let linkNode = $compileNode.getAny();
2422
-
2423
- if (scope.$$destroyed) {
2424
- continue;
2425
- }
2426
-
2427
- if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
2428
- const oldClasses = beforeTemplateLinkNode.className;
2429
-
2430
- if (
2431
- !(
2432
- previousCompileContext.hasElementTranscludeDirective &&
2433
- origAsyncDirective.replace
2434
- )
2435
- ) {
2436
- // it was cloned therefore we have to clone as well.
2437
- linkNode = compileNode.cloneNode(true);
2438
- beforeTemplateLinkNode.appendChild(linkNode);
2439
- }
2440
- // Copy in CSS classes from original node
2441
- try {
2442
- if (oldClasses !== "") {
2443
- $compileNode.element.classList.forEach((cls) =>
2444
- beforeTemplateLinkNode.classList.add(cls),
2445
- );
2446
- }
2447
- } catch {
2448
- // ignore, since it means that we are trying to set class on
2449
- // SVG element, where class name is read-only.
2450
- }
2451
- }
2452
- if (afterTemplateNodeLinkFnCtx.transcludeOnThisElement) {
2453
- childBoundTranscludeFn = createBoundTranscludeFn(
2454
- scope,
2455
- afterTemplateNodeLinkFnCtx.transclude,
2456
- boundTranscludeFn,
2457
- );
2458
- } else {
2459
- childBoundTranscludeFn = boundTranscludeFn;
2460
- }
2461
-
2462
- afterTemplateNodeLinkFn(
2463
- afterTemplateChildLinkFn,
2464
- scope,
2465
- linkNode,
2466
- childBoundTranscludeFn,
2467
- );
2468
- }
2469
- linkQueue = null;
2470
- })
2471
- .catch((error) => {
2472
- if (isError(error)) {
2473
- $exceptionHandler(error);
2474
- } else {
2475
- $exceptionHandler(new Error(error));
2476
- }
2477
- });
2478
-
2479
- return function delayedNodeLinkFn(
2480
- _ignoreChildLinkFn,
2481
- scope,
2482
- node,
2483
- rootElement,
2484
- boundTranscludeFn,
2485
- ) {
2486
- let childBoundTranscludeFn = boundTranscludeFn;
2487
- if (scope.$$destroyed) {
2488
- return;
2489
- }
2490
- if (linkQueue) {
2491
- linkQueue.push(scope, node, rootElement);
2492
- } else {
2493
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
2494
- childBoundTranscludeFn = createBoundTranscludeFn(
2495
- scope,
2496
- afterTemplateNodeLinkFn.transclude,
2497
- boundTranscludeFn,
2498
- );
2499
- }
2500
- afterTemplateNodeLinkFn(
2501
- afterTemplateChildLinkFn,
2502
- scope,
2503
- node,
2504
- rootElement,
2505
- childBoundTranscludeFn,
2506
- );
2507
- }
2508
- };
2509
- }
2510
-
2511
- /**
2512
- * Sorting function for bound directives.
2513
- */
2514
- function byPriority(a, b) {
2515
- const diff = b.priority - a.priority;
2516
- if (diff !== 0) {
2517
- return diff;
2518
- }
2519
- if (a.name !== b.name) {
2520
- return a.name < b.name ? -1 : 1;
2521
- }
2522
- return a.index - b.index;
2523
- }
2524
-
2525
- function assertNoDuplicate(
2526
- what,
2527
- previousDirective,
2528
- directive,
2529
- element,
2530
- ) {
2531
- function wrapModuleNameIfDefined(moduleName) {
2532
- return moduleName ? ` (module: ${moduleName})` : "";
2533
- }
2534
-
2535
- if (previousDirective) {
2536
- throw $compileMinErr(
2537
- "multidir",
2538
- "Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}",
2539
- previousDirective.name,
2540
- wrapModuleNameIfDefined(previousDirective.$$moduleName),
2541
- directive.name,
2542
- wrapModuleNameIfDefined(directive.$$moduleName),
2543
- what,
2544
- startingTag(element.getAny()),
2545
- );
2546
- }
2547
- }
2548
-
2549
- function addTextInterpolateDirective(directives, text) {
2550
- const interpolateFn = $interpolate(text, true);
2551
- if (interpolateFn) {
2552
- directives.push({
2553
- priority: 0,
2554
- compile: () => (scope, node) => {
2555
- interpolateFn.expressions.forEach((x) => {
2556
- scope.$watch(x, () => {
2557
- const res = interpolateFn(
2558
- isProxy(scope) ? scope.$target : scope,
2559
- );
2560
- switch (node.nodeType) {
2561
- case 1:
2562
- node.innerHTML = res;
2563
- break;
2564
- default:
2565
- node.nodeValue = res;
2566
- }
2567
- });
2568
- });
2569
- },
2570
- });
2571
- }
2572
- }
2573
-
2574
- /**
2575
- * @param {string} type
2576
- * @param {string} template
2577
- * @returns
2578
- */
2579
- function wrapTemplate(type, template) {
2580
- type = (type || "html").toLowerCase();
2581
- switch (type) {
2582
- case "svg":
2583
- case "math": {
2584
- const wrapper =
2585
- /** @type {HTMLDivElement} */ document.createElement("div");
2586
- wrapper.innerHTML = `<${type}>${template}</${type}>`;
2587
- return wrapper.childNodes[0].childNodes;
2588
- }
2589
- default:
2590
- return template;
2591
- }
2592
- }
2593
-
2594
- function getTrustedAttrContext(nodeName, attrNormalizedName) {
2595
- if (attrNormalizedName === "srcdoc") {
2596
- return $sce.HTML;
2597
- }
2598
- // All nodes with src attributes require a RESOURCE_URL value, except for
2599
- // img and various html5 media nodes, which require the MEDIA_URL context.
2600
- if (attrNormalizedName === "src" || attrNormalizedName === "ngSrc") {
2601
- if (
2602
- ["img", "video", "audio", "source", "track"].indexOf(nodeName) ===
2603
- -1
2604
- ) {
2605
- return $sce.RESOURCE_URL;
2606
- }
2607
- return $sce.MEDIA_URL;
2608
- }
2609
- if (attrNormalizedName === "xlinkHref") {
2610
- // Some xlink:href are okay, most aren't
2611
- if (nodeName === "image") {
2612
- return $sce.MEDIA_URL;
2613
- }
2614
- if (nodeName === "a") {
2615
- return $sce.URL;
2616
- }
2617
- return $sce.RESOURCE_URL;
2618
- }
2619
- if (
2620
- // Formaction
2621
- (nodeName === "form" && attrNormalizedName === "action") ||
2622
- // If relative URLs can go where they are not expected to, then
2623
- // all sorts of trust issues can arise.
2624
- (nodeName === "base" && attrNormalizedName === "href") ||
2625
- // links can be stylesheets or imports, which can run script in the current origin
2626
- (nodeName === "link" && attrNormalizedName === "href")
2627
- ) {
2628
- return $sce.RESOURCE_URL;
2629
- }
2630
- if (
2631
- nodeName === "a" &&
2632
- (attrNormalizedName === "href" || attrNormalizedName === "ngHref")
2633
- ) {
2634
- return $sce.URL;
2635
- }
2636
- }
2637
-
2638
- function getTrustedPropContext(nodeName, propNormalizedName) {
2639
- const prop = propNormalizedName.toLowerCase();
2640
- return (
2641
- PROP_CONTEXTS[`${nodeName}|${prop}`] || PROP_CONTEXTS[`*|${prop}`]
2642
- );
2643
- }
2644
-
2645
- function sanitizeSrcset(value, invokeType) {
2646
- if (!value) {
2647
- return value;
2648
- }
2649
- if (!isString(value)) {
2650
- throw $compileMinErr(
2651
- "srcset",
2652
- 'Can\'t pass trusted values to `{0}`: "{1}"',
2653
- invokeType,
2654
- value.toString(),
2655
- );
2656
- }
2657
-
2658
- // Such values are a bit too complex to handle automatically inside $sce.
2659
- // Instead, we sanitize each of the URIs individually, which works, even dynamically.
2660
- // It's not possible to work around this using `$sce.trustAsMediaUrl`.
2661
- // If you want to programmatically set explicitly trusted unsafe URLs, you should use
2662
- // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
2663
- // `ng-bind-html` directive.
2664
- let result = "";
2665
-
2666
- // first check if there are spaces because it's not the same pattern
2667
- const trimmedSrcset = trim(value);
2668
- // ( 999x ,| 999w ,| ,|, )
2669
- const srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
2670
- const pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
2671
-
2672
- // split srcset into tuple of uri and descriptor except for the last item
2673
- const rawUris = trimmedSrcset.split(pattern);
2674
-
2675
- // for each tuples
2676
- const nbrUrisWith2parts = Math.floor(rawUris.length / 2);
2677
- let i;
2678
- for (i = 0; i < nbrUrisWith2parts; i++) {
2679
- const innerIdx = i * 2;
2680
- // sanitize the uri
2681
- result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
2682
- // add the descriptor
2683
- result += " " + trim(rawUris[innerIdx + 1]);
2684
- }
2685
-
2686
- // split the last item into uri and descriptor
2687
- const lastTuple = trim(rawUris[i * 2]).split(/\s/);
2688
-
2689
- // sanitize the last uri
2690
- result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));
2691
-
2692
- // and add the last descriptor if any
2693
- if (lastTuple.length === 2) {
2694
- result += " " + trim(lastTuple[1]);
2695
- }
2696
- return result;
2697
- }
2698
-
2699
- function addPropertyDirective(node, directives, attrName, propName) {
2700
- if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) {
2701
- throw $compileMinErr(
2702
- "nodomevents",
2703
- "Property bindings for HTML DOM event properties are disallowed",
2704
- );
2705
- }
2706
-
2707
- const nodeName = getNodeName(node);
2708
- const trustedContext = getTrustedPropContext(nodeName, propName);
2709
-
2710
- let sanitizer = (x) => x;
2711
- // Sanitize img[srcset] + source[srcset] values.
2712
- if (
2713
- propName === "srcset" &&
2714
- (nodeName === "img" || nodeName === "source")
2715
- ) {
2716
- sanitizer = (value) =>
2717
- sanitizeSrcset($sce.valueOf(value), "ng-prop-srcset");
2718
- } else if (trustedContext) {
2719
- sanitizer = $sce.getTrusted.bind($sce, trustedContext);
2720
- }
2721
-
2722
- directives.push({
2723
- priority: 100,
2724
- compile: function ngPropCompileFn(_, attr) {
2725
- const ngPropGetter = $parse(attr[attrName]);
2726
- return {
2727
- pre: function ngPropPreLinkFn(scope, $element) {
2728
- function applyPropValue() {
2729
- const propValue = ngPropGetter(scope);
2730
- $element[propName] = sanitizer(propValue);
2731
- }
2732
-
2733
- applyPropValue();
2734
- scope.$watch(propName, applyPropValue);
2735
- scope.$watch(attr[attrName], (val) => {
2736
- $sce.valueOf(val);
2737
- applyPropValue();
2738
- });
2739
- },
2740
- };
2741
- },
2742
- });
2743
- }
2744
-
2745
- function addAttrInterpolateDirective(
2746
- node,
2747
- directives,
2748
- value,
2749
- name,
2750
- isNgAttr,
2751
- ) {
2752
- const nodeName = getNodeName(node);
2753
- const trustedContext = getTrustedAttrContext(nodeName, name);
2754
- const mustHaveExpression = !isNgAttr;
2755
- const allOrNothing = ALL_OR_NOTHING_ATTRS.includes(name) || isNgAttr;
2756
-
2757
- let interpolateFn = $interpolate(
2758
- value,
2759
- mustHaveExpression,
2760
- trustedContext,
2761
- allOrNothing,
2762
- );
2763
-
2764
- // no interpolation found -> ignore
2765
- if (!interpolateFn) {
2766
- return;
2767
- }
2768
-
2769
- if (name === "multiple" && nodeName === "select") {
2770
- throw $compileMinErr(
2771
- "selmulti",
2772
- "Binding to the 'multiple' attribute is not supported. Element: {0}",
2773
- startingTag(node.outerHTML),
2774
- );
2775
- }
2776
-
2777
- if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
2778
- throw $compileMinErr(
2779
- "nodomevents",
2780
- "Interpolations for HTML DOM event attributes are disallowed",
2781
- );
2782
- }
2783
-
2784
- directives.push({
2785
- priority: 100,
2786
- compile() {
2787
- return {
2788
- pre: function attrInterpolatePreLinkFn(scope, element, attr) {
2789
- const $$observers =
2790
- attr.$$observers ||
2791
- (attr.$$observers = Object.create(null));
2792
-
2793
- // If the attribute has changed since last $interpolate()ed
2794
- const newValue = attr[name];
2795
- if (newValue !== value) {
2796
- // we need to interpolate again since the attribute value has been updated
2797
- // (e.g. by another directive's compile function)
2798
- // ensure unset/empty values make interpolateFn falsy
2799
- interpolateFn =
2800
- newValue &&
2801
- $interpolate(
2802
- newValue,
2803
- true,
2804
- trustedContext,
2805
- allOrNothing,
2806
- );
2807
- value = newValue;
2808
- }
2809
-
2810
- // if attribute was updated so that there is no interpolation going on we don't want to
2811
- // register any observers
2812
- if (!interpolateFn) {
2813
- return;
2814
- }
2815
-
2816
- // initialize attr object so that it's ready in case we need the value for isolate
2817
- // scope initialization, otherwise the value would not be available from isolate
2818
- // directive's linking fn during linking phase
2819
- attr[name] = interpolateFn(scope);
2820
-
2821
- ($$observers[name] || ($$observers[name] = [])).$$inter =
2822
- true;
2823
- interpolateFn.expressions.forEach((x) => {
2824
- const targetScope =
2825
- (attr.$$observers && attr.$$observers[name].$$scope) ||
2826
- scope;
2827
- targetScope.$watch(x, () => {
2828
- let newValue = interpolateFn(scope);
2829
- // special case for class attribute addition + removal
2830
- // so that class changes can tap into the animation
2831
- // hooks provided by the $animate service. Be sure to
2832
- // skip animations when the first digest occurs (when
2833
- // both the new and the old values are the same) since
2834
- // the CSS classes are the non-interpolated values
2835
- if (name === "class") {
2836
- attr.$updateClass(
2837
- newValue,
2838
- attr.$$element.classList.value,
2839
- );
2840
- } else {
2841
- attr.$set(name, newValue);
2842
- }
2843
- });
2844
- });
2845
-
2846
- if (interpolateFn.expressions.length == 0) {
2847
- // if there is nothing to watch, its a constant
2848
- attr.$set(name, newValue);
2849
- }
2850
- },
2851
- };
2852
- },
2853
- });
2854
- }
2855
-
2856
- /**
2857
- *
2858
- * @param {NodeRef} elementsToRemove The JQLite element which we are going to replace. We keep
2859
- * the shell, but replace its DOM node reference.
2860
- * @param {Node} newNode The new DOM node.
2861
- * @param {number} [index] Parent node index.
2862
- */
2863
- function replaceWith(elementsToRemove, newNode, index) {
2864
- const firstElementToRemove = elementsToRemove.getAny();
2865
- // const removeCount = elementsToRemove.length;
2866
- const parent = firstElementToRemove.parentNode;
2867
-
2868
- if (parent) {
2869
- if (isDefined(index)) {
2870
- const oldChild = parent.childNodes[index];
2871
- if (oldChild) {
2872
- parent.replaceChild(newNode, oldChild);
2873
- }
2874
- } else {
2875
- parent.insertBefore(newNode, parent.firstChild);
2876
- //parent.append(newNode);
2877
- }
2878
- }
2879
-
2880
- // Append all the `elementsToRemove` to a fragment. This will...
2881
- // - remove them from the DOM
2882
- // - allow them to still be traversed with .nextSibling
2883
- // - allow a single fragment.qSA to fetch all elements being removed
2884
- const fragment = document.createDocumentFragment();
2885
- elementsToRemove.collection().forEach((element) => {
2886
- fragment.appendChild(element);
2887
- });
2888
-
2889
- elementsToRemove.node = newNode;
2890
- }
2891
-
2892
- function cloneAndAnnotateFn(fn, annotation) {
2893
- return extend(
2894
- function () {
2895
- return fn.apply(null, arguments);
2896
- },
2897
- fn,
2898
- annotation,
2899
- );
2900
- }
2901
-
2902
- function strictBindingsCheck(attrName, directiveName) {
2903
- if (strictComponentBindingsEnabled) {
2904
- throw $compileMinErr(
2905
- "missingattr",
2906
- "Attribute '{0}' of '{1}' is non-optional and must be set!",
2907
- attrName,
2908
- directiveName,
2909
- );
2910
- }
2911
- }
2912
-
2913
- // Set up $watches for isolate scope and controller bindings.
2914
- /**
2915
- *
2916
- * @param {import('../scope/scope.js').Scope} scope
2917
- * @param {*} attrs
2918
- * @param {import('../scope/scope.js').Scope} destination - child scope or isolate scope
2919
- * @param {*} bindings
2920
- * @param {*} directive
2921
- * @returns
2922
- */
2923
- function initializeDirectiveBindings(
2924
- scope,
2925
- attrs,
2926
- destination,
2927
- bindings,
2928
- directive,
2929
- ) {
2930
- const removeWatchCollection = [];
2931
- const initialChanges = {};
2932
- let changes;
2933
-
2934
- if (bindings) {
2935
- Object.entries(bindings).forEach(([scopeName, definition]) => {
2936
- const {
2937
- attrName,
2938
- optional,
2939
- mode, // @, =, <, or &
2940
- } = definition;
2941
- let lastValue;
2942
- let parentGet;
2943
- let parentSet;
2944
- let compare;
2945
- let removeWatch;
2946
- let firstCall = true;
2947
- let firstChange = true;
2948
-
2949
- switch (mode) {
2950
- case "@":
2951
- if (!optional && !hasOwn(attrs, attrName)) {
2952
- strictBindingsCheck(attrName, directive.name);
2953
- destination[scopeName] = attrs[attrName] = undefined;
2954
- }
2955
-
2956
- removeWatch = attrs.$observe(attrName, (value) => {
2957
- if (isString(value) || isBoolean(value)) {
2958
- recordChanges(scopeName, value, firstChange);
2959
-
2960
- destination[scopeName] = value;
2961
- if (firstCall) {
2962
- firstCall = false;
2963
- } else {
2964
- triggerOnChangesHook();
2965
- firstChange = false;
2966
- }
2967
- }
2968
- });
2969
- attrs.$$observers[attrName].$$scope = scope;
2970
- lastValue = attrs[attrName];
2971
- if (isString(lastValue)) {
2972
- // If the attribute has been provided then we trigger an interpolation to ensure
2973
- // the value is there for use in the link fn
2974
- destination[scopeName] = $interpolate(lastValue)(scope);
2975
- } else if (isBoolean(lastValue)) {
2976
- // If the attributes is one of the BOOLEAN_ATTR then AngularTS will have converted
2977
- // the value to boolean rather than a string, so we special case this situation
2978
- destination[scopeName] = lastValue;
2979
- }
2980
-
2981
- /**
2982
- * @type {SimpleChange}
2983
- */
2984
- initialChanges[scopeName] = {
2985
- currentValue: destination[scopeName],
2986
- firstChange: true,
2987
- };
2988
- removeWatchCollection.push(removeWatch);
2989
- break;
2990
-
2991
- case "=": {
2992
- if (!hasOwn(attrs, attrName)) {
2993
- if (optional) {
2994
- break;
2995
- }
2996
- strictBindingsCheck(attrName, directive.name);
2997
- attrs[attrName] = undefined;
2998
- }
2999
- if (optional && !attrs[attrName]) {
3000
- break;
3001
- }
3002
-
3003
- parentGet = $parse(attrs[attrName]);
3004
- if (parentGet.literal) {
3005
- compare = equals;
3006
- } else {
3007
- compare = simpleCompare;
3008
- }
3009
-
3010
- parentSet =
3011
- parentGet.assign ||
3012
- function () {
3013
- // reset the change, or we will throw this exception on every $digest
3014
- lastValue = destination.$target[scopeName] =
3015
- parentGet(scope);
3016
- throw $compileMinErr(
3017
- "nonassign",
3018
- "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
3019
- attrs[attrName],
3020
- attrName,
3021
- directive.name,
3022
- );
3023
- };
3024
- // store the value that the parent scope had after the last check:
3025
- lastValue = destination.$target[scopeName] = parentGet(
3026
- scope.$target,
3027
- );
3028
- const parentValueWatch = function parentValueWatch(
3029
- parentValue,
3030
- ) {
3031
- if (!compare(parentValue, destination[scopeName])) {
3032
- // we are out of sync and need to copy
3033
- if (!compare(parentValue, lastValue)) {
3034
- // parent changed and it has precedence
3035
- destination[scopeName] = parentValue;
3036
- } else {
3037
- // if the parent can be assigned then do so
3038
- parentSet(
3039
- scope,
3040
- (parentValue = destination[scopeName]),
3041
- );
3042
- }
3043
- }
3044
- lastValue = parentValue;
3045
- return lastValue;
3046
- };
3047
- parentValueWatch.$stateful = true;
3048
- if (definition.collection) {
3049
- removeWatch = scope.$watch(
3050
- attrs[attrName],
3051
- parentValueWatch,
3052
- );
3053
- } else {
3054
- if (attrs[attrName]) {
3055
- let expr = attrs[attrName];
3056
- // make it lazy as we dont want to trigger the two way data binding at this point
3057
- scope.$watch(
3058
- expr,
3059
- (val) => {
3060
- const res = $parse(attrs[attrName], parentValueWatch);
3061
- if (val) {
3062
- if (parentGet.literal) {
3063
- scope.$target[attrName] = val;
3064
- } else {
3065
- scope[attrName] = val;
3066
- }
3067
- res(scope);
3068
- } else {
3069
- scope[attrName] = scope[attrs[attrName]];
3070
- }
3071
- },
3072
- true,
3073
- );
3074
- }
3075
-
3076
- removeWatch = destination.$watch(
3077
- attrName,
3078
- (val) => {
3079
- if (
3080
- val === lastValue &&
3081
- !isUndefined(attrs[attrName])
3082
- ) {
3083
- return;
3084
- }
3085
- if (
3086
- (!!parentGet.inputs && !parentGet.literal) ||
3087
- (isUndefined(attrs[attrName]) && isDefined(val))
3088
- ) {
3089
- destination.$target[attrName] = lastValue;
3090
- throw $compileMinErr(
3091
- "nonassign",
3092
- "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
3093
- attrs[attrName],
3094
- attrName,
3095
- directive.name,
3096
- );
3097
- } else {
3098
- // manually set the handler to avoid watch cycles
3099
- if (isObject(val)) {
3100
- Object.entries(val).forEach(([key, value]) => {
3101
- scope.$target[key] = value;
3102
- });
3103
- } else {
3104
- parentSet(scope.$target, (lastValue = val));
3105
- scope.$handler.watchers
3106
- .get(attrs[attrName])
3107
- ?.forEach((watchFn) => {
3108
- watchFn.listenerFn(val);
3109
- });
3110
- }
3111
- }
3112
- },
3113
- true,
3114
- );
3115
- }
3116
- removeWatchCollection.push(removeWatch);
3117
- break;
3118
- }
3119
-
3120
- case "<":
3121
- if (!hasOwn(attrs, attrName)) {
3122
- if (optional) {
3123
- break;
3124
- }
3125
- strictBindingsCheck(attrName, directive.name);
3126
- attrs[attrName] = undefined;
3127
- }
3128
- if (optional && !attrs[attrName]) {
3129
- break;
3130
- }
3131
-
3132
- parentGet = $parse(attrs[attrName]);
3133
-
3134
- destination.$target[scopeName] = parentGet(scope.$target);
3135
- /** @type {SimpleChange} */
3136
- initialChanges[scopeName] = {
3137
- currentValue: destination.$target[scopeName],
3138
- firstChange: firstChange,
3139
- };
3140
- scope.$target.attrs = attrs;
3141
-
3142
- if (attrs[attrName]) {
3143
- removeWatch = scope.$watch(
3144
- attrs[attrName],
3145
- (val) => {
3146
- destination.$target[scopeName] = val;
3147
- recordChanges(scopeName, val, firstChange);
3148
- if (firstChange) {
3149
- firstChange = false;
3150
- }
3151
- },
3152
- true,
3153
- );
3154
- removeWatchCollection.push(removeWatch);
3155
- }
3156
- break;
3157
-
3158
- case "&":
3159
- if (!optional && !hasOwn(attrs, attrName)) {
3160
- strictBindingsCheck(attrName, directive.name);
3161
- }
3162
- // Don't assign Object.prototype method to scope
3163
- parentGet = hasOwn(attrs, attrName)
3164
- ? $parse(attrs[attrName])
3165
- : () => {};
3166
-
3167
- // Don't assign noop to destination if expression is not valid
3168
- if (
3169
- parentGet.toString() === (() => {}).toString() &&
3170
- optional
3171
- ) {
3172
- break;
3173
- }
3174
-
3175
- destination.$target[scopeName] = function (locals) {
3176
- return parentGet(scope.$target, locals);
3177
- };
3178
-
3179
- break;
3180
- }
3181
- });
3182
- }
3183
-
3184
- function recordChanges(key, currentValue, initial) {
3185
- if (isFunction(destination["$onChanges"])) {
3186
- // If we have not already scheduled the top level onChangesQueue handler then do so now
3187
- if (!onChangesQueue) {
3188
- scope.$postUpdate(flushOnChangesQueue);
3189
- onChangesQueue = [];
3190
- }
3191
- // If we have not already queued a trigger of onChanges for this controller then do so now
3192
- if (!changes) {
3193
- changes = {};
3194
- onChangesQueue.push(triggerOnChangesHook);
3195
- }
3196
- // Store this change
3197
- changes[key] = {
3198
- currentValue: currentValue,
3199
- firstChange: initial,
3200
- };
3201
- }
3202
- }
3203
-
3204
- function triggerOnChangesHook() {
3205
- destination["$onChanges"] &&
3206
- changes &&
3207
- destination["$onChanges"](changes);
3208
- // Now clear the changes so that we schedule onChanges when more changes arrive
3209
- changes = undefined;
3210
- }
3211
-
3212
- return {
3213
- initialChanges,
3214
- removeWatches:
3215
- removeWatchCollection.length &&
3216
- function removeWatches() {
3217
- for (
3218
- let i = 0, ii = removeWatchCollection.length;
3219
- i < ii;
3220
- ++i
3221
- ) {
3222
- removeWatchCollection[i]();
3223
- }
3224
- },
3225
- };
3226
- }
3227
- },
3228
- ];
3229
- }
3230
- }
3231
-
3232
- function removeComments(jqNodes) {
3233
- let i = jqNodes.length;
3234
-
3235
- if (i <= 1) {
3236
- return jqNodes;
3237
- }
3238
-
3239
- while (i--) {
3240
- const node = jqNodes[i];
3241
- if (
3242
- node.nodeType === Node.COMMENT_NODE ||
3243
- (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() === "")
3244
- ) {
3245
- [].splice.call(jqNodes, i, 1);
3246
- }
3247
- }
3248
- return jqNodes;
3249
- }
3250
-
3251
- /**
3252
- * @param {String} name
3253
- * @returns {void}
3254
- */
3255
- function assertValidDirectiveName(name) {
3256
- const letter = name.charAt(0);
3257
- if (!letter || letter !== lowercase(letter)) {
3258
- throw $compileMinErr(
3259
- "baddir",
3260
- "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter",
3261
- name,
3262
- );
3263
- }
3264
- if (name !== name.trim()) {
3265
- throw $compileMinErr(
3266
- "baddir",
3267
- "Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
3268
- name,
3269
- );
3270
- }
3271
- }