@intlayer/core 9.4.1 → 9.4.3

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 (220) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/index.cjs +8 -4
  3. package/dist/cjs/localization/getCanonicalPath.cjs +52 -0
  4. package/dist/cjs/localization/getCanonicalPath.cjs.map +1 -0
  5. package/dist/cjs/localization/getCanonicalPath.test-d.cjs +12 -0
  6. package/dist/cjs/localization/getCanonicalPath.test-d.cjs.map +1 -0
  7. package/dist/cjs/localization/getLocalizedPath.cjs +4 -2
  8. package/dist/cjs/localization/getLocalizedPath.cjs.map +1 -1
  9. package/dist/cjs/localization/index.cjs +4 -2
  10. package/dist/cjs/localization/rewriteMatch.cjs +52 -0
  11. package/dist/cjs/localization/rewriteMatch.cjs.map +1 -0
  12. package/dist/cjs/localization/rewriteUtils.cjs +6 -68
  13. package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
  14. package/dist/cjs/localization/rewriteUtils.test-d.cjs +0 -5
  15. package/dist/cjs/localization/rewriteUtils.test-d.cjs.map +1 -1
  16. package/dist/cjs/markdown/compiler.cjs +100 -75
  17. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  18. package/dist/cjs/markdown/constants.cjs +14 -5
  19. package/dist/cjs/markdown/constants.cjs.map +1 -1
  20. package/dist/cjs/markdown/index.cjs +4 -2
  21. package/dist/cjs/markdown/parser.cjs +70 -44
  22. package/dist/cjs/markdown/parser.cjs.map +1 -1
  23. package/dist/cjs/markdown/renderer.cjs +7 -19
  24. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  25. package/dist/cjs/markdown/utils.cjs +33 -37
  26. package/dist/cjs/markdown/utils.cjs.map +1 -1
  27. package/dist/esm/index.mjs +5 -3
  28. package/dist/esm/localization/getCanonicalPath.mjs +51 -0
  29. package/dist/esm/localization/getCanonicalPath.mjs.map +1 -0
  30. package/dist/esm/localization/getCanonicalPath.test-d.mjs +12 -0
  31. package/dist/esm/localization/getCanonicalPath.test-d.mjs.map +1 -0
  32. package/dist/esm/localization/getLocalizedPath.mjs +3 -1
  33. package/dist/esm/localization/getLocalizedPath.mjs.map +1 -1
  34. package/dist/esm/localization/index.mjs +3 -1
  35. package/dist/esm/localization/rewriteMatch.mjs +49 -0
  36. package/dist/esm/localization/rewriteMatch.mjs.map +1 -0
  37. package/dist/esm/localization/rewriteUtils.mjs +3 -63
  38. package/dist/esm/localization/rewriteUtils.mjs.map +1 -1
  39. package/dist/esm/localization/rewriteUtils.test-d.mjs +1 -6
  40. package/dist/esm/localization/rewriteUtils.test-d.mjs.map +1 -1
  41. package/dist/esm/markdown/compiler.mjs +101 -55
  42. package/dist/esm/markdown/compiler.mjs.map +1 -1
  43. package/dist/esm/markdown/constants.mjs +11 -4
  44. package/dist/esm/markdown/constants.mjs.map +1 -1
  45. package/dist/esm/markdown/index.mjs +2 -2
  46. package/dist/esm/markdown/parser.mjs +70 -44
  47. package/dist/esm/markdown/parser.mjs.map +1 -1
  48. package/dist/esm/markdown/renderer.mjs +7 -19
  49. package/dist/esm/markdown/renderer.mjs.map +1 -1
  50. package/dist/esm/markdown/utils.mjs +34 -38
  51. package/dist/esm/markdown/utils.mjs.map +1 -1
  52. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +1 -0
  53. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +1 -0
  54. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +1 -0
  55. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +1 -0
  56. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +1 -0
  57. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +1 -0
  58. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +1 -0
  59. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +7 -0
  60. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +1 -0
  61. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +2 -0
  62. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  63. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +1 -0
  64. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +1 -0
  65. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +1 -0
  66. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +1 -0
  67. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +1 -0
  68. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +1 -0
  69. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +1 -0
  70. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +1 -0
  71. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +7 -0
  72. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +1 -0
  73. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +6 -0
  74. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +2 -0
  75. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  76. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +1 -0
  77. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +1 -0
  78. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +1 -0
  79. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +1 -0
  80. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +1 -0
  81. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +1 -0
  82. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +1 -0
  83. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +1 -0
  84. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +7 -0
  85. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +1 -0
  86. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +6 -0
  87. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +2 -0
  88. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  89. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +1 -0
  90. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +1 -0
  91. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +1 -0
  92. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +1 -0
  93. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +1 -0
  94. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +1 -0
  95. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +1 -0
  96. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +1 -0
  97. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +7 -0
  98. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +1 -0
  99. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +6 -0
  100. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +2 -0
  101. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  102. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +1 -0
  103. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +1 -0
  104. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +1 -0
  105. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +1 -0
  106. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +1 -0
  107. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +1 -0
  108. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +1 -0
  109. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +1 -0
  110. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +7 -0
  111. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +1 -0
  112. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +6 -0
  113. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +2 -0
  114. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  115. package/dist/types/@intlayer/core/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +1 -0
  116. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/plainDynamicLoader.d.ts +2 -0
  117. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +2 -0
  118. package/dist/types/@intlayer/core/dist/types/formatters/compact.d.ts +1 -0
  119. package/dist/types/@intlayer/core/dist/types/formatters/currency.d.ts +1 -0
  120. package/dist/types/@intlayer/core/dist/types/formatters/date.d.ts +1 -0
  121. package/dist/types/@intlayer/core/dist/types/formatters/index.d.ts +9 -0
  122. package/dist/types/@intlayer/core/dist/types/formatters/list.d.ts +1 -0
  123. package/dist/types/@intlayer/core/dist/types/formatters/number.d.ts +1 -0
  124. package/dist/types/@intlayer/core/dist/types/formatters/percentage.d.ts +1 -0
  125. package/dist/types/@intlayer/core/dist/types/formatters/relativeTime.d.ts +1 -0
  126. package/dist/types/@intlayer/core/dist/types/formatters/units.d.ts +1 -0
  127. package/dist/types/@intlayer/core/dist/types/interpreter/dictionaryTransformCache.d.ts +4 -0
  128. package/dist/types/@intlayer/core/dist/types/interpreter/getCondition.d.ts +2 -0
  129. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/deepTransform.d.ts +1 -0
  130. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/getContent.d.ts +3 -0
  131. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/index.d.ts +3 -0
  132. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/plugins.d.ts +7 -0
  133. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionary.d.ts +4 -0
  134. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +6 -0
  135. package/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +2 -0
  136. package/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +2 -0
  137. package/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +2 -0
  138. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayer.d.ts +4 -0
  139. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayerAsync.d.ts +4 -0
  140. package/dist/types/@intlayer/core/dist/types/interpreter/getNesting.d.ts +6 -0
  141. package/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +3 -0
  142. package/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +2 -0
  143. package/dist/types/@intlayer/core/dist/types/interpreter/getTranslation.d.ts +1 -0
  144. package/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +18 -0
  145. package/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +2 -0
  146. package/dist/types/@intlayer/core/dist/types/intlayer/dist/types/index.d.ts +6 -0
  147. package/dist/types/@intlayer/core/dist/types/localization/comparePaths.d.ts +1 -0
  148. package/dist/types/@intlayer/core/dist/types/localization/domainUtils.d.ts +2 -0
  149. package/dist/types/@intlayer/core/dist/types/localization/generateSitemap.d.ts +2 -0
  150. package/dist/types/@intlayer/core/dist/types/localization/getBrowserLocale.d.ts +1 -0
  151. package/dist/types/@intlayer/core/dist/types/localization/getCanonicalPath.d.ts +2 -0
  152. package/dist/types/@intlayer/core/dist/types/localization/getHTMLTextDir.d.ts +1 -0
  153. package/dist/types/@intlayer/core/dist/types/localization/getLocale.d.ts +1 -0
  154. package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromPath.d.ts +2 -0
  155. package/dist/types/@intlayer/core/dist/types/localization/getLocaleLang.d.ts +1 -0
  156. package/dist/types/@intlayer/core/dist/types/localization/getLocaleName.d.ts +1 -0
  157. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedPath.d.ts +2 -0
  158. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedUrl.d.ts +2 -0
  159. package/dist/types/@intlayer/core/dist/types/localization/getMultilingualUrls.d.ts +2 -0
  160. package/dist/types/@intlayer/core/dist/types/localization/getPathWithoutLocale.d.ts +1 -0
  161. package/dist/types/@intlayer/core/dist/types/localization/getPrefix.d.ts +2 -0
  162. package/dist/types/@intlayer/core/dist/types/localization/index.d.ts +22 -0
  163. package/dist/types/@intlayer/core/dist/types/localization/localeDetector.d.ts +2 -0
  164. package/dist/types/@intlayer/core/dist/types/localization/localeMapper.d.ts +1 -0
  165. package/dist/types/@intlayer/core/dist/types/localization/localeResolver.d.ts +1 -0
  166. package/dist/types/@intlayer/core/dist/types/localization/resolveBrowserLocale.d.ts +2 -0
  167. package/dist/types/@intlayer/core/dist/types/localization/rewriteMatch.d.ts +1 -0
  168. package/dist/types/@intlayer/core/dist/types/localization/rewriteUtils.d.ts +2 -0
  169. package/dist/types/@intlayer/core/dist/types/localization/validatePrefix.d.ts +2 -0
  170. package/dist/types/@intlayer/core/dist/types/markdown/index.d.ts +2 -0
  171. package/dist/types/@intlayer/core/dist/types/transpiler/condition/condition.d.ts +1 -0
  172. package/dist/types/@intlayer/core/dist/types/transpiler/condition/index.d.ts +1 -0
  173. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/enumeration.d.ts +1 -0
  174. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/index.d.ts +1 -0
  175. package/dist/types/@intlayer/core/dist/types/transpiler/file/file.d.ts +1 -0
  176. package/dist/types/@intlayer/core/dist/types/transpiler/file/index.d.ts +1 -0
  177. package/dist/types/@intlayer/core/dist/types/transpiler/gender/gender.d.ts +1 -0
  178. package/dist/types/@intlayer/core/dist/types/transpiler/gender/index.d.ts +1 -0
  179. package/dist/types/@intlayer/core/dist/types/transpiler/html/html.d.ts +1 -0
  180. package/dist/types/@intlayer/core/dist/types/transpiler/html/index.d.ts +1 -0
  181. package/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +22 -0
  182. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/index.d.ts +1 -0
  183. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/insertion.d.ts +1 -0
  184. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/index.d.ts +1 -0
  185. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/markdown.d.ts +1 -0
  186. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  187. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +4 -0
  188. package/dist/types/@intlayer/core/dist/types/transpiler/plural/index.d.ts +1 -0
  189. package/dist/types/@intlayer/core/dist/types/transpiler/plural/plural.d.ts +1 -0
  190. package/dist/types/@intlayer/core/dist/types/transpiler/select/index.d.ts +1 -0
  191. package/dist/types/@intlayer/core/dist/types/transpiler/select/select.d.ts +1 -0
  192. package/dist/types/@intlayer/core/dist/types/transpiler/translation/index.d.ts +1 -0
  193. package/dist/types/@intlayer/core/dist/types/transpiler/translation/translation.d.ts +2 -0
  194. package/dist/types/@intlayer/core/dist/types/utils/index.d.ts +3 -0
  195. package/dist/types/@intlayer/core/dist/types/utils/intl.d.ts +1 -0
  196. package/dist/types/@intlayer/core/dist/types/utils/isSameKeyPath.d.ts +1 -0
  197. package/dist/types/@intlayer/core/dist/types/utils/localeStorage.d.ts +2 -0
  198. package/dist/types/index.d.ts +5 -3
  199. package/dist/types/interpreter/getPlural.d.ts +1 -1
  200. package/dist/types/intlayer/dist/types/index.d.ts +14 -0
  201. package/dist/types/localization/getCanonicalPath.d.ts +19 -0
  202. package/dist/types/localization/getCanonicalPath.d.ts.map +1 -0
  203. package/dist/types/localization/getCanonicalPath.test-d.d.ts +1 -0
  204. package/dist/types/localization/getLocalizedPath.d.ts.map +1 -1
  205. package/dist/types/localization/index.d.ts +3 -1
  206. package/dist/types/localization/rewriteMatch.d.ts +20 -0
  207. package/dist/types/localization/rewriteMatch.d.ts.map +1 -0
  208. package/dist/types/localization/rewriteUtils.d.ts +2 -14
  209. package/dist/types/localization/rewriteUtils.d.ts.map +1 -1
  210. package/dist/types/markdown/compiler.d.ts.map +1 -1
  211. package/dist/types/markdown/constants.d.ts +11 -4
  212. package/dist/types/markdown/constants.d.ts.map +1 -1
  213. package/dist/types/markdown/index.d.ts +2 -2
  214. package/dist/types/markdown/parser.d.ts.map +1 -1
  215. package/dist/types/markdown/renderer.d.ts.map +1 -1
  216. package/dist/types/markdown/types.d.ts +8 -2
  217. package/dist/types/markdown/types.d.ts.map +1 -1
  218. package/dist/types/markdown/utils.d.ts +0 -4
  219. package/dist/types/markdown/utils.d.ts.map +1 -1
  220. package/package.json +7 -7
@@ -49,15 +49,37 @@ const get = (src, path, fb) => {
49
49
  * Convert a string to a URL-safe slug.
50
50
  * Based on https://stackoverflow.com/a/18123682/1141611
51
51
  */
52
- const slugify = (str) => str.replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a").replace(/[çÇ]/g, "c").replace(/[ðÐ]/g, "d").replace(/[ÈÉÊËéèêë]/g, "e").replace(/[ÏïÎîÍíÌì]/g, "i").replace(/[Ññ]/g, "n").replace(/[øØœŒÕõÔôÓóÒò]/g, "o").replace(/[ÜüÛûÚúÙù]/g, "u").replace(/[ŸÿÝý]/g, "y").replace(/[^a-z0-9- ]/gi, "").replace(/ /gi, "-").toLowerCase();
52
+ const SLUGIFY_REPLACEMENTS = [
53
+ [/[ÀÁÂÃÄÅàáâãä忯]/g, "a"],
54
+ [/[çÇ]/g, "c"],
55
+ [/[ðÐ]/g, "d"],
56
+ [/[ÈÉÊËéèêë]/g, "e"],
57
+ [/[ÏïÎîÍíÌì]/g, "i"],
58
+ [/[Ññ]/g, "n"],
59
+ [/[øØœŒÕõÔôÓóÒò]/g, "o"],
60
+ [/[ÜüÛûÚúÙù]/g, "u"],
61
+ [/[ŸÿÝý]/g, "y"],
62
+ [/[^a-z0-9- ]/gi, ""],
63
+ [/ /gi, "-"]
64
+ ];
65
+ const slugify = (str) => {
66
+ let result = str;
67
+ for (let i = 0; i < SLUGIFY_REPLACEMENTS.length; i++) {
68
+ const [pattern, replacement] = SLUGIFY_REPLACEMENTS[i];
69
+ result = result.replace(pattern, replacement);
70
+ }
71
+ return result.toLowerCase();
72
+ };
53
73
  const SANITIZE_R = /(javascript|vbscript|data(?!:image)):/i;
74
+ const SANITIZE_STRIP_R = /[^A-Za-z0-9/:]/g;
54
75
  /**
55
76
  * Sanitize URLs to prevent XSS attacks.
56
77
  * Returns null if the URL is unsafe.
57
78
  */
58
79
  const sanitizer = (input) => {
80
+ if (input.indexOf(":") === -1 && input.indexOf("%") === -1) return input;
59
81
  try {
60
- const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, "");
82
+ const decoded = decodeURIComponent(input).replace(SANITIZE_STRIP_R, "");
61
83
  if (SANITIZE_R.test(decoded)) {
62
84
  console.warn("Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.", decoded);
63
85
  return null;
@@ -71,13 +93,11 @@ const sanitizer = (input) => {
71
93
  /**
72
94
  * Normalize whitespace in source string.
73
95
  */
74
- const normalizeWhitespace = (source) => {
75
- const start = performance.now();
76
- const result = source.replace(require_markdown_constants.CR_NEWLINE_R, "\n").replace(require_markdown_constants.FORMFEED_R, "").replace(require_markdown_constants.TAB_R, " ");
77
- const duration = performance.now() - start;
78
- if (duration > 20) console.log(`normalizeWhitespace: ${duration.toFixed(3)}ms, source length: ${source.length}`);
79
- return result;
80
- };
96
+ const normalizeWhitespace = (source) => source.replace(require_markdown_constants.NORMALIZE_WHITESPACE_R, (match) => {
97
+ if (match === " ") return " ";
98
+ if (match === "\f") return "";
99
+ return "\n";
100
+ });
81
101
  /**
82
102
  * Safely remove a uniform leading indentation from lines, but do NOT touch
83
103
  * the content inside fenced code blocks (``` or ~~~).
@@ -89,13 +109,12 @@ const normalizeWhitespace = (source) => {
89
109
  * verbatim, instead of losing the first level of indentation.
90
110
  */
91
111
  const trimLeadingWhitespaceOutsideFences = (text, whitespace) => {
92
- const start = performance.now();
93
112
  if (!whitespace) return text;
94
113
  const lines = text.split("\n");
95
114
  /** Indentation and marker of the fence currently open, if any. */
96
115
  let openFence = null;
97
116
  const removePrefix = (line, prefix) => prefix && line.startsWith(prefix) ? line.slice(prefix.length) : line;
98
- const result = lines.map((line) => {
117
+ return lines.map((line) => {
99
118
  const fenceMatch = line.match(require_markdown_constants.FENCE_DELIMITER_R);
100
119
  if (!openFence) {
101
120
  if (fenceMatch) openFence = {
@@ -104,14 +123,11 @@ const trimLeadingWhitespaceOutsideFences = (text, whitespace) => {
104
123
  };
105
124
  return removePrefix(line, whitespace);
106
125
  }
107
- const isClosingFence = fenceMatch?.[2].startsWith(openFence.marker);
126
+ const isClosingFence = fenceMatch?.[2]?.startsWith(openFence.marker);
108
127
  const { indentation } = openFence;
109
128
  if (isClosingFence) openFence = null;
110
129
  return removePrefix(line, indentation);
111
130
  }).join("\n");
112
- const duration = performance.now() - start;
113
- if (duration > 20) console.log(`trimLeadingWhitespaceOutsideFences: ${duration.toFixed(3)}ms, text length: ${text.length}, lines count: ${lines.length}`);
114
- return result;
115
131
  };
116
132
  /**
117
133
  * Normalize HTML attribute key to JSX prop name.
@@ -126,7 +142,6 @@ const normalizeAttributeKey = (key) => {
126
142
  * Parse a CSS style string into an array of [key, value] tuples.
127
143
  */
128
144
  const parseStyleAttribute = (styleString) => {
129
- const start = performance.now();
130
145
  const styles = [];
131
146
  let buffer = "";
132
147
  let inUrl = false;
@@ -168,8 +183,6 @@ const parseStyleAttribute = (styleString) => {
168
183
  styles.push([key, value]);
169
184
  }
170
185
  }
171
- const duration = performance.now() - start;
172
- if (duration > 20) console.log(`parseStyleAttribute: ${duration.toFixed(3)}ms, styleString length: ${styleString.length}, styles count: ${styles.length}`);
173
186
  return styles;
174
187
  };
175
188
  /**
@@ -206,7 +219,6 @@ const parseTableAlign = (source) => {
206
219
  * Parse a single table row.
207
220
  */
208
221
  const parseTableRow = (source, parse, state, tableOutput) => {
209
- const start = performance.now();
210
222
  const prevInTable = state.inTable;
211
223
  state.inTable = true;
212
224
  const cells = [[]];
@@ -229,20 +241,13 @@ const parseTableRow = (source, parse, state, tableOutput) => {
229
241
  });
230
242
  flush();
231
243
  state.inTable = prevInTable;
232
- const duration = performance.now() - start;
233
- if (duration > 20) console.log(`parseTableRow: ${duration.toFixed(3)}ms, source length: ${source.length}, cells count: ${cells.length}`);
234
244
  return cells;
235
245
  };
236
246
  /**
237
247
  * Parse table cells (multiple rows).
238
248
  */
239
249
  const parseTableCells = (source, parse, state) => {
240
- const start = performance.now();
241
- const rowsText = source.trim().split("\n");
242
- const result = rowsText.map((rowText) => parseTableRow(rowText, parse, state, true));
243
- const duration = performance.now() - start;
244
- if (duration > 20) console.log(`parseTableCells: ${duration.toFixed(3)}ms, source length: ${source.length}, rows count: ${rowsText.length}`);
245
- return result;
250
+ return source.trim().split("\n").map((rowText) => parseTableRow(rowText, parse, state, true));
246
251
  };
247
252
  /**
248
253
  * Check if a rule qualifies for the current source and state.
@@ -293,7 +298,6 @@ const anyScopeRegex = (fn) => allowInline((source, state) => {
293
298
  * Parse inline content (including links).
294
299
  */
295
300
  const parseInline = (parse, children, state) => {
296
- const start = performance.now();
297
301
  const isCurrentlyInline = state.inline ?? false;
298
302
  const isCurrentlySimple = state.simple ?? false;
299
303
  state.inline = true;
@@ -301,15 +305,12 @@ const parseInline = (parse, children, state) => {
301
305
  const result = parse(children, state);
302
306
  state.inline = isCurrentlyInline;
303
307
  state.simple = isCurrentlySimple;
304
- const duration = performance.now() - start;
305
- if (duration > 20) console.log(`parseInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`);
306
308
  return result;
307
309
  };
308
310
  /**
309
311
  * Parse simple inline content (no links).
310
312
  */
311
313
  const parseSimpleInline = (parse, children, state) => {
312
- const start = performance.now();
313
314
  const isCurrentlyInline = state.inline ?? false;
314
315
  const isCurrentlySimple = state.simple ?? false;
315
316
  state.inline = false;
@@ -317,29 +318,24 @@ const parseSimpleInline = (parse, children, state) => {
317
318
  const result = parse(children, state);
318
319
  state.inline = isCurrentlyInline;
319
320
  state.simple = isCurrentlySimple;
320
- const duration = performance.now() - start;
321
- if (duration > 20) console.log(`parseSimpleInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`);
322
321
  return result;
323
322
  };
324
323
  /**
325
324
  * Parse block content.
326
325
  */
327
326
  const parseBlock = (parse, children, state = {}) => {
328
- const start = performance.now();
329
327
  const isCurrentlyInline = state.inline || false;
330
328
  state.inline = false;
331
329
  const normalizedChildren = trimEnd(children);
332
330
  const result = parse(/\n\n$/.test(normalizedChildren) === false ? normalizedChildren.endsWith("\n") ? `${normalizedChildren}\n` : `${normalizedChildren}\n\n` : normalizedChildren, state);
333
331
  state.inline = isCurrentlyInline;
334
- const duration = performance.now() - start;
335
- if (duration > 20) console.log(`parseBlock: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`);
336
332
  return result;
337
333
  };
338
334
  /**
339
335
  * Helper to parse capture group 2 as inline content.
340
336
  */
341
337
  const parseCaptureInline = (capture, parse, state) => {
342
- return { children: parseInline(parse, capture[2], state) };
338
+ return { children: parseInline(parse, capture[2] ?? "", state) };
343
339
  };
344
340
  /**
345
341
  * Helper that captures nothing (empty object).
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":["UNESCAPE_R","CR_NEWLINE_R","FORMFEED_R","TAB_R","FENCE_DELIMITER_R","HTML_CUSTOM_ATTR_R","CAPTURE_LETTER_AFTER_HYPHEN","ATTRIBUTES_TO_SANITIZE","INTERPOLATION_R","TABLE_RIGHT_ALIGN","TABLE_CENTER_ALIGN","TABLE_LEFT_ALIGN","TABLE_TRIM_PIPES"],"sources":["../../../src/markdown/utils.ts"],"sourcesContent":["import {\n ATTRIBUTES_TO_SANITIZE,\n CAPTURE_LETTER_AFTER_HYPHEN,\n CR_NEWLINE_R,\n DURATION_DELAY_TRIGGER,\n FENCE_DELIMITER_R,\n FORMFEED_R,\n HTML_CUSTOM_ATTR_R,\n INTERPOLATION_R,\n TAB_R,\n TABLE_CENTER_ALIGN,\n TABLE_LEFT_ALIGN,\n TABLE_RIGHT_ALIGN,\n TABLE_TRIM_PIPES,\n UNESCAPE_R,\n} from './constants';\nimport type { NestedParser, ParserResult, ParseState, Rule } from './types';\n\n// ============================================================================\n// STRING UTILITIES\n// ============================================================================\n\n/**\n * Trim trailing whitespace from a string.\n */\nexport const trimEnd = (str: string): string => {\n let end = str.length;\n\n while (end > 0 && str[end - 1] <= ' ') end--;\n\n return str.slice(0, end);\n};\n\n/**\n * Check if string starts with prefix.\n */\nexport const startsWith = (str: string, prefix: string): boolean => {\n return str.startsWith(prefix);\n};\n\n/**\n * Remove symmetrical leading and trailing quotes.\n */\nexport const unquote = (str: string): string => {\n const first = str[0];\n\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n ) {\n return str.slice(1, -1);\n }\n\n return str;\n};\n\n/**\n * Unescape backslash-escaped characters.\n */\nexport const unescapeString = (rawString: string): string =>\n rawString ? rawString.replace(UNESCAPE_R, '$1') : rawString;\n\n/**\n * Join class names, filtering out falsy values.\n */\nexport const cx = (...args: any[]): string => args.filter(Boolean).join(' ');\n\n/**\n * Get a nested property from an object using dot notation.\n */\nexport const get = (src: any, path: string, fb?: any): any => {\n let ptr = src;\n const frags = path.split('.');\n\n while (frags.length) {\n ptr = ptr[frags[0]];\n\n if (ptr === undefined) break;\n else frags.shift();\n }\n\n return ptr ?? fb;\n};\n\n// ============================================================================\n// SLUGIFY\n// ============================================================================\n\n/**\n * Convert a string to a URL-safe slug.\n * Based on https://stackoverflow.com/a/18123682/1141611\n */\nexport const slugify = (str: string): string =>\n str\n .replace(/[ÀÁÂÃÄÅàáâãä忯]/g, 'a')\n .replace(/[çÇ]/g, 'c')\n .replace(/[ðÐ]/g, 'd')\n .replace(/[ÈÉÊËéèêë]/g, 'e')\n .replace(/[ÏïÎîÍíÌì]/g, 'i')\n .replace(/[Ññ]/g, 'n')\n .replace(/[øØœŒÕõÔôÓóÒò]/g, 'o')\n .replace(/[ÜüÛûÚúÙù]/g, 'u')\n .replace(/[ŸÿÝý]/g, 'y')\n .replace(/[^a-z0-9- ]/gi, '')\n .replace(/ /gi, '-')\n .toLowerCase();\n\n// ============================================================================\n// SANITIZER\n// ============================================================================\n\nconst SANITIZE_R = /(javascript|vbscript|data(?!:image)):/i;\n\n/**\n * Sanitize URLs to prevent XSS attacks.\n * Returns null if the URL is unsafe.\n */\nexport const sanitizer = (input: string): string | null => {\n try {\n const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, '');\n\n if (SANITIZE_R.test(decoded)) {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n );\n\n return null;\n }\n } catch (_e) {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n );\n\n // decodeURIComponent sometimes throws a URIError\n return null;\n }\n\n return input;\n};\n\n// ============================================================================\n// WHITESPACE NORMALIZATION\n// ============================================================================\n\n/**\n * Normalize whitespace in source string.\n */\nexport const normalizeWhitespace = (source: string): string => {\n const start = performance.now();\n const result = source\n .replace(CR_NEWLINE_R, '\\n')\n .replace(FORMFEED_R, '')\n .replace(TAB_R, ' ');\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `normalizeWhitespace: ${duration.toFixed(3)}ms, source length: ${source.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Safely remove a uniform leading indentation from lines, but do NOT touch\n * the content inside fenced code blocks (``` or ~~~).\n *\n * Inside a fenced block the structural indentation is irrelevant: what matters\n * is the indentation of the opening fence itself, which is the only amount\n * CommonMark strips from the code lines. A block nested in an indented HTML\n * element but written with its fence at column 0 therefore keeps its code\n * verbatim, instead of losing the first level of indentation.\n */\nexport const trimLeadingWhitespaceOutsideFences = (\n text: string,\n whitespace: string\n): string => {\n const start = performance.now();\n if (!whitespace) return text;\n\n const lines = text.split('\\n');\n\n /** Indentation and marker of the fence currently open, if any. */\n let openFence: { indentation: string; marker: string } | null = null;\n\n const removePrefix = (line: string, prefix: string): string =>\n prefix && line.startsWith(prefix) ? line.slice(prefix.length) : line;\n\n // Outside fences, strip the base structural indentation from every line.\n // Lines that don't start with the whitespace prefix are left as-is.\n const result = lines\n .map((line) => {\n const fenceMatch = line.match(FENCE_DELIMITER_R);\n\n if (!openFence) {\n if (fenceMatch)\n openFence = { indentation: fenceMatch[1], marker: fenceMatch[2] };\n return removePrefix(line, whitespace);\n }\n\n const isClosingFence = fenceMatch?.[2].startsWith(openFence.marker);\n const { indentation } = openFence;\n\n if (isClosingFence) openFence = null;\n\n return removePrefix(line, indentation);\n })\n .join('\\n');\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `trimLeadingWhitespaceOutsideFences: ${duration.toFixed(3)}ms, text length: ${text.length}, lines count: ${lines.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Normalize HTML attribute key to JSX prop name.\n */\nexport const normalizeAttributeKey = (key: string): string => {\n const hyphenIndex = key.indexOf('-');\n\n if (hyphenIndex !== -1 && key.match(HTML_CUSTOM_ATTR_R) === null) {\n key = key.replace(CAPTURE_LETTER_AFTER_HYPHEN, (_, letter) => {\n return letter.toUpperCase();\n });\n }\n\n return key;\n};\n\ntype StyleTuple = [key: string, value: string];\n\n/**\n * Parse a CSS style string into an array of [key, value] tuples.\n */\nexport const parseStyleAttribute = (styleString: string): StyleTuple[] => {\n const start = performance.now();\n const styles: StyleTuple[] = [];\n let buffer = '';\n let inUrl = false;\n let inQuotes = false;\n let quoteChar: '\"' | \"'\" | '' = '';\n\n if (!styleString) return styles;\n\n for (let i = 0; i < styleString.length; i++) {\n const char = styleString[i];\n\n if ((char === '\"' || char === \"'\") && !inUrl) {\n if (!inQuotes) {\n inQuotes = true;\n quoteChar = char;\n } else if (char === quoteChar) {\n inQuotes = false;\n quoteChar = '';\n }\n }\n\n if (char === '(' && buffer.endsWith('url')) {\n inUrl = true;\n } else if (char === ')' && inUrl) {\n inUrl = false;\n }\n\n if (char === ';' && !inQuotes && !inUrl) {\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n buffer = '';\n } else {\n buffer += char;\n }\n }\n\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseStyleAttribute: ${duration.toFixed(3)}ms, styleString length: ${styleString.length}, styles count: ${styles.length}`\n );\n }\n\n return styles;\n};\n\n/**\n * Convert an attribute value to a Node prop value.\n */\nexport const attributeValueToNodePropValue = (\n tag: string,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null\n): any => {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n (styles, [styleKey, styleValue]) => {\n const camelCasedKey = styleKey.replace(/(-[a-z])/g, (substr) =>\n substr[1].toUpperCase()\n );\n\n (styles as Record<string, any>)[camelCasedKey] = sanitizeUrlFn(\n styleValue,\n tag,\n styleKey\n );\n\n return styles;\n },\n {} as Record<string, any>\n );\n } else if (ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(unescapeString(value), tag, key);\n } else if (value.match(INTERPOLATION_R)) {\n value = unescapeString(value.slice(1, value.length - 1));\n }\n\n if (value === 'true') {\n return true;\n } else if (value === 'false') {\n return false;\n }\n\n return value;\n};\n\n// ============================================================================\n// TABLE PARSING\n// ============================================================================\n\n/**\n * Parse table alignment from a separator row.\n */\nexport const parseTableAlignCapture = (\n alignCapture: string\n): 'left' | 'right' | 'center' => {\n if (TABLE_RIGHT_ALIGN.test(alignCapture)) {\n return 'right';\n } else if (TABLE_CENTER_ALIGN.test(alignCapture)) {\n return 'center';\n } else if (TABLE_LEFT_ALIGN.test(alignCapture)) {\n return 'left';\n }\n\n return 'left';\n};\n\n/**\n * Parse table alignment row.\n */\nexport const parseTableAlign = (\n source: string\n): ('left' | 'right' | 'center')[] => {\n const alignText = source.replace(TABLE_TRIM_PIPES, '').split('|');\n return alignText.map(parseTableAlignCapture);\n};\n\n/**\n * Parse a single table row.\n */\nexport const parseTableRow = (\n source: string,\n parse: NestedParser,\n state: ParseState,\n tableOutput: boolean\n): ParserResult[][] => {\n const start = performance.now();\n const prevInTable = state.inTable;\n\n state.inTable = true;\n\n const cells: ParserResult[][] = [[]];\n let acc = '';\n\n const flush = (): void => {\n if (!acc) return;\n\n const cell = cells[cells.length - 1];\n cell.push.apply(cell, parse(acc, state));\n acc = '';\n };\n\n source\n .trim()\n .split(/(`[^`]*`|\\\\\\||\\|)/)\n .filter(Boolean)\n .forEach((fragment, i, arr) => {\n if (fragment.trim() === '|') {\n flush();\n\n if (tableOutput) {\n if (i !== 0 && i !== arr.length - 1) {\n cells.push([]);\n }\n\n return;\n }\n }\n\n acc += fragment;\n });\n\n flush();\n\n state.inTable = prevInTable;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableRow: ${duration.toFixed(3)}ms, source length: ${source.length}, cells count: ${cells.length}`\n );\n }\n\n return cells;\n};\n\n/**\n * Parse table cells (multiple rows).\n */\nexport const parseTableCells = (\n source: string,\n parse: NestedParser,\n state: ParseState\n): ParserResult[][][] => {\n const start = performance.now();\n const rowsText = source.trim().split('\\n');\n\n const result = rowsText.map((rowText) =>\n parseTableRow(rowText, parse, state, true)\n );\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableCells: ${duration.toFixed(3)}ms, source length: ${source.length}, rows count: ${rowsText.length}`\n );\n }\n\n return result;\n};\n\n// ============================================================================\n// PARSING HELPERS\n// ============================================================================\n\n/**\n * Check if a rule qualifies for the current source and state.\n */\nexport const qualifies = (\n source: string,\n state: ParseState,\n qualify: NonNullable<Rule<any>['_qualify']>\n): boolean => {\n if (Array.isArray(qualify)) {\n for (let i = 0; i < qualify.length; i++) {\n if (startsWith(source, qualify[i])) return true;\n }\n\n return false;\n }\n\n return (qualify as (source: string, state: ParseState) => boolean)(\n source,\n state\n );\n};\n\n/**\n * Marks a matcher function as eligible for being run inside an inline context.\n */\nexport const allowInline = <T extends (...args: any[]) => any>(\n fn: T\n): T & { inline: 1 } => {\n (fn as any).inline = 1;\n return fn as T & { inline: 1 };\n};\n\n/**\n * Creates a match function for an inline scoped element from a regex.\n */\nexport const inlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for inline elements except links.\n */\nexport const simpleInlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for a block scoped element from a regex.\n */\nexport const blockRegex =\n (regex: RegExp) =>\n (source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return null;\n } else {\n return regex.exec(source);\n }\n };\n\n/**\n * Creates a match function from a regex, ignoring block/inline scope.\n */\nexport const anyScopeRegex = (\n fn: RegExp | ((source: string, state: ParseState) => RegExpMatchArray | null)\n) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (typeof fn === 'function') {\n return fn(source, state);\n }\n return fn.exec(source);\n });\n\n/**\n * Parse inline content (including links).\n */\nexport const parseInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n state.inline = true;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse simple inline content (no links).\n */\nexport const parseSimpleInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n\n state.inline = false;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseSimpleInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse block content.\n */\nexport const parseBlock = (\n parse: NestedParser,\n children: string,\n state: ParseState = {}\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline || false;\n state.inline = false;\n const normalizedChildren = trimEnd(children);\n const needsTerminator = /\\n\\n$/.test(normalizedChildren) === false;\n const blockInput = needsTerminator\n ? normalizedChildren.endsWith('\\n')\n ? `${normalizedChildren}\\n`\n : `${normalizedChildren}\\n\\n`\n : normalizedChildren;\n\n const result = parse(blockInput, state);\n state.inline = isCurrentlyInline;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseBlock: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Helper to parse capture group 2 as inline content.\n */\nexport const parseCaptureInline = (\n capture: RegExpMatchArray,\n parse: NestedParser,\n state: ParseState\n): { children: ParserResult[] } => {\n return {\n children: parseInline(parse, capture[2], state),\n };\n};\n\n/**\n * Helper that captures nothing (empty object).\n */\nexport const captureNothing = (): Record<string, never> => ({});\n\n/**\n * Helper that renders nothing (null).\n */\nexport const renderNothing = (): null => null;\n\n/**\n * Check if any regex in a list matches the input.\n */\nexport const some = (regexes: RegExp[], input: string): boolean => {\n for (let i = 0; i < regexes.length; i++) {\n if (regexes[i].test(input)) {\n return true;\n }\n }\n return false;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","names":["UNESCAPE_R","NORMALIZE_WHITESPACE_R","FENCE_DELIMITER_R","HTML_CUSTOM_ATTR_R","CAPTURE_LETTER_AFTER_HYPHEN","ATTRIBUTES_TO_SANITIZE","INTERPOLATION_R","TABLE_RIGHT_ALIGN","TABLE_CENTER_ALIGN","TABLE_LEFT_ALIGN","TABLE_TRIM_PIPES"],"sources":["../../../src/markdown/utils.ts"],"sourcesContent":["import {\n ATTRIBUTES_TO_SANITIZE,\n CAPTURE_LETTER_AFTER_HYPHEN,\n FENCE_DELIMITER_R,\n HTML_CUSTOM_ATTR_R,\n INTERPOLATION_R,\n NORMALIZE_WHITESPACE_R,\n TABLE_CENTER_ALIGN,\n TABLE_LEFT_ALIGN,\n TABLE_RIGHT_ALIGN,\n TABLE_TRIM_PIPES,\n UNESCAPE_R,\n} from './constants';\nimport type { NestedParser, ParserResult, ParseState, Rule } from './types';\n\n// ============================================================================\n// STRING UTILITIES\n// ============================================================================\n\n/**\n * Trim trailing whitespace from a string.\n */\nexport const trimEnd = (str: string): string => {\n let end = str.length;\n\n while (end > 0 && str[end - 1]! <= ' ') end--;\n\n return str.slice(0, end);\n};\n\n/**\n * Check if string starts with prefix.\n */\nexport const startsWith = (str: string, prefix: string): boolean => {\n return str.startsWith(prefix);\n};\n\n/**\n * Remove symmetrical leading and trailing quotes.\n */\nexport const unquote = (str: string): string => {\n const first = str[0];\n\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n ) {\n return str.slice(1, -1);\n }\n\n return str;\n};\n\n/**\n * Unescape backslash-escaped characters.\n */\nexport const unescapeString = (rawString: string): string =>\n rawString ? rawString.replace(UNESCAPE_R, '$1') : rawString;\n\n/**\n * Join class names, filtering out falsy values.\n */\nexport const cx = (...args: any[]): string => args.filter(Boolean).join(' ');\n\n/**\n * Get a nested property from an object using dot notation.\n */\nexport const get = (src: any, path: string, fb?: any): any => {\n let ptr = src;\n const frags = path.split('.');\n\n while (frags.length) {\n ptr = ptr[frags[0]!];\n\n if (ptr === undefined) break;\n else frags.shift();\n }\n\n return ptr ?? fb;\n};\n\n// ============================================================================\n// SLUGIFY\n// ============================================================================\n\n/**\n * Convert a string to a URL-safe slug.\n * Based on https://stackoverflow.com/a/18123682/1141611\n */\nconst SLUGIFY_REPLACEMENTS: [pattern: RegExp, replacement: string][] = [\n [/[ÀÁÂÃÄÅàáâãä忯]/g, 'a'],\n [/[çÇ]/g, 'c'],\n [/[ðÐ]/g, 'd'],\n [/[ÈÉÊËéèêë]/g, 'e'],\n [/[ÏïÎîÍíÌì]/g, 'i'],\n [/[Ññ]/g, 'n'],\n [/[øØœŒÕõÔôÓóÒò]/g, 'o'],\n [/[ÜüÛûÚúÙù]/g, 'u'],\n [/[ŸÿÝý]/g, 'y'],\n [/[^a-z0-9- ]/gi, ''],\n [/ /gi, '-'],\n];\n\nexport const slugify = (str: string): string => {\n let result = str;\n\n for (let i = 0; i < SLUGIFY_REPLACEMENTS.length; i++) {\n const [pattern, replacement] = SLUGIFY_REPLACEMENTS[i]!;\n result = result.replace(pattern, replacement);\n }\n\n return result.toLowerCase();\n};\n\n// ============================================================================\n// SANITIZER\n// ============================================================================\n\nconst SANITIZE_R = /(javascript|vbscript|data(?!:image)):/i;\nconst SANITIZE_STRIP_R = /[^A-Za-z0-9/:]/g;\n\n/**\n * Sanitize URLs to prevent XSS attacks.\n * Returns null if the URL is unsafe.\n */\nexport const sanitizer = (input: string): string | null => {\n // `SANITIZE_R` only ever matches on a colon, and decoding can introduce one\n // solely through a percent escape — so a value with neither is safe as-is,\n // and skipping the decode avoids the bulk of the work on ordinary links.\n if (input.indexOf(':') === -1 && input.indexOf('%') === -1) return input;\n\n try {\n const decoded = decodeURIComponent(input).replace(SANITIZE_STRIP_R, '');\n\n if (SANITIZE_R.test(decoded)) {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n );\n\n return null;\n }\n } catch (_e) {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n );\n\n // decodeURIComponent sometimes throws a URIError\n return null;\n }\n\n return input;\n};\n\n// ============================================================================\n// WHITESPACE NORMALIZATION\n// ============================================================================\n\n/**\n * Normalize whitespace in source string.\n */\nexport const normalizeWhitespace = (source: string): string =>\n // `\\r`, `\\f` and `\\t` are disjoint, so one pass over the source replaces\n // what used to take three full scans.\n source.replace(NORMALIZE_WHITESPACE_R, (match) => {\n if (match === '\\t') return ' ';\n if (match === '\\f') return '';\n\n return '\\n';\n });\n\n/**\n * Safely remove a uniform leading indentation from lines, but do NOT touch\n * the content inside fenced code blocks (``` or ~~~).\n *\n * Inside a fenced block the structural indentation is irrelevant: what matters\n * is the indentation of the opening fence itself, which is the only amount\n * CommonMark strips from the code lines. A block nested in an indented HTML\n * element but written with its fence at column 0 therefore keeps its code\n * verbatim, instead of losing the first level of indentation.\n */\nexport const trimLeadingWhitespaceOutsideFences = (\n text: string,\n whitespace: string\n): string => {\n if (!whitespace) return text;\n\n const lines = text.split('\\n');\n\n /** Indentation and marker of the fence currently open, if any. */\n let openFence: { indentation: string; marker: string } | null = null;\n\n const removePrefix = (line: string, prefix: string): string =>\n prefix && line.startsWith(prefix) ? line.slice(prefix.length) : line;\n\n // Outside fences, strip the base structural indentation from every line.\n // Lines that don't start with the whitespace prefix are left as-is.\n const result = lines\n .map((line) => {\n const fenceMatch = line.match(FENCE_DELIMITER_R);\n\n if (!openFence) {\n if (fenceMatch)\n openFence = { indentation: fenceMatch[1]!, marker: fenceMatch[2]! };\n return removePrefix(line, whitespace);\n }\n\n const isClosingFence = fenceMatch?.[2]?.startsWith(openFence.marker);\n const { indentation } = openFence;\n\n if (isClosingFence) openFence = null;\n\n return removePrefix(line, indentation);\n })\n .join('\\n');\n\n return result;\n};\n\n/**\n * Normalize HTML attribute key to JSX prop name.\n */\nexport const normalizeAttributeKey = (key: string): string => {\n const hyphenIndex = key.indexOf('-');\n\n if (hyphenIndex !== -1 && key.match(HTML_CUSTOM_ATTR_R) === null) {\n key = key.replace(CAPTURE_LETTER_AFTER_HYPHEN, (_, letter) => {\n return letter.toUpperCase();\n });\n }\n\n return key;\n};\n\ntype StyleTuple = [key: string, value: string];\n\n/**\n * Parse a CSS style string into an array of [key, value] tuples.\n */\nexport const parseStyleAttribute = (styleString: string): StyleTuple[] => {\n const styles: StyleTuple[] = [];\n let buffer = '';\n let inUrl = false;\n let inQuotes = false;\n let quoteChar: '\"' | \"'\" | '' = '';\n\n if (!styleString) return styles;\n\n for (let i = 0; i < styleString.length; i++) {\n const char = styleString[i];\n\n if ((char === '\"' || char === \"'\") && !inUrl) {\n if (!inQuotes) {\n inQuotes = true;\n quoteChar = char;\n } else if (char === quoteChar) {\n inQuotes = false;\n quoteChar = '';\n }\n }\n\n if (char === '(' && buffer.endsWith('url')) {\n inUrl = true;\n } else if (char === ')' && inUrl) {\n inUrl = false;\n }\n\n if (char === ';' && !inQuotes && !inUrl) {\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n buffer = '';\n } else {\n buffer += char;\n }\n }\n\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n\n return styles;\n};\n\n/**\n * Convert an attribute value to a Node prop value.\n */\nexport const attributeValueToNodePropValue = (\n tag: string,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null\n): any => {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n (styles, [styleKey, styleValue]) => {\n const camelCasedKey = styleKey.replace(/(-[a-z])/g, (substr) =>\n substr[1]!.toUpperCase()\n );\n\n (styles as Record<string, any>)[camelCasedKey] = sanitizeUrlFn(\n styleValue,\n tag,\n styleKey\n );\n\n return styles;\n },\n {} as Record<string, any>\n );\n } else if (ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(unescapeString(value), tag, key);\n } else if (value.match(INTERPOLATION_R)) {\n value = unescapeString(value.slice(1, value.length - 1));\n }\n\n if (value === 'true') {\n return true;\n } else if (value === 'false') {\n return false;\n }\n\n return value;\n};\n\n// ============================================================================\n// TABLE PARSING\n// ============================================================================\n\n/**\n * Parse table alignment from a separator row.\n */\nexport const parseTableAlignCapture = (\n alignCapture: string\n): 'left' | 'right' | 'center' => {\n if (TABLE_RIGHT_ALIGN.test(alignCapture)) {\n return 'right';\n } else if (TABLE_CENTER_ALIGN.test(alignCapture)) {\n return 'center';\n } else if (TABLE_LEFT_ALIGN.test(alignCapture)) {\n return 'left';\n }\n\n return 'left';\n};\n\n/**\n * Parse table alignment row.\n */\nexport const parseTableAlign = (\n source: string\n): ('left' | 'right' | 'center')[] => {\n const alignText = source.replace(TABLE_TRIM_PIPES, '').split('|');\n return alignText.map(parseTableAlignCapture);\n};\n\n/**\n * Parse a single table row.\n */\nexport const parseTableRow = (\n source: string,\n parse: NestedParser,\n state: ParseState,\n tableOutput: boolean\n): ParserResult[][] => {\n const prevInTable = state.inTable;\n\n state.inTable = true;\n\n const cells: ParserResult[][] = [[]];\n let acc = '';\n\n const flush = (): void => {\n if (!acc) return;\n\n const cell = cells[cells.length - 1]!;\n cell.push.apply(cell, parse(acc, state));\n acc = '';\n };\n\n source\n .trim()\n .split(/(`[^`]*`|\\\\\\||\\|)/)\n .filter(Boolean)\n .forEach((fragment, i, arr) => {\n if (fragment.trim() === '|') {\n flush();\n\n if (tableOutput) {\n if (i !== 0 && i !== arr.length - 1) {\n cells.push([]);\n }\n\n return;\n }\n }\n\n acc += fragment;\n });\n\n flush();\n\n state.inTable = prevInTable;\n\n return cells;\n};\n\n/**\n * Parse table cells (multiple rows).\n */\nexport const parseTableCells = (\n source: string,\n parse: NestedParser,\n state: ParseState\n): ParserResult[][][] => {\n const rowsText = source.trim().split('\\n');\n\n const result = rowsText.map((rowText) =>\n parseTableRow(rowText, parse, state, true)\n );\n\n return result;\n};\n\n// ============================================================================\n// PARSING HELPERS\n// ============================================================================\n\n/**\n * Check if a rule qualifies for the current source and state.\n */\nexport const qualifies = (\n source: string,\n state: ParseState,\n qualify: NonNullable<Rule<any>['_qualify']>\n): boolean => {\n if (Array.isArray(qualify)) {\n for (let i = 0; i < qualify.length; i++) {\n if (startsWith(source, qualify[i]!)) return true;\n }\n\n return false;\n }\n\n return (qualify as (source: string, state: ParseState) => boolean)(\n source,\n state\n );\n};\n\n/**\n * Marks a matcher function as eligible for being run inside an inline context.\n */\nexport const allowInline = <T extends (...args: any[]) => any>(\n fn: T\n): T & { inline: 1 } => {\n (fn as any).inline = 1;\n return fn as T & { inline: 1 };\n};\n\n/**\n * Creates a match function for an inline scoped element from a regex.\n */\nexport const inlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for inline elements except links.\n */\nexport const simpleInlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for a block scoped element from a regex.\n */\nexport const blockRegex =\n (regex: RegExp) =>\n (source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return null;\n } else {\n return regex.exec(source);\n }\n };\n\n/**\n * Creates a match function from a regex, ignoring block/inline scope.\n */\nexport const anyScopeRegex = (\n fn: RegExp | ((source: string, state: ParseState) => RegExpMatchArray | null)\n) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (typeof fn === 'function') {\n return fn(source, state);\n }\n return fn.exec(source);\n });\n\n/**\n * Parse inline content (including links).\n */\nexport const parseInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n state.inline = true;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n return result;\n};\n\n/**\n * Parse simple inline content (no links).\n */\nexport const parseSimpleInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n\n state.inline = false;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n return result;\n};\n\n/**\n * Parse block content.\n */\nexport const parseBlock = (\n parse: NestedParser,\n children: string,\n state: ParseState = {}\n): ParserResult[] => {\n const isCurrentlyInline = state.inline || false;\n state.inline = false;\n const normalizedChildren = trimEnd(children);\n const needsTerminator = /\\n\\n$/.test(normalizedChildren) === false;\n const blockInput = needsTerminator\n ? normalizedChildren.endsWith('\\n')\n ? `${normalizedChildren}\\n`\n : `${normalizedChildren}\\n\\n`\n : normalizedChildren;\n\n const result = parse(blockInput, state);\n state.inline = isCurrentlyInline;\n\n return result;\n};\n\n/**\n * Helper to parse capture group 2 as inline content.\n */\nexport const parseCaptureInline = (\n capture: RegExpMatchArray,\n parse: NestedParser,\n state: ParseState\n): { children: ParserResult[] } => {\n return {\n children: parseInline(parse, capture[2] ?? '', state),\n };\n};\n\n/**\n * Helper that captures nothing (empty object).\n */\nexport const captureNothing = (): Record<string, never> => ({});\n\n/**\n * Helper that renders nothing (null).\n */\nexport const renderNothing = (): null => null;\n\n/**\n * Check if any regex in a list matches the input.\n */\nexport const some = (regexes: RegExp[], input: string): boolean => {\n for (let i = 0; i < regexes.length; i++) {\n if (regexes[i]!.test(input)) {\n return true;\n }\n }\n return false;\n};\n"],"mappings":"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"}
@@ -77,8 +77,10 @@ import { checkIsURLAbsolute } from "./utils/checkIsURLAbsolute.mjs";
77
77
  import { getPathWithoutLocale } from "./localization/getPathWithoutLocale.mjs";
78
78
  import { comparePaths, normalizePath } from "./localization/comparePaths.mjs";
79
79
  import { getDomainHostname, getDomainOrigin, getLocaleFromDomain, isLocaleExclusiveOnDomain } from "./localization/domainUtils.mjs";
80
+ import { getRewriteRules } from "./localization/rewriteMatch.mjs";
81
+ import { getCanonicalPath } from "./localization/getCanonicalPath.mjs";
80
82
  import { getPrefix, isDeclaredLocale } from "./localization/getPrefix.mjs";
81
- import { getCanonicalPath, getInternalPath, getRewritePath, getRewriteRules, resolveLocalizedPath } from "./localization/rewriteUtils.mjs";
83
+ import { getInternalPath, getRewritePath, resolveLocalizedPath } from "./localization/rewriteUtils.mjs";
82
84
  import { getLocalizedPath } from "./localization/getLocalizedPath.mjs";
83
85
  import { getLocalizedUrl } from "./localization/getLocalizedUrl.mjs";
84
86
  import { getMultilingualUrls } from "./localization/getMultilingualUrls.mjs";
@@ -97,7 +99,7 @@ import { localeFlatMap, localeMap, localeRecord } from "./localization/localeMap
97
99
  import { formatProxyEnabledMessage, isProxyStorageLocaleEnabled, resolveProxyMode } from "./localization/proxyMode.mjs";
98
100
  import { getPreloadLocale, resolveBrowserLocale } from "./localization/resolveBrowserLocale.mjs";
99
101
  import { validatePrefix } from "./localization/validatePrefix.mjs";
100
- import { ATTRIBUTES_TO_SANITIZE, ATTRIBUTE_TO_NODE_PROP_MAP, ATTR_EXTRACTOR_R, BLOCKQUOTE_ALERT_R, BLOCKQUOTE_R, BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, BLOCK_END_R, BREAK_LINE_R, BREAK_THEMATIC_R, CAPTURE_LETTER_AFTER_HYPHEN, CODE_BLOCK_FENCED_R, CODE_BLOCK_R, CODE_INLINE_R, CONSECUTIVE_NEWLINE_R, CR_NEWLINE_R, CUSTOM_COMPONENT_R, DO_NOT_PROCESS_HTML_ELEMENTS, DURATION_DELAY_TRIGGER, FENCE_DELIMITER_R, FOOTNOTE_R, FOOTNOTE_REFERENCE_R, FORMFEED_R, FRONT_MATTER_R, GFM_TASK_R, HEADING_ATX_COMPLIANT_R, HEADING_R, HEADING_SETEXT_R, HTML_BLOCK_ELEMENT_R, HTML_CHAR_CODE_R, HTML_COMMENT_R, HTML_CUSTOM_ATTR_R, HTML_LEFT_TRIM_AMOUNT_R, HTML_SELF_CLOSING_ELEMENT_R, INLINE_SKIP_R, INTERPOLATION_R, LINK_AUTOLINK_BARE_URL_R, LINK_AUTOLINK_R, LIST_LOOKBEHIND_R, LOOKAHEAD, NAMED_CODES_TO_UNICODE, NP_TABLE_R, ORDERED, ORDERED_LIST_BULLET, ORDERED_LIST_ITEM_PREFIX, ORDERED_LIST_ITEM_PREFIX_R, ORDERED_LIST_ITEM_R, ORDERED_LIST_R, PARAGRAPH_R, Priority, REFERENCE_IMAGE_OR_LINK, REFERENCE_IMAGE_R, REFERENCE_LINK_R, RuleType, SHORTCODE_R, SHOULD_RENDER_AS_BLOCK_R, TABLE_CENTER_ALIGN, TABLE_LEFT_ALIGN, TABLE_RIGHT_ALIGN, TABLE_TRIM_PIPES, TAB_R, TEXT_BOLD_R, TEXT_EMPHASIZED_R, TEXT_ESCAPED_R, TEXT_MARKED_R, TEXT_PLAIN_R, TEXT_STRIKETHROUGHED_R, TRIM_STARTING_NEWLINES, UNESCAPE_R, UNORDERED, UNORDERED_LIST_BULLET, UNORDERED_LIST_ITEM_PREFIX, UNORDERED_LIST_ITEM_PREFIX_R, UNORDERED_LIST_ITEM_R, UNORDERED_LIST_R, generateListItemPrefix, generateListItemPrefixRegex, generateListItemRegex, generateListRegex } from "./markdown/constants.mjs";
102
+ import { ATTRIBUTES_TO_SANITIZE, ATTRIBUTE_TO_NODE_PROP_MAP, ATTR_EXTRACTOR_R, BLOCKQUOTE_ALERT_R, BLOCKQUOTE_R, BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, BLOCK_END_R, BREAK_LINE_R, BREAK_THEMATIC_R, CAPTURE_LETTER_AFTER_HYPHEN, CODE_BLOCK_FENCED_R, CODE_BLOCK_R, CODE_INLINE_R, CONSECUTIVE_NEWLINE_R, CR_NEWLINE_R, CUSTOM_COMPONENT_OPENING_TAG_R, CUSTOM_COMPONENT_R, DO_NOT_PROCESS_HTML_ELEMENTS, FENCE_DELIMITER_R, FOOTNOTE_R, FOOTNOTE_REFERENCE_R, FORMFEED_R, FRONT_MATTER_R, GFM_TASK_R, HEADING_ATX_COMPLIANT_R, HEADING_R, HEADING_SETEXT_R, HTML_BLOCK_ELEMENT_R, HTML_BLOCK_OPENING_TAG_R, HTML_CHAR_CODE_R, HTML_COMMENT_R, HTML_CUSTOM_ATTR_R, HTML_LEFT_TRIM_AMOUNT_R, HTML_SELF_CLOSING_ELEMENT_R, HTML_SELF_CLOSING_OPENING_TAG_R, INLINE_SKIP_R, INTERPOLATION_R, LINK_AUTOLINK_BARE_URL_R, LINK_AUTOLINK_R, LOOKAHEAD, NAMED_CODES_TO_UNICODE, NORMALIZE_WHITESPACE_R, NP_TABLE_R, ORDERED, ORDERED_LIST_BULLET, ORDERED_LIST_ITEM_PREFIX, ORDERED_LIST_ITEM_PREFIX_R, ORDERED_LIST_ITEM_R, ORDERED_LIST_R, PARAGRAPH_R, Priority, REFERENCE_IMAGE_OR_LINK, REFERENCE_IMAGE_R, REFERENCE_LINK_R, RuleType, SHORTCODE_R, SHOULD_RENDER_AS_BLOCK_R, TABLE_CENTER_ALIGN, TABLE_LEFT_ALIGN, TABLE_RIGHT_ALIGN, TABLE_TRIM_PIPES, TAB_R, TEXT_BOLD_R, TEXT_EMPHASIZED_R, TEXT_ESCAPED_R, TEXT_MARKED_R, TEXT_PLAIN_R, TEXT_STRIKETHROUGHED_R, TRIM_STARTING_NEWLINES, UNESCAPE_R, UNORDERED, UNORDERED_LIST_BULLET, UNORDERED_LIST_ITEM_PREFIX, UNORDERED_LIST_ITEM_PREFIX_R, UNORDERED_LIST_ITEM_R, UNORDERED_LIST_R, generateListItemPrefix, generateListItemPrefixRegex, generateListItemRegex, generateListRegex } from "./markdown/constants.mjs";
101
103
  import { allowInline, anyScopeRegex, attributeValueToNodePropValue, blockRegex, captureNothing, cx, get, inlineRegex, normalizeAttributeKey, normalizeWhitespace, parseBlock, parseCaptureInline, parseInline, parseSimpleInline, parseStyleAttribute, parseTableAlign, parseTableAlignCapture, parseTableCells, parseTableRow, qualifies, renderNothing, sanitizer, simpleInlineRegex, slugify, some, startsWith, trimEnd, trimLeadingWhitespaceOutsideFences, unescapeString, unquote } from "./markdown/utils.mjs";
102
104
  import { parserFor } from "./markdown/parser.mjs";
103
105
  import { createRenderer, renderFor } from "./markdown/renderer.mjs";
@@ -111,4 +113,4 @@ import { interpolateMessage, parseTaggedMessage, resolveMessage, resolveMessageN
111
113
  import { isSameKeyPath } from "./utils/isSameKeyPath.mjs";
112
114
  import { stringifyYaml } from "./utils/stringifyYaml.mjs";
113
115
 
114
- export { ATTRIBUTES_TO_SANITIZE, ATTRIBUTE_TO_NODE_PROP_MAP, ATTR_EXTRACTOR_R, BLOCKQUOTE_ALERT_R, BLOCKQUOTE_R, BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, BLOCK_END_R, BREAK_LINE_R, BREAK_THEMATIC_R, CAPTURE_LETTER_AFTER_HYPHEN, CODE_BLOCK_FENCED_R, CODE_BLOCK_R, CODE_INLINE_R, COMPOSITE_ID_SEPARATOR, CONSECUTIVE_NEWLINE_R, CR_NEWLINE_R, CUSTOM_COMPONENT_R, CachedIntl, CachedIntl as Intl, DEFAULT_VARIANT_ID, DO_NOT_PROCESS_HTML_ELEMENTS, DURATION_DELAY_TRIGGER, FENCE_DELIMITER_R, FOOTNOTE_R, FOOTNOTE_REFERENCE_R, FORMFEED_R, FRONT_MATTER_R, GFM_TASK_R, HEADING_ATX_COMPLIANT_R, HEADING_R, HEADING_SETEXT_R, HTML_BLOCK_ELEMENT_R, HTML_CHAR_CODE_R, HTML_COMMENT_R, HTML_CUSTOM_ATTR_R, HTML_LEFT_TRIM_AMOUNT_R, HTML_SELF_CLOSING_ELEMENT_R, HTML_TAGS, INLINE_SKIP_R, INTERPOLATION_R, LINK_AUTOLINK_BARE_URL_R, LINK_AUTOLINK_R, LIST_LOOKBEHIND_R, LOOKAHEAD, LocaleStorage, LocaleStorageClient, LocaleStorageServer, NAMED_CODES_TO_UNICODE, NP_TABLE_R, ORDERED, ORDERED_LIST_BULLET, ORDERED_LIST_ITEM_PREFIX, ORDERED_LIST_ITEM_PREFIX_R, ORDERED_LIST_ITEM_R, ORDERED_LIST_R, PARAGRAPH_R, PRELOADED_DYNAMIC_KEY, Priority, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, REFERENCE_IMAGE_OR_LINK, REFERENCE_IMAGE_R, REFERENCE_LINK_R, RuleType, SHORTCODE_R, SHOULD_RENDER_AS_BLOCK_R, TABLE_CENTER_ALIGN, TABLE_LEFT_ALIGN, TABLE_RIGHT_ALIGN, TABLE_TRIM_PIPES, TAB_R, TEXT_BOLD_R, TEXT_EMPHASIZED_R, TEXT_ESCAPED_R, TEXT_MARKED_R, TEXT_PLAIN_R, TEXT_STRIKETHROUGHED_R, TRIM_STARTING_NEWLINES, UNESCAPE_R, UNORDERED, UNORDERED_LIST_BULLET, UNORDERED_LIST_ITEM_PREFIX, UNORDERED_LIST_ITEM_PREFIX_R, UNORDERED_LIST_ITEM_R, UNORDERED_LIST_R, VOID_HTML_ELEMENTS, allowInline, anyScopeRegex, attributeValueToNodePropValue, bindIntl, blockRegex, buildMaskPlugin, captureNothing, checkIsURLAbsolute, checkMissingLocalesPlugin, compact, comparePaths, compile, compileWithOptions, condition as cond, conditionPlugin, createCompiler, createRenderer, currency, cx, date, deepTransformNode, editDictionaryByKeyPath, enumeration as enu, enumerationPlugin, fallbackPlugin, filePlugin, filterMissingTranslationsOnlyPlugin, filterTranslationsOnlyPlugin, findMatchingCondition, findPlainDynamicLoader, formatProxyEnabledMessage, gender, genderPlugin, generateListItemPrefix, generateListItemPrefixRegex, generateListItemRegex, generateListRegex, generateSitemap, generateSitemapUrl, get, getBasePlugins, getBrowserLocale, getCachedIntl, getCanonicalPath, getCondition, getContent, getContentNodeByKeyPath, getCookie, getDefaultNode, getDictionary, getDictionaryAsync, getDictionaryCompositeIds, getDictionaryQualifierIds, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, getDictionaryTransformCacheKey, getDomainHostname, getDomainOrigin, getEditedContent, getEditedDictionary, getEmptyNode, getEnumeration, getFilterMissingTranslationsContent, getFilterMissingTranslationsDictionary, getFilterTranslationsOnlyContent, getFilterTranslationsOnlyDictionary, getFilteredLocalesContent, getFilteredLocalesDictionary, getGender, getHTML, getHTMLTextDir, getInsertion, getInsertionValues, getInternalPath, getInterpolableContent, getIntlayer, getIntlayerAsync, getLocale, getLocaleFromDomain, getLocaleFromPath, getLocaleFromStorage, getLocaleFromStorageClient, getLocaleFromStorageServer, getLocaleLang, getLocaleName, getLocalizedContent, getLocalizedPath, getLocalizedUrl, getMarkdownMetadata, getMaskContent, getMissingLocalesContent, getMissingLocalesContentFromDictionary, getMultilingualDictionary, getMultilingualUrls, getNestedDictionaryGraph, getNestedDictionaryKeys, getNestedDictionaryReferences, getNesting, getNodeChildren, getNodeType, getPathWithoutLocale, getPerLocaleDictionary, getPluginsCacheKey, getPlural, getPrefix, getPreloadLocale, getPreloadedDictionary, getReplacedValuesContent, getRewritePath, getRewriteRules, getSelect, getSplittedContent, getSplittedDictionaryContent, getTranslation, getVariantIds, html, i18nextToIntlayerFormatter, icuToIntlayerFormatter, inlineRegex, insertion as insert, insertContentInDictionary, insertionPlugin, interpolateMessage, intlayerToI18nextFormatter, intlayerToICUFormatter, intlayerToPortableObjectFormatter, intlayerToVueI18nFormatter, isDeclaredLocale, isInterpolableWrapperNode, isLocaleExclusiveOnDomain, isProxyStorageLocaleEnabled, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, isSameKeyPath, isValidElement, list, localeDetector, localeFlatMap, localeMap, localeRecord, localeResolver, localeStorageOptions, markdown as md, mergeDictionaries, mergeQualifiedDictionaries, navigatePath, nesting as nest, nestedPlugin, normalizeAttributeKey, normalizeDictionaries, normalizeDictionary, normalizePath, normalizeWhitespace, number, orderDictionaries, parseBlock, parseCaptureInline, parseDictionarySelector, parseInline, parseMarkdown, parseSimpleInline, parseStyleAttribute, parseTableAlign, parseTableAlignCapture, parseTableCells, parseTableRow, parseTaggedMessage, parseYaml, parserFor, percentage, plural, pluralPlugin, portableObjectToIntlayerFormatter, presets, qualifies, readTransformCache, rebuildInterpolableContent, reconstructQualifiedEntry, relativeTime, removeContentNodeByKeyPath, renameContentNodeByKeyPath, renderFor, renderMarkdownAst, renderNothing, resolveBrowserLocale, resolveDictionaryArgument, resolveEffectiveVariantId, resolveLocalizedPath, resolveMessage, resolveMessageNode, resolvePlainDynamicLoader, resolveProviderVariant, resolveProxyMode, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, sanitizer, select, selectPlugin, serializeVariant, serializeVariantChain, setLocaleInStorage, setLocaleInStorageClient, setLocaleInStorageServer, simpleInlineRegex, slugify, some, splitInsertionTemplate, startsWith, stringifyYaml, translation as t, transformInterpolableNode, translationPlugin, trimEnd, trimLeadingWhitespaceOutsideFences, unescapeString, units, unquote, updateNodeChildren, validateHTML, validateMarkdown, validatePrefix, vueI18nToIntlayerFormatter, writeTransformCache };
116
+ export { ATTRIBUTES_TO_SANITIZE, ATTRIBUTE_TO_NODE_PROP_MAP, ATTR_EXTRACTOR_R, BLOCKQUOTE_ALERT_R, BLOCKQUOTE_R, BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, BLOCK_END_R, BREAK_LINE_R, BREAK_THEMATIC_R, CAPTURE_LETTER_AFTER_HYPHEN, CODE_BLOCK_FENCED_R, CODE_BLOCK_R, CODE_INLINE_R, COMPOSITE_ID_SEPARATOR, CONSECUTIVE_NEWLINE_R, CR_NEWLINE_R, CUSTOM_COMPONENT_OPENING_TAG_R, CUSTOM_COMPONENT_R, CachedIntl, CachedIntl as Intl, DEFAULT_VARIANT_ID, DO_NOT_PROCESS_HTML_ELEMENTS, FENCE_DELIMITER_R, FOOTNOTE_R, FOOTNOTE_REFERENCE_R, FORMFEED_R, FRONT_MATTER_R, GFM_TASK_R, HEADING_ATX_COMPLIANT_R, HEADING_R, HEADING_SETEXT_R, HTML_BLOCK_ELEMENT_R, HTML_BLOCK_OPENING_TAG_R, HTML_CHAR_CODE_R, HTML_COMMENT_R, HTML_CUSTOM_ATTR_R, HTML_LEFT_TRIM_AMOUNT_R, HTML_SELF_CLOSING_ELEMENT_R, HTML_SELF_CLOSING_OPENING_TAG_R, HTML_TAGS, INLINE_SKIP_R, INTERPOLATION_R, LINK_AUTOLINK_BARE_URL_R, LINK_AUTOLINK_R, LOOKAHEAD, LocaleStorage, LocaleStorageClient, LocaleStorageServer, NAMED_CODES_TO_UNICODE, NORMALIZE_WHITESPACE_R, NP_TABLE_R, ORDERED, ORDERED_LIST_BULLET, ORDERED_LIST_ITEM_PREFIX, ORDERED_LIST_ITEM_PREFIX_R, ORDERED_LIST_ITEM_R, ORDERED_LIST_R, PARAGRAPH_R, PRELOADED_DYNAMIC_KEY, Priority, QUALIFIER_DYNAMIC_TYPES_KEY, QUALIFIER_ORDER, REFERENCE_IMAGE_OR_LINK, REFERENCE_IMAGE_R, REFERENCE_LINK_R, RuleType, SHORTCODE_R, SHOULD_RENDER_AS_BLOCK_R, TABLE_CENTER_ALIGN, TABLE_LEFT_ALIGN, TABLE_RIGHT_ALIGN, TABLE_TRIM_PIPES, TAB_R, TEXT_BOLD_R, TEXT_EMPHASIZED_R, TEXT_ESCAPED_R, TEXT_MARKED_R, TEXT_PLAIN_R, TEXT_STRIKETHROUGHED_R, TRIM_STARTING_NEWLINES, UNESCAPE_R, UNORDERED, UNORDERED_LIST_BULLET, UNORDERED_LIST_ITEM_PREFIX, UNORDERED_LIST_ITEM_PREFIX_R, UNORDERED_LIST_ITEM_R, UNORDERED_LIST_R, VOID_HTML_ELEMENTS, allowInline, anyScopeRegex, attributeValueToNodePropValue, bindIntl, blockRegex, buildMaskPlugin, captureNothing, checkIsURLAbsolute, checkMissingLocalesPlugin, compact, comparePaths, compile, compileWithOptions, condition as cond, conditionPlugin, createCompiler, createRenderer, currency, cx, date, deepTransformNode, editDictionaryByKeyPath, enumeration as enu, enumerationPlugin, fallbackPlugin, filePlugin, filterMissingTranslationsOnlyPlugin, filterTranslationsOnlyPlugin, findMatchingCondition, findPlainDynamicLoader, formatProxyEnabledMessage, gender, genderPlugin, generateListItemPrefix, generateListItemPrefixRegex, generateListItemRegex, generateListRegex, generateSitemap, generateSitemapUrl, get, getBasePlugins, getBrowserLocale, getCachedIntl, getCanonicalPath, getCondition, getContent, getContentNodeByKeyPath, getCookie, getDefaultNode, getDictionary, getDictionaryAsync, getDictionaryCompositeIds, getDictionaryQualifierIds, getDictionaryQualifierTypes, getDictionarySelectorCacheKey, getDictionaryTransformCacheKey, getDomainHostname, getDomainOrigin, getEditedContent, getEditedDictionary, getEmptyNode, getEnumeration, getFilterMissingTranslationsContent, getFilterMissingTranslationsDictionary, getFilterTranslationsOnlyContent, getFilterTranslationsOnlyDictionary, getFilteredLocalesContent, getFilteredLocalesDictionary, getGender, getHTML, getHTMLTextDir, getInsertion, getInsertionValues, getInternalPath, getInterpolableContent, getIntlayer, getIntlayerAsync, getLocale, getLocaleFromDomain, getLocaleFromPath, getLocaleFromStorage, getLocaleFromStorageClient, getLocaleFromStorageServer, getLocaleLang, getLocaleName, getLocalizedContent, getLocalizedPath, getLocalizedUrl, getMarkdownMetadata, getMaskContent, getMissingLocalesContent, getMissingLocalesContentFromDictionary, getMultilingualDictionary, getMultilingualUrls, getNestedDictionaryGraph, getNestedDictionaryKeys, getNestedDictionaryReferences, getNesting, getNodeChildren, getNodeType, getPathWithoutLocale, getPerLocaleDictionary, getPluginsCacheKey, getPlural, getPrefix, getPreloadLocale, getPreloadedDictionary, getReplacedValuesContent, getRewritePath, getRewriteRules, getSelect, getSplittedContent, getSplittedDictionaryContent, getTranslation, getVariantIds, html, i18nextToIntlayerFormatter, icuToIntlayerFormatter, inlineRegex, insertion as insert, insertContentInDictionary, insertionPlugin, interpolateMessage, intlayerToI18nextFormatter, intlayerToICUFormatter, intlayerToPortableObjectFormatter, intlayerToVueI18nFormatter, isDeclaredLocale, isInterpolableWrapperNode, isLocaleExclusiveOnDomain, isProxyStorageLocaleEnabled, isQualifiedDictionaryGroup, isQualifiedDynamicLoaderMap, isSameKeyPath, isValidElement, list, localeDetector, localeFlatMap, localeMap, localeRecord, localeResolver, localeStorageOptions, markdown as md, mergeDictionaries, mergeQualifiedDictionaries, navigatePath, nesting as nest, nestedPlugin, normalizeAttributeKey, normalizeDictionaries, normalizeDictionary, normalizePath, normalizeWhitespace, number, orderDictionaries, parseBlock, parseCaptureInline, parseDictionarySelector, parseInline, parseMarkdown, parseSimpleInline, parseStyleAttribute, parseTableAlign, parseTableAlignCapture, parseTableCells, parseTableRow, parseTaggedMessage, parseYaml, parserFor, percentage, plural, pluralPlugin, portableObjectToIntlayerFormatter, presets, qualifies, readTransformCache, rebuildInterpolableContent, reconstructQualifiedEntry, relativeTime, removeContentNodeByKeyPath, renameContentNodeByKeyPath, renderFor, renderMarkdownAst, renderNothing, resolveBrowserLocale, resolveDictionaryArgument, resolveEffectiveVariantId, resolveLocalizedPath, resolveMessage, resolveMessageNode, resolvePlainDynamicLoader, resolveProviderVariant, resolveProxyMode, resolveQualifiedDictionary, resolveQualifiedDynamicContent, resolveQualifiedDynamicContentAsync, sanitizer, select, selectPlugin, serializeVariant, serializeVariantChain, setLocaleInStorage, setLocaleInStorageClient, setLocaleInStorageServer, simpleInlineRegex, slugify, some, splitInsertionTemplate, startsWith, stringifyYaml, translation as t, transformInterpolableNode, translationPlugin, trimEnd, trimLeadingWhitespaceOutsideFences, unescapeString, units, unquote, updateNodeChildren, validateHTML, validateMarkdown, validatePrefix, vueI18nToIntlayerFormatter, writeTransformCache };
@@ -0,0 +1,51 @@
1
+ import { extractParams, fillPath, getRewriteRules } from "./rewriteMatch.mjs";
2
+ import { routing } from "@intlayer/config/built";
3
+
4
+ //#region src/localization/getCanonicalPath.ts
5
+ /**
6
+ * Decodes percent-encoding so an encoded pathname
7
+ * (`/doc/%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9/v8`, as `URL.pathname` and the
8
+ * router hand it over) matches a rewrite pattern written with its literal
9
+ * characters (`/doc/リリース/v8`). Reserved delimiters stay encoded, and a path
10
+ * with no escape — or a malformed one — is returned untouched.
11
+ */
12
+ const decodePath = (path) => {
13
+ if (!path.includes("%")) return path;
14
+ try {
15
+ return decodeURI(path);
16
+ } catch {
17
+ return path;
18
+ }
19
+ };
20
+ /**
21
+ * Given a localized URL (e.g., "/produits/123"), finds the canonical internal path (e.g., "/products/123").
22
+ * If locale is provided, only check for that locale. Otherwise, check for all locales.
23
+ *
24
+ * The lookup is encoding-insensitive: a percent-encoded path matches a pattern
25
+ * written with literal (non-ASCII) characters.
26
+ *
27
+ * @param localizedPath - The path as seen in the browser, without locale prefix.
28
+ * @param locale - Restricts the lookup to that locale's rules. Defaults to every locale.
29
+ * @param rewriteRules - Raw `routing.rewrite` configuration or already-normalized
30
+ * rules. Defaults to the project configuration's `routing.rewrite`.
31
+ */
32
+ const getCanonicalPath = (localizedPath, locale, rewriteRules) => {
33
+ const rules = getRewriteRules(rewriteRules ?? routing?.rewrite, "url");
34
+ if (!rules || process.env.INTLAYER_ROUTING_REWRITE_RULES && process.env.INTLAYER_ROUTING_REWRITE_RULES === "false") return localizedPath;
35
+ const pathToMatch = decodePath(localizedPath);
36
+ for (const rule of rules.rules) {
37
+ const { canonical, localized } = rule;
38
+ const localesToCheck = locale ? [locale] : Object.keys(localized);
39
+ for (const locale of localesToCheck) {
40
+ const localizedPattern = localized[locale];
41
+ if (!localizedPattern) continue;
42
+ const params = extractParams(pathToMatch, localizedPattern);
43
+ if (params) return fillPath(canonical, params);
44
+ }
45
+ }
46
+ return localizedPath;
47
+ };
48
+
49
+ //#endregion
50
+ export { getCanonicalPath };
51
+ //# sourceMappingURL=getCanonicalPath.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCanonicalPath.mjs","names":[],"sources":["../../../src/localization/getCanonicalPath.ts"],"sourcesContent":["import { routing } from '@intlayer/config/built';\nimport type { RewriteRules, RoutingConfig } from '@intlayer/types/config';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { extractParams, fillPath, getRewriteRules } from './rewriteMatch';\n\n/**\n * Decodes percent-encoding so an encoded pathname\n * (`/doc/%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9/v8`, as `URL.pathname` and the\n * router hand it over) matches a rewrite pattern written with its literal\n * characters (`/doc/リリース/v8`). Reserved delimiters stay encoded, and a path\n * with no escape — or a malformed one — is returned untouched.\n */\nconst decodePath = (path: string): string => {\n if (!path.includes('%')) return path;\n\n try {\n return decodeURI(path);\n } catch {\n return path;\n }\n};\n\n/**\n * Given a localized URL (e.g., \"/produits/123\"), finds the canonical internal path (e.g., \"/products/123\").\n * If locale is provided, only check for that locale. Otherwise, check for all locales.\n *\n * The lookup is encoding-insensitive: a percent-encoded path matches a pattern\n * written with literal (non-ASCII) characters.\n *\n * @param localizedPath - The path as seen in the browser, without locale prefix.\n * @param locale - Restricts the lookup to that locale's rules. Defaults to every locale.\n * @param rewriteRules - Raw `routing.rewrite` configuration or already-normalized\n * rules. Defaults to the project configuration's `routing.rewrite`.\n */\nexport const getCanonicalPath = <\n const Path extends string,\n const Locale extends LocalesValues = LocalesValues,\n>(\n localizedPath: Path,\n locale?: Locale,\n rewriteRules?: RoutingConfig['rewrite'] | RewriteRules\n): string => {\n const rules = getRewriteRules(rewriteRules ?? routing?.rewrite, 'url');\n\n if (\n !rules ||\n (process.env.INTLAYER_ROUTING_REWRITE_RULES &&\n process.env.INTLAYER_ROUTING_REWRITE_RULES === 'false')\n )\n return localizedPath;\n\n const pathToMatch = decodePath(localizedPath);\n\n for (const rule of rules.rules) {\n const { canonical, localized } = rule;\n const localesToCheck = locale ? [locale] : Object.keys(localized);\n\n for (const locale of localesToCheck) {\n const localizedPattern = localized[locale as keyof typeof localized];\n\n if (!localizedPattern) continue;\n\n const params = extractParams(pathToMatch, localizedPattern);\n\n if (params) {\n return fillPath(canonical, params);\n }\n }\n }\n\n return localizedPath;\n};\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,cAAc,SAAyB;CAC3C,IAAI,CAAC,KAAK,SAAS,GAAG,GAAG,OAAO;CAEhC,IAAI;EACF,OAAO,UAAU,IAAI;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;AAcA,MAAa,oBAIX,eACA,QACA,iBACW;CACX,MAAM,QAAQ,gBAAgB,gBAAgB,SAAS,SAAS,KAAK;CAErE,IACE,CAAC,SACA,QAAQ,IAAI,kCACX,QAAQ,IAAI,mCAAmC,SAEjD,OAAO;CAET,MAAM,cAAc,WAAW,aAAa;CAE5C,KAAK,MAAM,QAAQ,MAAM,OAAO;EAC9B,MAAM,EAAE,WAAW,cAAc;EACjC,MAAM,iBAAiB,SAAS,CAAC,MAAM,IAAI,OAAO,KAAK,SAAS;EAEhE,KAAK,MAAM,UAAU,gBAAgB;GACnC,MAAM,mBAAmB,UAAU;GAEnC,IAAI,CAAC,kBAAkB;GAEvB,MAAM,SAAS,cAAc,aAAa,gBAAgB;GAE1D,IAAI,QACF,OAAO,SAAS,WAAW,MAAM;EAErC;CACF;CAEA,OAAO;AACT"}
@@ -0,0 +1,12 @@
1
+ import { getCanonicalPath } from "./getCanonicalPath.mjs";
2
+ import { describe, expectTypeOf, it } from "vitest";
3
+
4
+ //#region src/localization/getCanonicalPath.test-d.ts
5
+ describe("getCanonicalPath", () => {
6
+ it("should accept an omitted locale (checks every locale)", () => {
7
+ expectTypeOf(getCanonicalPath("/a-propos")).toEqualTypeOf();
8
+ });
9
+ });
10
+
11
+ //#endregion
12
+ //# sourceMappingURL=getCanonicalPath.test-d.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCanonicalPath.test-d.mjs","names":[],"sources":["../../../src/localization/getCanonicalPath.test-d.ts"],"sourcesContent":["import { describe, expectTypeOf, it } from 'vitest';\nimport { getCanonicalPath } from './getCanonicalPath';\n\ndescribe('getCanonicalPath', () => {\n it('should accept an omitted locale (checks every locale)', () => {\n expectTypeOf(getCanonicalPath('/a-propos')).toEqualTypeOf<string>();\n });\n});\n"],"mappings":";;;;AAGA,SAAS,0BAA0B;CACjC,GAAG,+DAA+D;EAChE,aAAa,iBAAiB,WAAW,CAAC,CAAC,CAAC,cAAsB;CACpE,CAAC;AACH,CAAC"}
@@ -1,6 +1,8 @@
1
1
  import { getPathWithoutLocale } from "./getPathWithoutLocale.mjs";
2
+ import { getRewriteRules } from "./rewriteMatch.mjs";
3
+ import { getCanonicalPath } from "./getCanonicalPath.mjs";
2
4
  import { getPrefix, resolveRoutingConfig } from "./getPrefix.mjs";
3
- import { getCanonicalPath, getRewriteRules, resolveLocalizedPath } from "./rewriteUtils.mjs";
5
+ import { resolveLocalizedPath } from "./rewriteUtils.mjs";
4
6
  import { internationalization } from "@intlayer/config/built";
5
7
 
6
8
  //#region src/localization/getLocalizedPath.ts
@@ -1 +1 @@
1
- {"version":3,"file":"getLocalizedPath.mjs","names":[],"sources":["../../../src/localization/getLocalizedPath.ts"],"sourcesContent":["import { internationalization } from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type {\n LocalesValues,\n LocalizedPathname,\n ResolvedDefaultLocale,\n} from '@intlayer/types/module_augmentation';\nimport { getPathWithoutLocale } from './getPathWithoutLocale';\nimport {\n getPrefix,\n type RoutingOptions,\n resolveRoutingConfig,\n} from './getPrefix';\nimport {\n getCanonicalPath,\n getRewriteRules,\n resolveLocalizedPath,\n} from './rewriteUtils';\n\n/**\n * Localizes an application path for a locale: resolves the `routing.rewrite`\n * rules, then applies the locale representation of the routing mode — a path\n * prefix, a `locale` search parameter, or nothing at all.\n *\n * Any query string and hash of the input are preserved.\n *\n * This is the relative half of {@link getLocalizedUrl}, which builds on it to\n * add an origin and cross-domain routing. For a relative input both return the\n * same value; this one never returns an absolute URL — the origin of an\n * absolute input is dropped and only its path is localized.\n *\n * Use `resolveLocalizedPath` instead to apply the rewrite rules alone, without\n * any locale representation.\n *\n * @example\n * ```ts\n * // routing: { mode: 'prefix-no-default', rewrite: { '/about': { fr: '/a-propos' } } }\n * getLocalizedPath('/about', 'fr'); // '/fr/a-propos'\n * getLocalizedPath('/about', 'en'); // '/about' (default locale, no prefix)\n * getLocalizedPath('/', 'fr'); // '/fr'\n * getLocalizedPath('/contact', 'fr'); // '/fr/contact' (no rewrite rule matches)\n * getLocalizedPath('https://intlayer.org/about', 'fr'); // '/fr/a-propos' (origin dropped)\n *\n * // routing: { domains: { zh: 'intlayer.cn' } } — zh is alone on that hostname\n * getLocalizedPath('/about', 'zh'); // '/about' (the domain identifies the locale)\n *\n * // Manual rules, bypassing the configuration\n * getLocalizedPath('/contact', 'fr', {\n * rewrite: { '/contact': { fr: '/contactez-nous' } },\n * });\n * // '/fr/contactez-nous'\n * ```\n *\n * @param canonicalPath - The internal application path (e.g. `/about`, `/product/123`).\n * An absolute URL is accepted; only its path, query and hash are kept.\n * @param locale - The target locale. Defaults to the configured default locale.\n * @param options - Routing overrides (`locales`, `defaultLocale`, `mode`, `rewrite`,\n * `domains`). Each one defaults to the project configuration. `domains` only\n * suppresses the prefix of a locale served from its own domain — the origin\n * itself is never emitted.\n * @returns The localized path for the target locale.\n */\nexport const getLocalizedPath = <\n const CanonicalPath extends string,\n const CurrentLocale extends LocalesValues = ResolvedDefaultLocale,\n>(\n canonicalPath: CanonicalPath,\n locale: CurrentLocale = internationalization?.defaultLocale as CurrentLocale,\n options: RoutingOptions = {}\n): LocalizedPathname<CanonicalPath, CurrentLocale> => {\n const { defaultLocale, mode, locales, rewrite, domains } =\n resolveRoutingConfig(options);\n\n const pathWithoutLocale = getPathWithoutLocale(canonicalPath, locales);\n const rewriteRules = getRewriteRules(rewrite, 'url');\n\n // Parsed against a dummy origin to split the path from its query and hash.\n // An absolute input parses on its own, and only its path is kept.\n const parsedPath = new URL(pathWithoutLocale, 'http://e.com');\n\n const translatedPathname = resolveLocalizedPath(\n getCanonicalPath(parsedPath.pathname, undefined, rewriteRules),\n locale as Locale,\n rewriteRules\n ).path;\n\n if (\n !(\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'no-prefix'\n ) &&\n mode === 'no-prefix'\n ) {\n return `${translatedPathname}${parsedPath.search}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n }\n\n if (\n !(\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'search-params'\n ) &&\n mode === 'search-params'\n ) {\n const searchParams = new URLSearchParams(parsedPath.search);\n\n searchParams.set('locale', locale.toString());\n\n const queryParams = searchParams.toString();\n\n return `${translatedPathname}${queryParams ? `?${queryParams}` : ''}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n }\n\n const { prefix } = getPrefix(locale, {\n defaultLocale,\n mode,\n locales,\n domains,\n });\n\n let localizedPath = `/${prefix}${translatedPathname}`.replace(/\\/+/g, '/');\n\n if (localizedPath.length > 1 && localizedPath.endsWith('/')) {\n localizedPath = localizedPath.slice(0, -1);\n }\n\n return `${localizedPath}${parsedPath.search}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DA,MAAa,oBAIX,eACA,SAAwB,sBAAsB,eAC9C,UAA0B,CAAC,MACyB;CACpD,MAAM,EAAE,eAAe,MAAM,SAAS,SAAS,YAC7C,qBAAqB,OAAO;CAE9B,MAAM,oBAAoB,qBAAqB,eAAe,OAAO;CACrE,MAAM,eAAe,gBAAgB,SAAS,KAAK;CAInD,MAAM,aAAa,IAAI,IAAI,mBAAmB,cAAc;CAE5D,MAAM,qBAAqB,qBACzB,iBAAiB,WAAW,UAAU,QAAW,YAAY,GAC7D,QACA,YACF,CAAC,CAAC;CAEF,IACE,EACE,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B,gBAExC,SAAS,aAET,OAAO,GAAG,qBAAqB,WAAW,SAAS,WAAW;CAMhE,IACE,EACE,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B,oBAExC,SAAS,iBACT;EACA,MAAM,eAAe,IAAI,gBAAgB,WAAW,MAAM;EAE1D,aAAa,IAAI,UAAU,OAAO,SAAS,CAAC;EAE5C,MAAM,cAAc,aAAa,SAAS;EAE1C,OAAO,GAAG,qBAAqB,cAAc,IAAI,gBAAgB,KAAK,WAAW;CAInF;CAEA,MAAM,EAAE,WAAW,UAAU,QAAQ;EACnC;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,gBAAgB,IAAI,SAAS,qBAAqB,QAAQ,QAAQ,GAAG;CAEzE,IAAI,cAAc,SAAS,KAAK,cAAc,SAAS,GAAG,GACxD,gBAAgB,cAAc,MAAM,GAAG,EAAE;CAG3C,OAAO,GAAG,gBAAgB,WAAW,SAAS,WAAW;AAI3D"}
1
+ {"version":3,"file":"getLocalizedPath.mjs","names":[],"sources":["../../../src/localization/getLocalizedPath.ts"],"sourcesContent":["import { internationalization } from '@intlayer/config/built';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type {\n LocalesValues,\n LocalizedPathname,\n ResolvedDefaultLocale,\n} from '@intlayer/types/module_augmentation';\nimport { getCanonicalPath } from './getCanonicalPath';\nimport { getPathWithoutLocale } from './getPathWithoutLocale';\nimport {\n getPrefix,\n type RoutingOptions,\n resolveRoutingConfig,\n} from './getPrefix';\nimport { getRewriteRules } from './rewriteMatch';\nimport { resolveLocalizedPath } from './rewriteUtils';\n\n/**\n * Localizes an application path for a locale: resolves the `routing.rewrite`\n * rules, then applies the locale representation of the routing mode — a path\n * prefix, a `locale` search parameter, or nothing at all.\n *\n * Any query string and hash of the input are preserved.\n *\n * This is the relative half of {@link getLocalizedUrl}, which builds on it to\n * add an origin and cross-domain routing. For a relative input both return the\n * same value; this one never returns an absolute URL — the origin of an\n * absolute input is dropped and only its path is localized.\n *\n * Use `resolveLocalizedPath` instead to apply the rewrite rules alone, without\n * any locale representation.\n *\n * @example\n * ```ts\n * // routing: { mode: 'prefix-no-default', rewrite: { '/about': { fr: '/a-propos' } } }\n * getLocalizedPath('/about', 'fr'); // '/fr/a-propos'\n * getLocalizedPath('/about', 'en'); // '/about' (default locale, no prefix)\n * getLocalizedPath('/', 'fr'); // '/fr'\n * getLocalizedPath('/contact', 'fr'); // '/fr/contact' (no rewrite rule matches)\n * getLocalizedPath('https://intlayer.org/about', 'fr'); // '/fr/a-propos' (origin dropped)\n *\n * // routing: { domains: { zh: 'intlayer.cn' } } — zh is alone on that hostname\n * getLocalizedPath('/about', 'zh'); // '/about' (the domain identifies the locale)\n *\n * // Manual rules, bypassing the configuration\n * getLocalizedPath('/contact', 'fr', {\n * rewrite: { '/contact': { fr: '/contactez-nous' } },\n * });\n * // '/fr/contactez-nous'\n * ```\n *\n * @param canonicalPath - The internal application path (e.g. `/about`, `/product/123`).\n * An absolute URL is accepted; only its path, query and hash are kept.\n * @param locale - The target locale. Defaults to the configured default locale.\n * @param options - Routing overrides (`locales`, `defaultLocale`, `mode`, `rewrite`,\n * `domains`). Each one defaults to the project configuration. `domains` only\n * suppresses the prefix of a locale served from its own domain — the origin\n * itself is never emitted.\n * @returns The localized path for the target locale.\n */\nexport const getLocalizedPath = <\n const CanonicalPath extends string,\n const CurrentLocale extends LocalesValues = ResolvedDefaultLocale,\n>(\n canonicalPath: CanonicalPath,\n locale: CurrentLocale = internationalization?.defaultLocale as CurrentLocale,\n options: RoutingOptions = {}\n): LocalizedPathname<CanonicalPath, CurrentLocale> => {\n const { defaultLocale, mode, locales, rewrite, domains } =\n resolveRoutingConfig(options);\n\n const pathWithoutLocale = getPathWithoutLocale(canonicalPath, locales);\n const rewriteRules = getRewriteRules(rewrite, 'url');\n\n // Parsed against a dummy origin to split the path from its query and hash.\n // An absolute input parses on its own, and only its path is kept.\n const parsedPath = new URL(pathWithoutLocale, 'http://e.com');\n\n const translatedPathname = resolveLocalizedPath(\n getCanonicalPath(parsedPath.pathname, undefined, rewriteRules),\n locale as Locale,\n rewriteRules\n ).path;\n\n if (\n !(\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'no-prefix'\n ) &&\n mode === 'no-prefix'\n ) {\n return `${translatedPathname}${parsedPath.search}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n }\n\n if (\n !(\n process.env.INTLAYER_ROUTING_MODE &&\n process.env.INTLAYER_ROUTING_MODE !== 'search-params'\n ) &&\n mode === 'search-params'\n ) {\n const searchParams = new URLSearchParams(parsedPath.search);\n\n searchParams.set('locale', locale.toString());\n\n const queryParams = searchParams.toString();\n\n return `${translatedPathname}${queryParams ? `?${queryParams}` : ''}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n }\n\n const { prefix } = getPrefix(locale, {\n defaultLocale,\n mode,\n locales,\n domains,\n });\n\n let localizedPath = `/${prefix}${translatedPathname}`.replace(/\\/+/g, '/');\n\n if (localizedPath.length > 1 && localizedPath.endsWith('/')) {\n localizedPath = localizedPath.slice(0, -1);\n }\n\n return `${localizedPath}${parsedPath.search}${parsedPath.hash}` as LocalizedPathname<\n CanonicalPath,\n CurrentLocale\n >;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAa,oBAIX,eACA,SAAwB,sBAAsB,eAC9C,UAA0B,CAAC,MACyB;CACpD,MAAM,EAAE,eAAe,MAAM,SAAS,SAAS,YAC7C,qBAAqB,OAAO;CAE9B,MAAM,oBAAoB,qBAAqB,eAAe,OAAO;CACrE,MAAM,eAAe,gBAAgB,SAAS,KAAK;CAInD,MAAM,aAAa,IAAI,IAAI,mBAAmB,cAAc;CAE5D,MAAM,qBAAqB,qBACzB,iBAAiB,WAAW,UAAU,QAAW,YAAY,GAC7D,QACA,YACF,CAAC,CAAC;CAEF,IACE,EACE,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B,gBAExC,SAAS,aAET,OAAO,GAAG,qBAAqB,WAAW,SAAS,WAAW;CAMhE,IACE,EACE,QAAQ,IAAI,yBACZ,QAAQ,IAAI,0BAA0B,oBAExC,SAAS,iBACT;EACA,MAAM,eAAe,IAAI,gBAAgB,WAAW,MAAM;EAE1D,aAAa,IAAI,UAAU,OAAO,SAAS,CAAC;EAE5C,MAAM,cAAc,aAAa,SAAS;EAE1C,OAAO,GAAG,qBAAqB,cAAc,IAAI,gBAAgB,KAAK,WAAW;CAInF;CAEA,MAAM,EAAE,WAAW,UAAU,QAAQ;EACnC;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,gBAAgB,IAAI,SAAS,qBAAqB,QAAQ,QAAQ,GAAG;CAEzE,IAAI,cAAc,SAAS,KAAK,cAAc,SAAS,GAAG,GACxD,gBAAgB,cAAc,MAAM,GAAG,EAAE;CAG3C,OAAO,GAAG,gBAAgB,WAAW,SAAS,WAAW;AAI3D"}
@@ -1,8 +1,10 @@
1
1
  import { getPathWithoutLocale } from "./getPathWithoutLocale.mjs";
2
2
  import { comparePaths, normalizePath } from "./comparePaths.mjs";
3
3
  import { getDomainHostname, getDomainOrigin, getLocaleFromDomain, isLocaleExclusiveOnDomain } from "./domainUtils.mjs";
4
+ import { getRewriteRules } from "./rewriteMatch.mjs";
5
+ import { getCanonicalPath } from "./getCanonicalPath.mjs";
4
6
  import { getPrefix, isDeclaredLocale } from "./getPrefix.mjs";
5
- import { getCanonicalPath, getInternalPath, getRewritePath, getRewriteRules, resolveLocalizedPath } from "./rewriteUtils.mjs";
7
+ import { getInternalPath, getRewritePath, resolveLocalizedPath } from "./rewriteUtils.mjs";
6
8
  import { getLocalizedPath } from "./getLocalizedPath.mjs";
7
9
  import { getLocalizedUrl } from "./getLocalizedUrl.mjs";
8
10
  import { getMultilingualUrls } from "./getMultilingualUrls.mjs";
@@ -0,0 +1,49 @@
1
+ //#region src/localization/rewriteMatch.ts
2
+ /**
3
+ * Normalizes legacy Record format or extracts specialized rules from RewriteObject.
4
+ *
5
+ * Idempotent: already-normalized rules are handed back untouched, so a caller
6
+ * holding resolved rules can pass them on without re-normalizing.
7
+ */
8
+ const getRewriteRules = (rewrite, context = "url") => {
9
+ if (!rewrite || process.env.INTLAYER_ROUTING_REWRITE_RULES && process.env.INTLAYER_ROUTING_REWRITE_RULES === "false") return void 0;
10
+ if (Array.isArray(rewrite.rules)) return rewrite;
11
+ if ("url" in rewrite) return rewrite[context];
12
+ return { rules: Object.entries(rewrite).map(([canonical, localized]) => ({
13
+ canonical: canonical.startsWith("/") ? canonical.replace(/\[([^\]]+)\]/g, ":$1") : `/${canonical.replace(/\[([^\]]+)\]/g, ":$1")}`,
14
+ localized: Object.fromEntries(Object.entries(localized).map(([locale, pattern]) => {
15
+ return [locale, pattern?.startsWith("/") ? pattern.replace(/\[([^\]]+)\]/g, ":$1") : `/${(pattern || "").replace(/\[([^\]]+)\]/g, ":$1")}`];
16
+ }))
17
+ })) };
18
+ };
19
+ /**
20
+ * Converts normalized pattern to Regex.
21
+ * Internal syntax supports:
22
+ * - :param -> ([^/]+) (one segment)
23
+ * - :param* -> (.*) (zero or more segments)
24
+ * - :param+ -> (.+) (one or more segments)
25
+ * - :param? -> ([^/]*) (zero or one segment)
26
+ */
27
+ const patternToRegex = (pattern) => {
28
+ const regexString = pattern.replace(/\//g, "\\/").replace(/\\\/:(?:[^/\\*+?]+)\*/g, "(?:\\/(.*))?").replace(/\\\/:(?:[^/\\*+?]+)\?/g, "(?:\\/([^\\/]+))?").replace(/:([^/\\*+?]+)\*/g, "(.*)").replace(/:([^/\\*+?]+)\?/g, "([^\\/]*)").replace(/:([^/\\*+?]+)\+/g, "(.+)").replace(/:([^/\\*+?]+)/g, "([^\\/]+)");
29
+ return new RegExp(`^${regexString}$`);
30
+ };
31
+ /**
32
+ * Replaces route parameters in a path with provided values.
33
+ */
34
+ const fillPath = (pattern, params) => {
35
+ let index = 0;
36
+ return pattern.replace(/:([^/\\*+?]+)[*+?]?/g, () => params[index++] ?? "").replace(/\/+/g, "/").replace(/\/$/, "") || "/";
37
+ };
38
+ /**
39
+ * Extract values from a URL based on a pattern.
40
+ */
41
+ const extractParams = (url, pattern) => {
42
+ const regex = patternToRegex(pattern);
43
+ const match = url.match(regex);
44
+ return match ? match.slice(1) : null;
45
+ };
46
+
47
+ //#endregion
48
+ export { extractParams, fillPath, getRewriteRules };
49
+ //# sourceMappingURL=rewriteMatch.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewriteMatch.mjs","names":["legacyRules"],"sources":["../../../src/localization/rewriteMatch.ts"],"sourcesContent":["import type {\n RewriteObject,\n RewriteRules,\n RoutingConfig,\n} from '@intlayer/types/config';\n\n/**\n * Normalizes legacy Record format or extracts specialized rules from RewriteObject.\n *\n * Idempotent: already-normalized rules are handed back untouched, so a caller\n * holding resolved rules can pass them on without re-normalizing.\n */\nexport const getRewriteRules = <\n const Context extends keyof RewriteObject = 'url',\n>(\n rewrite: RoutingConfig['rewrite'] | RewriteRules,\n context: Context = 'url' as Context\n): RewriteRules | undefined => {\n if (\n !rewrite ||\n (process.env.INTLAYER_ROUTING_REWRITE_RULES &&\n process.env.INTLAYER_ROUTING_REWRITE_RULES === 'false')\n )\n return undefined;\n\n if (Array.isArray((rewrite as RewriteRules).rules)) {\n return rewrite as RewriteRules;\n }\n\n if ('url' in rewrite) {\n return (rewrite as RewriteObject)[context];\n }\n\n // Normalize legacy format\n const legacyRules = rewrite as Record<string, Record<string, string>>;\n\n return {\n rules: Object.entries(legacyRules).map(([canonical, localized]) => ({\n // Normalize canonical path\n canonical: canonical.startsWith('/')\n ? canonical.replace(/\\[([^\\]]+)\\]/g, ':$1')\n : `/${canonical.replace(/\\[([^\\]]+)\\]/g, ':$1')}`,\n\n // Normalize localized path\n localized: Object.fromEntries(\n Object.entries(localized).map(([locale, pattern]) => {\n const normalizedPattern = pattern?.startsWith('/')\n ? pattern.replace(/\\[([^\\]]+)\\]/g, ':$1')\n : `/${(pattern || '').replace(/\\[([^\\]]+)\\]/g, ':$1')}`;\n return [locale, normalizedPattern];\n })\n ),\n })),\n };\n};\n\n/**\n * Converts normalized pattern to Regex.\n * Internal syntax supports:\n * - :param -> ([^/]+) (one segment)\n * - :param* -> (.*) (zero or more segments)\n * - :param+ -> (.+) (one or more segments)\n * - :param? -> ([^/]*) (zero or one segment)\n */\nconst patternToRegex = (pattern: string) => {\n const regexString = pattern\n .replace(/\\//g, '\\\\/') // Escape slashes\n .replace(/\\\\\\/:(?:[^/\\\\*+?]+)\\*/g, '(?:\\\\/(.*))?') // /:param*\n .replace(/\\\\\\/:(?:[^/\\\\*+?]+)\\?/g, '(?:\\\\/([^\\\\/]+))?') // /:param?\n .replace(/:([^/\\\\*+?]+)\\*/g, '(.*)') // :param* (if no leading slash)\n .replace(/:([^/\\\\*+?]+)\\?/g, '([^\\\\/]*)') // :param? (if no leading slash)\n .replace(/:([^/\\\\*+?]+)\\+/g, '(.+)') // :param+\n .replace(/:([^/\\\\*+?]+)/g, '([^\\\\/]+)'); // :param\n\n return new RegExp(`^${regexString}$`);\n};\n\n/**\n * Replaces route parameters in a path with provided values.\n */\nexport const fillPath = (pattern: string, params: string[]) => {\n let index = 0;\n return (\n pattern\n .replace(/:([^/\\\\*+?]+)[*+?]?/g, () => params[index++] ?? '')\n .replace(/\\/+/g, '/')\n .replace(/\\/$/, '') || '/'\n );\n};\n\n/**\n * Extract values from a URL based on a pattern.\n */\nexport const extractParams = (\n url: string,\n pattern: string\n): string[] | null => {\n const regex = patternToRegex(pattern);\n const match = url.match(regex);\n return match ? match.slice(1) : null;\n};\n"],"mappings":";;;;;;;AAYA,MAAa,mBAGX,SACA,UAAmB,UACU;CAC7B,IACE,CAAC,WACA,QAAQ,IAAI,kCACX,QAAQ,IAAI,mCAAmC,SAEjD,OAAO;CAET,IAAI,MAAM,QAAS,QAAyB,KAAK,GAC/C,OAAO;CAGT,IAAI,SAAS,SACX,OAAQ,QAA0B;CAMpC,OAAO,EACL,OAAO,OAAO,QAAQA,OAAW,CAAC,CAAC,KAAK,CAAC,WAAW,gBAAgB;EAElE,WAAW,UAAU,WAAW,GAAG,IAC/B,UAAU,QAAQ,iBAAiB,KAAK,IACxC,IAAI,UAAU,QAAQ,iBAAiB,KAAK;EAGhD,WAAW,OAAO,YAChB,OAAO,QAAQ,SAAS,CAAC,CAAC,KAAK,CAAC,QAAQ,aAAa;GAInD,OAAO,CAAC,QAHkB,SAAS,WAAW,GAAG,IAC7C,QAAQ,QAAQ,iBAAiB,KAAK,IACtC,KAAK,WAAW,GAAE,CAAE,QAAQ,iBAAiB,KAAK,GACrB;EACnC,CAAC,CACH;CACF,EAAE,EACJ;AACF;;;;;;;;;AAUA,MAAM,kBAAkB,YAAoB;CAC1C,MAAM,cAAc,QACjB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,0BAA0B,cAAc,CAAC,CACjD,QAAQ,0BAA0B,mBAAmB,CAAC,CACtD,QAAQ,oBAAoB,MAAM,CAAC,CACnC,QAAQ,oBAAoB,WAAW,CAAC,CACxC,QAAQ,oBAAoB,MAAM,CAAC,CACnC,QAAQ,kBAAkB,WAAW;CAExC,OAAO,IAAI,OAAO,IAAI,YAAY,EAAE;AACtC;;;;AAKA,MAAa,YAAY,SAAiB,WAAqB;CAC7D,IAAI,QAAQ;CACZ,OACE,QACG,QAAQ,8BAA8B,OAAO,YAAY,EAAE,CAAC,CAC5D,QAAQ,QAAQ,GAAG,CAAC,CACpB,QAAQ,OAAO,EAAE,KAAK;AAE7B;;;;AAKA,MAAa,iBACX,KACA,YACoB;CACpB,MAAM,QAAQ,eAAe,OAAO;CACpC,MAAM,QAAQ,IAAI,MAAM,KAAK;CAC7B,OAAO,QAAQ,MAAM,MAAM,CAAC,IAAI;AAClC"}