@itwin/core-backend 5.2.0-dev.7 → 5.2.0

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 (506) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/lib/cjs/BackendHubAccess.d.ts +2 -0
  3. package/lib/cjs/BackendHubAccess.d.ts.map +1 -1
  4. package/lib/cjs/BackendHubAccess.js.map +1 -1
  5. package/lib/cjs/BackendLoggerCategory.d.ts +6 -0
  6. package/lib/cjs/BackendLoggerCategory.d.ts.map +1 -1
  7. package/lib/cjs/BackendLoggerCategory.js +6 -0
  8. package/lib/cjs/BackendLoggerCategory.js.map +1 -1
  9. package/lib/cjs/BisCoreSchema.js.map +1 -1
  10. package/lib/cjs/BlobContainerService.js.map +1 -1
  11. package/lib/cjs/BriefcaseManager.d.ts +57 -3
  12. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  13. package/lib/cjs/BriefcaseManager.js +151 -42
  14. package/lib/cjs/BriefcaseManager.js.map +1 -1
  15. package/lib/cjs/CatalogDb.js.map +1 -1
  16. package/lib/cjs/Category.js.map +1 -1
  17. package/lib/cjs/ChangeSummaryManager.js +2 -2
  18. package/lib/cjs/ChangeSummaryManager.js.map +1 -1
  19. package/lib/cjs/ChangedElementsDb.js.map +1 -1
  20. package/lib/cjs/ChangesetECAdaptor.js +248 -248
  21. package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
  22. package/lib/cjs/ChannelControl.js.map +1 -1
  23. package/lib/cjs/CheckpointManager.js.map +1 -1
  24. package/lib/cjs/ClassRegistry.js +5 -5
  25. package/lib/cjs/ClassRegistry.js.map +1 -1
  26. package/lib/cjs/CloudSqlite.d.ts +4 -0
  27. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  28. package/lib/cjs/CloudSqlite.js.map +1 -1
  29. package/lib/cjs/CodeService.js.map +1 -1
  30. package/lib/cjs/CodeSpecs.js.map +1 -1
  31. package/lib/cjs/ConcurrentQuery.js.map +1 -1
  32. package/lib/cjs/CustomViewState3dCreator.js.map +1 -1
  33. package/lib/cjs/DevTools.js.map +1 -1
  34. package/lib/cjs/DisplayStyle.js.map +1 -1
  35. package/lib/cjs/ECDb.d.ts +8 -0
  36. package/lib/cjs/ECDb.d.ts.map +1 -1
  37. package/lib/cjs/ECDb.js +22 -0
  38. package/lib/cjs/ECDb.js.map +1 -1
  39. package/lib/cjs/ECSchemaXmlContext.js.map +1 -1
  40. package/lib/cjs/ECSqlStatement.js.map +1 -1
  41. package/lib/cjs/Element.js.map +1 -1
  42. package/lib/cjs/ElementAspect.js.map +1 -1
  43. package/lib/cjs/ElementGraphics.js.map +1 -1
  44. package/lib/cjs/ElementTreeWalker.js.map +1 -1
  45. package/lib/cjs/Entity.js.map +1 -1
  46. package/lib/cjs/EntityReferences.js.map +1 -1
  47. package/lib/cjs/ExportGraphics.js.map +1 -1
  48. package/lib/cjs/ExternalSource.js.map +1 -1
  49. package/lib/cjs/FontFile.js.map +1 -1
  50. package/lib/cjs/GeoCoordConfig.js.map +1 -1
  51. package/lib/cjs/GeographicCRSServices.js.map +1 -1
  52. package/lib/cjs/GeometrySummary.js +47 -47
  53. package/lib/cjs/GeometrySummary.js.map +1 -1
  54. package/lib/cjs/IModelDb.d.ts +54 -3
  55. package/lib/cjs/IModelDb.d.ts.map +1 -1
  56. package/lib/cjs/IModelDb.js +96 -18
  57. package/lib/cjs/IModelDb.js.map +1 -1
  58. package/lib/cjs/IModelDbFonts.js.map +1 -1
  59. package/lib/cjs/IModelElementCloneContext.js.map +1 -1
  60. package/lib/cjs/IModelHost.d.ts +11 -1
  61. package/lib/cjs/IModelHost.d.ts.map +1 -1
  62. package/lib/cjs/IModelHost.js +5 -0
  63. package/lib/cjs/IModelHost.js.map +1 -1
  64. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts +1 -5
  65. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts.map +1 -1
  66. package/lib/cjs/IModelIncrementalSchemaLocater.js +0 -6
  67. package/lib/cjs/IModelIncrementalSchemaLocater.js.map +1 -1
  68. package/lib/cjs/IModelJsFs.js.map +1 -1
  69. package/lib/cjs/ImageSourceConversion.js.map +1 -1
  70. package/lib/cjs/IpcHost.js.map +1 -1
  71. package/lib/cjs/LineStyle.js.map +1 -1
  72. package/lib/cjs/LocalHub.js +1 -1
  73. package/lib/cjs/LocalHub.js.map +1 -1
  74. package/lib/cjs/LocalhostIpcHost.js.map +1 -1
  75. package/lib/cjs/LockControl.js.map +1 -1
  76. package/lib/cjs/Material.js.map +1 -1
  77. package/lib/cjs/Model.js.map +1 -1
  78. package/lib/cjs/NativeAppStorage.js.map +1 -1
  79. package/lib/cjs/NativeHost.js.map +1 -1
  80. package/lib/cjs/NavigationRelationship.js.map +1 -1
  81. package/lib/cjs/PromiseMemoizer.js.map +1 -1
  82. package/lib/cjs/PropertyStore.js.map +1 -1
  83. package/lib/cjs/Relationship.js.map +1 -1
  84. package/lib/cjs/RpcBackend.js.map +1 -1
  85. package/lib/cjs/SQLiteDb.js.map +1 -1
  86. package/lib/cjs/Schema.js.map +1 -1
  87. package/lib/cjs/SchemaSync.js.map +1 -1
  88. package/lib/cjs/SchemaUtils.js.map +1 -1
  89. package/lib/cjs/SheetIndex.js.map +1 -1
  90. package/lib/cjs/SqliteChangesetReader.d.ts +8 -0
  91. package/lib/cjs/SqliteChangesetReader.d.ts.map +1 -1
  92. package/lib/cjs/SqliteChangesetReader.js +11 -0
  93. package/lib/cjs/SqliteChangesetReader.js.map +1 -1
  94. package/lib/cjs/SqliteStatement.js.map +1 -1
  95. package/lib/cjs/StashManager.d.ts +175 -0
  96. package/lib/cjs/StashManager.d.ts.map +1 -0
  97. package/lib/cjs/StashManager.js +306 -0
  98. package/lib/cjs/StashManager.js.map +1 -0
  99. package/lib/cjs/Texture.js.map +1 -1
  100. package/lib/cjs/TileStorage.js.map +1 -1
  101. package/lib/cjs/TxnManager.d.ts +226 -15
  102. package/lib/cjs/TxnManager.d.ts.map +1 -1
  103. package/lib/cjs/TxnManager.js +249 -23
  104. package/lib/cjs/TxnManager.js.map +1 -1
  105. package/lib/cjs/ViewDefinition.js.map +1 -1
  106. package/lib/cjs/ViewStateHydrator.js.map +1 -1
  107. package/lib/cjs/ViewStore.js.map +1 -1
  108. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +10 -1
  109. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  110. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js +15 -6
  111. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  112. package/lib/cjs/annotations/FrameGeometry.js +6 -6
  113. package/lib/cjs/annotations/FrameGeometry.js.map +1 -1
  114. package/lib/cjs/annotations/LeaderGeometry.d.ts +3 -2
  115. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  116. package/lib/cjs/annotations/LeaderGeometry.js +8 -7
  117. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  118. package/lib/cjs/annotations/TextAnnotationElement.d.ts +145 -36
  119. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
  120. package/lib/cjs/annotations/TextAnnotationElement.js +234 -106
  121. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
  122. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts +2 -0
  123. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  124. package/lib/cjs/annotations/TextAnnotationGeometry.js +26 -19
  125. package/lib/cjs/annotations/TextAnnotationGeometry.js.map +1 -1
  126. package/lib/cjs/annotations/TextBlockGeometry.d.ts.map +1 -1
  127. package/lib/cjs/annotations/TextBlockGeometry.js +11 -3
  128. package/lib/cjs/annotations/TextBlockGeometry.js.map +1 -1
  129. package/lib/cjs/annotations/TextBlockLayout.d.ts +51 -38
  130. package/lib/cjs/annotations/TextBlockLayout.d.ts.map +1 -1
  131. package/lib/cjs/annotations/TextBlockLayout.js +252 -156
  132. package/lib/cjs/annotations/TextBlockLayout.js.map +1 -1
  133. package/lib/cjs/assets/IModelChange.02.00.00.ecschema.xml +90 -90
  134. package/lib/cjs/assets/Settings/Schemas/Base.Schema.json +32 -32
  135. package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +27 -27
  136. package/lib/cjs/assets/Settings/Schemas/Workspace.Schema.json +94 -94
  137. package/lib/cjs/assets/Settings/backend.setting.json5 +21 -21
  138. package/lib/cjs/core-backend.js.map +1 -1
  139. package/lib/cjs/domains/FunctionalElements.js.map +1 -1
  140. package/lib/cjs/domains/FunctionalSchema.js.map +1 -1
  141. package/lib/cjs/domains/GenericElements.js.map +1 -1
  142. package/lib/cjs/domains/GenericSchema.js.map +1 -1
  143. package/lib/cjs/internal/ChangesetConflictArgs.js.map +1 -1
  144. package/lib/cjs/internal/ChannelAdmin.js +1 -1
  145. package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
  146. package/lib/cjs/internal/ElementLRUCache.js.map +1 -1
  147. package/lib/cjs/internal/FontFileImpl.js.map +1 -1
  148. package/lib/cjs/internal/HubMock.js.map +1 -1
  149. package/lib/cjs/internal/IModelDbFontsImpl.js.map +1 -1
  150. package/lib/cjs/internal/NativePlatform.js.map +1 -1
  151. package/lib/cjs/internal/NoLocks.js.map +1 -1
  152. package/lib/cjs/internal/ServerBasedLocks.js.map +1 -1
  153. package/lib/cjs/internal/Symbols.d.ts +1 -0
  154. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  155. package/lib/cjs/internal/Symbols.js +2 -1
  156. package/lib/cjs/internal/Symbols.js.map +1 -1
  157. package/lib/cjs/internal/annotations/fields.d.ts +2 -12
  158. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
  159. package/lib/cjs/internal/annotations/fields.js +49 -45
  160. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  161. package/lib/cjs/internal/cross-package.js.map +1 -1
  162. package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
  163. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  164. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  165. package/lib/cjs/internal/workspace/WorkspaceSqliteDb.js.map +1 -1
  166. package/lib/cjs/rpc/multipart.js.map +1 -1
  167. package/lib/cjs/rpc/tracing.js.map +1 -1
  168. package/lib/cjs/rpc/web/logging.js.map +1 -1
  169. package/lib/cjs/rpc/web/request.js.map +1 -1
  170. package/lib/cjs/rpc/web/response.js.map +1 -1
  171. package/lib/cjs/rpc-impl/DevToolsRpcImpl.js.map +1 -1
  172. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  173. package/lib/cjs/rpc-impl/IModelTileRpcImpl.js.map +1 -1
  174. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  175. package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
  176. package/lib/cjs/workspace/Settings.js.map +1 -1
  177. package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
  178. package/lib/cjs/workspace/Workspace.d.ts +1 -1
  179. package/lib/cjs/workspace/Workspace.js.map +1 -1
  180. package/lib/cjs/workspace/WorkspaceEditor.js.map +1 -1
  181. package/lib/esm/BackendHubAccess.d.ts +2 -0
  182. package/lib/esm/BackendHubAccess.d.ts.map +1 -1
  183. package/lib/esm/BackendHubAccess.js.map +1 -1
  184. package/lib/esm/BackendLoggerCategory.d.ts +6 -0
  185. package/lib/esm/BackendLoggerCategory.d.ts.map +1 -1
  186. package/lib/esm/BackendLoggerCategory.js +6 -0
  187. package/lib/esm/BackendLoggerCategory.js.map +1 -1
  188. package/lib/esm/BisCoreSchema.js.map +1 -1
  189. package/lib/esm/BlobContainerService.js.map +1 -1
  190. package/lib/esm/BriefcaseManager.d.ts +57 -3
  191. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  192. package/lib/esm/BriefcaseManager.js +152 -43
  193. package/lib/esm/BriefcaseManager.js.map +1 -1
  194. package/lib/esm/CatalogDb.js.map +1 -1
  195. package/lib/esm/Category.js.map +1 -1
  196. package/lib/esm/ChangeSummaryManager.js +2 -2
  197. package/lib/esm/ChangeSummaryManager.js.map +1 -1
  198. package/lib/esm/ChangedElementsDb.js.map +1 -1
  199. package/lib/esm/ChangesetECAdaptor.js +248 -248
  200. package/lib/esm/ChangesetECAdaptor.js.map +1 -1
  201. package/lib/esm/ChannelControl.js.map +1 -1
  202. package/lib/esm/CheckpointManager.js.map +1 -1
  203. package/lib/esm/ClassRegistry.js +5 -5
  204. package/lib/esm/ClassRegistry.js.map +1 -1
  205. package/lib/esm/CloudSqlite.d.ts +4 -0
  206. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  207. package/lib/esm/CloudSqlite.js.map +1 -1
  208. package/lib/esm/CodeService.js.map +1 -1
  209. package/lib/esm/CodeSpecs.js.map +1 -1
  210. package/lib/esm/ConcurrentQuery.js.map +1 -1
  211. package/lib/esm/CustomViewState3dCreator.js.map +1 -1
  212. package/lib/esm/DevTools.js.map +1 -1
  213. package/lib/esm/DisplayStyle.js.map +1 -1
  214. package/lib/esm/ECDb.d.ts +8 -0
  215. package/lib/esm/ECDb.d.ts.map +1 -1
  216. package/lib/esm/ECDb.js +22 -0
  217. package/lib/esm/ECDb.js.map +1 -1
  218. package/lib/esm/ECSchemaXmlContext.js.map +1 -1
  219. package/lib/esm/ECSqlStatement.js.map +1 -1
  220. package/lib/esm/Element.js.map +1 -1
  221. package/lib/esm/ElementAspect.js.map +1 -1
  222. package/lib/esm/ElementGraphics.js.map +1 -1
  223. package/lib/esm/ElementTreeWalker.js.map +1 -1
  224. package/lib/esm/Entity.js.map +1 -1
  225. package/lib/esm/EntityReferences.js.map +1 -1
  226. package/lib/esm/ExportGraphics.js.map +1 -1
  227. package/lib/esm/ExternalSource.js.map +1 -1
  228. package/lib/esm/FontFile.js.map +1 -1
  229. package/lib/esm/GeoCoordConfig.js.map +1 -1
  230. package/lib/esm/GeographicCRSServices.js.map +1 -1
  231. package/lib/esm/GeometrySummary.js +47 -47
  232. package/lib/esm/GeometrySummary.js.map +1 -1
  233. package/lib/esm/IModelDb.d.ts +54 -3
  234. package/lib/esm/IModelDb.d.ts.map +1 -1
  235. package/lib/esm/IModelDb.js +97 -19
  236. package/lib/esm/IModelDb.js.map +1 -1
  237. package/lib/esm/IModelDbFonts.js.map +1 -1
  238. package/lib/esm/IModelElementCloneContext.js.map +1 -1
  239. package/lib/esm/IModelHost.d.ts +11 -1
  240. package/lib/esm/IModelHost.d.ts.map +1 -1
  241. package/lib/esm/IModelHost.js +5 -0
  242. package/lib/esm/IModelHost.js.map +1 -1
  243. package/lib/esm/IModelIncrementalSchemaLocater.d.ts +1 -5
  244. package/lib/esm/IModelIncrementalSchemaLocater.d.ts.map +1 -1
  245. package/lib/esm/IModelIncrementalSchemaLocater.js +0 -6
  246. package/lib/esm/IModelIncrementalSchemaLocater.js.map +1 -1
  247. package/lib/esm/IModelJsFs.js.map +1 -1
  248. package/lib/esm/ImageSourceConversion.js.map +1 -1
  249. package/lib/esm/IpcHost.js.map +1 -1
  250. package/lib/esm/LineStyle.js.map +1 -1
  251. package/lib/esm/LocalHub.js +1 -1
  252. package/lib/esm/LocalHub.js.map +1 -1
  253. package/lib/esm/LocalhostIpcHost.js.map +1 -1
  254. package/lib/esm/LockControl.js.map +1 -1
  255. package/lib/esm/Material.js.map +1 -1
  256. package/lib/esm/Model.js.map +1 -1
  257. package/lib/esm/NativeAppStorage.js.map +1 -1
  258. package/lib/esm/NativeHost.js.map +1 -1
  259. package/lib/esm/NavigationRelationship.js.map +1 -1
  260. package/lib/esm/PromiseMemoizer.js.map +1 -1
  261. package/lib/esm/PropertyStore.js.map +1 -1
  262. package/lib/esm/Relationship.js.map +1 -1
  263. package/lib/esm/RpcBackend.js.map +1 -1
  264. package/lib/esm/SQLiteDb.js.map +1 -1
  265. package/lib/esm/Schema.js.map +1 -1
  266. package/lib/esm/SchemaSync.js.map +1 -1
  267. package/lib/esm/SchemaUtils.js.map +1 -1
  268. package/lib/esm/SheetIndex.js.map +1 -1
  269. package/lib/esm/SqliteChangesetReader.d.ts +8 -0
  270. package/lib/esm/SqliteChangesetReader.d.ts.map +1 -1
  271. package/lib/esm/SqliteChangesetReader.js +11 -0
  272. package/lib/esm/SqliteChangesetReader.js.map +1 -1
  273. package/lib/esm/SqliteStatement.js.map +1 -1
  274. package/lib/esm/StashManager.d.ts +175 -0
  275. package/lib/esm/StashManager.d.ts.map +1 -0
  276. package/lib/esm/StashManager.js +301 -0
  277. package/lib/esm/StashManager.js.map +1 -0
  278. package/lib/esm/Texture.js.map +1 -1
  279. package/lib/esm/TileStorage.js.map +1 -1
  280. package/lib/esm/TxnManager.d.ts +226 -15
  281. package/lib/esm/TxnManager.d.ts.map +1 -1
  282. package/lib/esm/TxnManager.js +247 -21
  283. package/lib/esm/TxnManager.js.map +1 -1
  284. package/lib/esm/ViewDefinition.js.map +1 -1
  285. package/lib/esm/ViewStateHydrator.js.map +1 -1
  286. package/lib/esm/ViewStore.js.map +1 -1
  287. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +10 -1
  288. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  289. package/lib/esm/annotations/ElementDrivesTextAnnotation.js +13 -5
  290. package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  291. package/lib/esm/annotations/FrameGeometry.js +6 -6
  292. package/lib/esm/annotations/FrameGeometry.js.map +1 -1
  293. package/lib/esm/annotations/LeaderGeometry.d.ts +3 -2
  294. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  295. package/lib/esm/annotations/LeaderGeometry.js +8 -7
  296. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  297. package/lib/esm/annotations/TextAnnotationElement.d.ts +145 -36
  298. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
  299. package/lib/esm/annotations/TextAnnotationElement.js +235 -107
  300. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
  301. package/lib/esm/annotations/TextAnnotationGeometry.d.ts +2 -0
  302. package/lib/esm/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  303. package/lib/esm/annotations/TextAnnotationGeometry.js +26 -19
  304. package/lib/esm/annotations/TextAnnotationGeometry.js.map +1 -1
  305. package/lib/esm/annotations/TextBlockGeometry.d.ts.map +1 -1
  306. package/lib/esm/annotations/TextBlockGeometry.js +11 -3
  307. package/lib/esm/annotations/TextBlockGeometry.js.map +1 -1
  308. package/lib/esm/annotations/TextBlockLayout.d.ts +51 -38
  309. package/lib/esm/annotations/TextBlockLayout.d.ts.map +1 -1
  310. package/lib/esm/annotations/TextBlockLayout.js +253 -157
  311. package/lib/esm/annotations/TextBlockLayout.js.map +1 -1
  312. package/lib/esm/core-backend.js.map +1 -1
  313. package/lib/esm/domains/FunctionalElements.js.map +1 -1
  314. package/lib/esm/domains/FunctionalSchema.js.map +1 -1
  315. package/lib/esm/domains/GenericElements.js.map +1 -1
  316. package/lib/esm/domains/GenericSchema.js.map +1 -1
  317. package/lib/esm/internal/ChangesetConflictArgs.js.map +1 -1
  318. package/lib/esm/internal/ChannelAdmin.js +1 -1
  319. package/lib/esm/internal/ChannelAdmin.js.map +1 -1
  320. package/lib/esm/internal/ElementLRUCache.js.map +1 -1
  321. package/lib/esm/internal/FontFileImpl.js.map +1 -1
  322. package/lib/esm/internal/HubMock.js.map +1 -1
  323. package/lib/esm/internal/IModelDbFontsImpl.js.map +1 -1
  324. package/lib/esm/internal/NativePlatform.js.map +1 -1
  325. package/lib/esm/internal/NoLocks.js.map +1 -1
  326. package/lib/esm/internal/ServerBasedLocks.js.map +1 -1
  327. package/lib/esm/internal/Symbols.d.ts +1 -0
  328. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  329. package/lib/esm/internal/Symbols.js +1 -0
  330. package/lib/esm/internal/Symbols.js.map +1 -1
  331. package/lib/esm/internal/annotations/fields.d.ts +2 -12
  332. package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
  333. package/lib/esm/internal/annotations/fields.js +51 -47
  334. package/lib/esm/internal/annotations/fields.js.map +1 -1
  335. package/lib/esm/internal/cross-package.js.map +1 -1
  336. package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
  337. package/lib/esm/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  338. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  339. package/lib/esm/internal/workspace/WorkspaceSqliteDb.js.map +1 -1
  340. package/lib/esm/rpc/multipart.js.map +1 -1
  341. package/lib/esm/rpc/tracing.js.map +1 -1
  342. package/lib/esm/rpc/web/logging.js.map +1 -1
  343. package/lib/esm/rpc/web/request.js.map +1 -1
  344. package/lib/esm/rpc/web/response.js.map +1 -1
  345. package/lib/esm/rpc-impl/DevToolsRpcImpl.js.map +1 -1
  346. package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  347. package/lib/esm/rpc-impl/IModelTileRpcImpl.js.map +1 -1
  348. package/lib/esm/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  349. package/lib/esm/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
  350. package/lib/esm/test/AdvancedEqual.js.map +1 -1
  351. package/lib/esm/test/AnnotationTestUtils.d.ts +5 -1
  352. package/lib/esm/test/AnnotationTestUtils.d.ts.map +1 -1
  353. package/lib/esm/test/AnnotationTestUtils.js +7 -2
  354. package/lib/esm/test/AnnotationTestUtils.js.map +1 -1
  355. package/lib/esm/test/AttachDb.test.js +11 -11
  356. package/lib/esm/test/AttachDb.test.js.map +1 -1
  357. package/lib/esm/test/ElementLRUCache.test.js.map +1 -1
  358. package/lib/esm/test/GeometryTestUtil.js.map +1 -1
  359. package/lib/esm/test/IModelHost.test.js.map +1 -1
  360. package/lib/esm/test/IModelTestUtils.js.map +1 -1
  361. package/lib/esm/test/ImageSourceConversion.test.js.map +1 -1
  362. package/lib/esm/test/IpcHost.test.js.map +1 -1
  363. package/lib/esm/test/KnownTestLocations.js.map +1 -1
  364. package/lib/esm/test/PrintElementTree.js.map +1 -1
  365. package/lib/esm/test/PropertyDb.test.js.map +1 -1
  366. package/lib/esm/test/RevisionUtility.js.map +1 -1
  367. package/lib/esm/test/SchemaUtils.test.js +25 -25
  368. package/lib/esm/test/SchemaUtils.test.js.map +1 -1
  369. package/lib/esm/test/SequentialLogMatcher.js.map +1 -1
  370. package/lib/esm/test/TestChangeSetUtility.js.map +1 -1
  371. package/lib/esm/test/TestUtils.js.map +1 -1
  372. package/lib/esm/test/annotations/Fields.test.js +195 -78
  373. package/lib/esm/test/annotations/Fields.test.js.map +1 -1
  374. package/lib/esm/test/annotations/FrameGeometry.test.js +4 -4
  375. package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
  376. package/lib/esm/test/annotations/LeaderGeometry.test.js +19 -17
  377. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  378. package/lib/esm/test/annotations/TextAnnotation.test.js +410 -59
  379. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  380. package/lib/esm/test/annotations/TextBlock.test.js +627 -193
  381. package/lib/esm/test/annotations/TextBlock.test.js.map +1 -1
  382. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.js.map +1 -1
  383. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts +46 -0
  384. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts.map +1 -1
  385. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js +20 -2
  386. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js.map +1 -1
  387. package/lib/esm/test/categories/Category.test.js.map +1 -1
  388. package/lib/esm/test/codespec/CodeSpec.test.js.map +1 -1
  389. package/lib/esm/test/ecdb/CTE.test.js +88 -88
  390. package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
  391. package/lib/esm/test/ecdb/ConcurrentQuery.test.js +15 -15
  392. package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -1
  393. package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js +15 -15
  394. package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js.map +1 -1
  395. package/lib/esm/test/ecdb/ECDb.test.js +128 -58
  396. package/lib/esm/test/ecdb/ECDb.test.js.map +1 -1
  397. package/lib/esm/test/ecdb/ECDbTestHelper.js.map +1 -1
  398. package/lib/esm/test/ecdb/ECSchemaXmlContext.test.js.map +1 -1
  399. package/lib/esm/test/ecdb/ECSqlAst.test.js +65 -65
  400. package/lib/esm/test/ecdb/ECSqlAst.test.js.map +1 -1
  401. package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
  402. package/lib/esm/test/ecdb/ECSqlReader.test.js +16 -16
  403. package/lib/esm/test/ecdb/ECSqlReader.test.js.map +1 -1
  404. package/lib/esm/test/ecdb/ECSqlStatement.test.js +326 -326
  405. package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
  406. package/lib/esm/test/ecdb/SqliteStatement.test.js.map +1 -1
  407. package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js.map +1 -1
  408. package/lib/esm/test/ecsql/src/ECSqlTestGenerator.js +21 -21
  409. package/lib/esm/test/ecsql/src/ECSqlTestGenerator.js.map +1 -1
  410. package/lib/esm/test/ecsql/src/ECSqlTestParser.js.map +1 -1
  411. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
  412. package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
  413. package/lib/esm/test/element/ElementAspect.test.js +22 -22
  414. package/lib/esm/test/element/ElementAspect.test.js.map +1 -1
  415. package/lib/esm/test/element/ElementDependencyGraph.test.js.map +1 -1
  416. package/lib/esm/test/element/ElementRoundTrip.test.js +139 -139
  417. package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
  418. package/lib/esm/test/element/ExcludedElements.test.js.map +1 -1
  419. package/lib/esm/test/element/ExternalSource.test.js.map +1 -1
  420. package/lib/esm/test/element/NullStructArray.test.js +13 -13
  421. package/lib/esm/test/element/NullStructArray.test.js.map +1 -1
  422. package/lib/esm/test/element/UrlLink.test.js.map +1 -1
  423. package/lib/esm/test/font/FontFile.test.js.map +1 -1
  424. package/lib/esm/test/font/IModelDbFonts.test.js.map +1 -1
  425. package/lib/esm/test/hubaccess/ApplyChangeset.test.js +32 -32
  426. package/lib/esm/test/hubaccess/ApplyChangeset.test.js.map +1 -1
  427. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  428. package/lib/esm/test/hubaccess/CheckpointManager.test.js.map +1 -1
  429. package/lib/esm/test/hubaccess/Rebase.test.d.ts +2 -0
  430. package/lib/esm/test/hubaccess/Rebase.test.d.ts.map +1 -0
  431. package/lib/esm/test/hubaccess/Rebase.test.js +640 -0
  432. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -0
  433. package/lib/esm/test/imageData.js.map +1 -1
  434. package/lib/esm/test/imodel/ElementTreeWalker.test.js.map +1 -1
  435. package/lib/esm/test/imodel/GetTextureImage.test.js.map +1 -1
  436. package/lib/esm/test/imodel/IModel.test.js +44 -44
  437. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  438. package/lib/esm/test/imodel/ProjectExtents.test.js.map +1 -1
  439. package/lib/esm/test/imodel/SchemaXmlImport.test.js.map +1 -1
  440. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js +20 -20
  441. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js.map +1 -1
  442. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js +3 -3
  443. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js.map +1 -1
  444. package/lib/esm/test/incrementalSchemaLocater/utils/IModelSchemaLocater.js.map +1 -1
  445. package/lib/esm/test/incrementalSchemaLocater/utils/IncrementalTestHelper.js.map +1 -1
  446. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts +16 -1
  447. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts.map +1 -1
  448. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js +47 -0
  449. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js.map +1 -1
  450. package/lib/esm/test/index.js.map +1 -1
  451. package/lib/esm/test/misc/DevTools.test.js.map +1 -1
  452. package/lib/esm/test/misc/EntitySubClasses.test.js.map +1 -1
  453. package/lib/esm/test/misc/GeoServices.test.js.map +1 -1
  454. package/lib/esm/test/misc/PromiseMemoizer.test.js.map +1 -1
  455. package/lib/esm/test/native/DgnDbWorker.test.js.map +1 -1
  456. package/lib/esm/test/rpc/response.test.js.map +1 -1
  457. package/lib/esm/test/schema/ClassRegistry.test.js +99 -99
  458. package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
  459. package/lib/esm/test/schema/FunctionalDomain.test.js.map +1 -1
  460. package/lib/esm/test/schema/GenericDomain.test.js.map +1 -1
  461. package/lib/esm/test/schema/IModelSchemaContext.test.js.map +1 -1
  462. package/lib/esm/test/sheetindex/SheetIndex.test.js.map +1 -1
  463. package/lib/esm/test/standalone/ChangeMerge.test.js +15 -19
  464. package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
  465. package/lib/esm/test/standalone/ChangesetReader.test.js +248 -118
  466. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  467. package/lib/esm/test/standalone/CustomViewState3dCreator.test.js.map +1 -1
  468. package/lib/esm/test/standalone/DisplayStyle.test.js.map +1 -1
  469. package/lib/esm/test/standalone/Drawing.test.js.map +1 -1
  470. package/lib/esm/test/standalone/ElementGraphics.test.js.map +1 -1
  471. package/lib/esm/test/standalone/ElementMesh.test.js.map +1 -1
  472. package/lib/esm/test/standalone/ExportGraphics.test.js +14 -14
  473. package/lib/esm/test/standalone/ExportGraphics.test.js.map +1 -1
  474. package/lib/esm/test/standalone/GeometryChangeEvents.test.js.map +1 -1
  475. package/lib/esm/test/standalone/GeometryStream.test.js.map +1 -1
  476. package/lib/esm/test/standalone/HubMock.test.js.map +1 -1
  477. package/lib/esm/test/standalone/IModelLimits.test.js.map +1 -1
  478. package/lib/esm/test/standalone/IModelWrite.test.js +27 -27
  479. package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
  480. package/lib/esm/test/standalone/InlineGeometryPartReferences.test.js.map +1 -1
  481. package/lib/esm/test/standalone/MergeConflict.test.js +3 -3
  482. package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
  483. package/lib/esm/test/standalone/NativeAppStorage.test.js.map +1 -1
  484. package/lib/esm/test/standalone/RenderMaterialElement.test.js.map +1 -1
  485. package/lib/esm/test/standalone/RenderTimeline.test.js.map +1 -1
  486. package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
  487. package/lib/esm/test/standalone/SchemaUtils.test.js.map +1 -1
  488. package/lib/esm/test/standalone/SectionDrawing.test.js.map +1 -1
  489. package/lib/esm/test/standalone/ServerBasedLocks.test.js.map +1 -1
  490. package/lib/esm/test/standalone/Setting.test.js.map +1 -1
  491. package/lib/esm/test/standalone/Settings.test.js.map +1 -1
  492. package/lib/esm/test/standalone/SettingsSchemas.test.js.map +1 -1
  493. package/lib/esm/test/standalone/SnapshotDb.test.js.map +1 -1
  494. package/lib/esm/test/standalone/Texture.test.js.map +1 -1
  495. package/lib/esm/test/standalone/TileCache.test.js.map +1 -1
  496. package/lib/esm/test/standalone/TileTree.test.js.map +1 -1
  497. package/lib/esm/test/standalone/TxnManager.test.js.map +1 -1
  498. package/lib/esm/test/standalone/ViewDefinition.test.js.map +1 -1
  499. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  500. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  501. package/lib/esm/workspace/Settings.js.map +1 -1
  502. package/lib/esm/workspace/SettingsSchemas.js.map +1 -1
  503. package/lib/esm/workspace/Workspace.d.ts +1 -1
  504. package/lib/esm/workspace/Workspace.js.map +1 -1
  505. package/lib/esm/workspace/WorkspaceEditor.js.map +1 -1
  506. package/package.json +13 -13
@@ -5,7 +5,7 @@
5
5
  import { expect } from "chai";
6
6
  import { computeGraphemeOffsets, layoutTextBlock, TextStyleResolver } from "../../annotations/TextBlockLayout";
7
7
  import { Geometry } from "@itwin/core-geometry";
8
- import { ColorDef, FontType, FractionRun, LineBreakRun, Paragraph, TabRun, TextAnnotation, TextBlock, TextRun, TextStyleSettings } from "@itwin/core-common";
8
+ import { ColorDef, FontType, FractionRun, LineBreakRun, List, ListMarkerEnumerator, Paragraph, TabRun, TextAnnotation, TextBlock, TextRun, TextStyleSettings } from "@itwin/core-common";
9
9
  import { IModelTestUtils } from "../IModelTestUtils";
10
10
  import { ProcessDetector } from "@itwin/core-bentley";
11
11
  import { produceTextBlockGeometry } from "../../core-backend";
@@ -21,64 +21,64 @@ function isIntlSupported() {
21
21
  }
22
22
  function findTextStyleImpl(id) {
23
23
  if (id === "0x42") {
24
- return TextStyleSettings.fromJSON({ lineSpacingFactor: 12, fontName: "block", isBold: true });
24
+ return TextStyleSettings.fromJSON({ lineSpacingFactor: 12, font: { name: "block" }, isBold: true });
25
25
  }
26
- return TextStyleSettings.fromJSON({ lineSpacingFactor: 1, fontName: "other" });
26
+ return TextStyleSettings.fromJSON({ lineSpacingFactor: 1, font: { name: "other" } });
27
27
  }
28
28
  describe("layoutTextBlock", () => {
29
29
  describe("resolves TextStyleSettings", () => {
30
30
  it("inherits styling from TextBlock when Paragraph and Run have no style overrides", () => {
31
- const textBlock = TextBlock.create({ styleId: "0x42" });
31
+ const textBlock = TextBlock.create();
32
32
  const run = TextRun.create({ content: "test" });
33
33
  textBlock.appendParagraph();
34
34
  textBlock.appendRun(run);
35
35
  const tb = doLayout(textBlock, {
36
+ textStyleId: "0x42",
36
37
  findTextStyle: findTextStyleImpl,
37
38
  });
38
39
  expect(tb.lines.length).to.equal(1);
39
40
  expect(tb.lines[0].runs.length).to.equal(1);
40
41
  const runStyle = tb.lines[0].runs[0].style;
41
- expect(runStyle.fontName).to.equal("block");
42
+ expect(runStyle.font.name).to.equal("block");
42
43
  expect(runStyle.lineSpacingFactor).to.equal(12);
43
44
  expect(runStyle.isBold).to.be.true;
44
45
  });
45
46
  it("inherits style overrides from Paragraph when Run has no style overrides", () => {
46
- const textBlock = TextBlock.create({ styleId: "0x42" });
47
- const paragraph = Paragraph.create({ styleOverrides: { fontName: "paragraph" } });
48
- const run = TextRun.create({ content: "test" });
49
- textBlock.paragraphs.push(paragraph);
50
- textBlock.appendRun(run);
47
+ const textBlock = TextBlock.create();
48
+ textBlock.appendParagraph({ styleOverrides: { font: { name: "paragraph" } } });
49
+ textBlock.appendRun(TextRun.create({ content: "test" }));
51
50
  const tb = doLayout(textBlock, {
51
+ textStyleId: "0x42",
52
52
  findTextStyle: findTextStyleImpl,
53
53
  });
54
54
  expect(tb.lines.length).to.equal(1);
55
55
  expect(tb.lines[0].runs.length).to.equal(1);
56
56
  const runStyle = tb.lines[0].runs[0].style;
57
- expect(runStyle.fontName).to.equal("paragraph");
57
+ expect(runStyle.font.name).to.equal("paragraph");
58
58
  expect(runStyle.isBold).to.be.true;
59
59
  });
60
60
  it("uses Run style overrides when Run has overrides", () => {
61
- const textBlock = TextBlock.create({ styleId: "0x42" });
62
- const paragraph = Paragraph.create({ styleOverrides: { lineSpacingFactor: 55, fontName: "paragraph" } });
63
- const run = TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, fontName: "run" } });
64
- textBlock.paragraphs.push(paragraph);
65
- textBlock.appendRun(run);
61
+ const textBlock = TextBlock.create();
62
+ textBlock.appendParagraph({ styleOverrides: { lineSpacingFactor: 55, font: { name: "paragraph" } } });
63
+ textBlock.appendRun(TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, font: { name: "run" } } }));
66
64
  const tb = doLayout(textBlock, {
65
+ textStyleId: "0x42",
67
66
  findTextStyle: findTextStyleImpl,
68
67
  });
69
68
  expect(tb.lines.length).to.equal(1);
70
69
  expect(tb.lines[0].runs.length).to.equal(1);
71
70
  const runStyle = tb.lines[0].runs[0].style;
72
- expect(runStyle.fontName).to.equal("run");
71
+ expect(runStyle.font.name).to.equal("run");
73
72
  expect(runStyle.isBold).to.be.true;
74
73
  });
75
74
  it("still uses TextBlock specific styles when Run has style overrides", () => {
76
- // Some style settings only make sense on a TextBlock, so they are always applied from the TextBlock, even if the Run has a style override.
77
- const textBlock = TextBlock.create({ styleId: "0x42" });
78
- const run = TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, fontName: "run" } });
75
+ // Some style settings make sense on a TextBlock, so they are always applied from the TextBlock, even if the Run has a style override.
76
+ const textBlock = TextBlock.create();
77
+ const run = TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, font: { name: "run" } } });
79
78
  textBlock.appendParagraph();
80
79
  textBlock.appendRun(run);
81
80
  const tb = doLayout(textBlock, {
81
+ textStyleId: "0x42",
82
82
  findTextStyle: findTextStyleImpl,
83
83
  });
84
84
  expect(tb.lines.length).to.equal(1);
@@ -87,10 +87,9 @@ describe("layoutTextBlock", () => {
87
87
  expect(runStyle.lineSpacingFactor).to.equal(12);
88
88
  });
89
89
  it("inherits overrides from TextBlock, Paragraph and Run when there is no styleId", () => {
90
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { widthFactor: 34, lineHeight: 3, lineSpacingFactor: 12, isBold: true } });
91
- const paragraph = Paragraph.create({ styleOverrides: { lineHeight: 56, color: 0xff0000, frame: { shape: "octagon" } } });
92
- const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, fontName: "override", leader: { wantElbow: true } } });
93
- textBlock.paragraphs.push(paragraph);
90
+ const textBlock = TextBlock.create({ styleOverrides: { widthFactor: 34, textHeight: 3, lineSpacingFactor: 12, paragraphSpacingFactor: 2, isBold: true } });
91
+ const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, font: { name: "override" }, leader: { wantElbow: true } } });
92
+ textBlock.appendParagraph({ styleOverrides: { textHeight: 56, paragraphSpacingFactor: 25, color: 0xff0000, frame: { shape: "octagon" } } });
94
93
  textBlock.appendRun(run);
95
94
  const tb = doLayout(textBlock, {
96
95
  findTextStyle: findTextStyleImpl,
@@ -100,25 +99,26 @@ describe("layoutTextBlock", () => {
100
99
  const runStyle = tb.lines[0].runs[0].style;
101
100
  // widthFactor is always taken from the TextBlock, even if the Run has overrides
102
101
  expect(runStyle.widthFactor).to.equal(34);
103
- // lineHeight is always taken from the TextBlock, even if the Run has overrides
104
- expect(runStyle.lineHeight).to.equal(3);
102
+ // paragraphSpacingFactor is always taken from the TextBlock, even if the Run has overrides
103
+ expect(runStyle.paragraphSpacingFactor).to.equal(2);
105
104
  // lineSpacingFactor is always taken from the TextBlock, even if the Run has overrides
106
105
  expect(runStyle.lineSpacingFactor).to.equal(12);
107
106
  // frame settings are always taken from the TextBlock, even if the Paragraph or Run has overrides
108
107
  expect(runStyle.frame.shape).to.equal("none");
109
108
  // leader settings are always taken from the TextBlock, even if the Paragraph or Run has overrides
110
109
  expect(runStyle.leader.wantElbow).to.be.false;
111
- expect(runStyle.fontName).to.equal("override");
110
+ expect(runStyle.font.name).to.equal("override");
112
111
  expect(runStyle.color).to.equal(0xff0000);
113
112
  expect(runStyle.isBold).to.be.true;
113
+ expect(runStyle.textHeight).to.equal(56);
114
114
  });
115
115
  it("does not inherit overrides in TextBlock or Paragraph when Run has same propertied overriden - unless they are TextBlock specific settings", () => {
116
- const textBlock = TextBlock.create({ styleId: "0x42", styleOverrides: { widthFactor: 34, lineHeight: 3, lineSpacingFactor: 12, isBold: true } });
117
- const paragraph = Paragraph.create({ styleOverrides: { lineHeight: 56, color: 0xff0000 } });
118
- const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, lineHeight: 6, lineSpacingFactor: 24, fontName: "override", isBold: false } });
119
- textBlock.paragraphs.push(paragraph);
116
+ const textBlock = TextBlock.create({ styleOverrides: { widthFactor: 34, margins: { left: 3 }, textHeight: 3, lineSpacingFactor: 12, paragraphSpacingFactor: 2, isBold: true, justification: "center" } });
117
+ const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, margins: { left: 4, right: 3 }, textHeight: 6, paragraphSpacingFactor: 25, lineSpacingFactor: 24, font: { name: "override" }, isBold: false, justification: "right" } });
118
+ textBlock.appendParagraph({ styleOverrides: { textHeight: 56, paragraphSpacingFactor: 50, color: 0xff0000, justification: "left" } });
120
119
  textBlock.appendRun(run);
121
120
  const tb = doLayout(textBlock, {
121
+ textStyleId: "0x42",
122
122
  findTextStyle: findTextStyleImpl,
123
123
  });
124
124
  expect(tb.lines.length).to.equal(1);
@@ -126,20 +126,25 @@ describe("layoutTextBlock", () => {
126
126
  const runStyle = tb.lines[0].runs[0].style;
127
127
  // widthFactor is always taken from the TextBlock, even if the Run has a styleId or overrides
128
128
  expect(runStyle.widthFactor).to.equal(34);
129
- // lineHeight is always taken from the TextBlock, even if the Run has a styleId or overrides
130
- expect(runStyle.lineHeight).to.equal(3);
129
+ // paragraphSpacingFactor is always taken from the TextBlock, even if the Run has overrides
130
+ expect(runStyle.paragraphSpacingFactor).to.equal(2);
131
131
  // lineSpacingFactor is always taken from the TextBlock, even if the Run has a styleId or overrides
132
132
  expect(runStyle.lineSpacingFactor).to.equal(12);
133
- expect(runStyle.fontName).to.equal("override");
133
+ // margins are always taken from the TextBlock, even if the Paragraph or Run has overrides
134
+ expect(runStyle.margins.left).to.equal(3);
135
+ expect(runStyle.margins.right).to.equal(0);
136
+ // justification is always taken from the TextBlock, even if the Paragraph or Run has overrides
137
+ expect(runStyle.justification).to.equal("center");
138
+ expect(runStyle.font.name).to.equal("override");
134
139
  expect(runStyle.color).to.equal(0xff0000);
135
140
  expect(runStyle.isBold).to.be.false;
141
+ expect(runStyle.textHeight).to.equal(6);
136
142
  });
137
143
  it("takes child overrides over parent overrides", () => {
138
144
  //...unless they are TextBlock specific as covered in other tests
139
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { fontName: "grandparent" } });
140
- const paragraph = Paragraph.create({ styleOverrides: { fontName: "parent" } });
141
- const run = TextRun.create({ content: "test", styleOverrides: { fontName: "child" } });
142
- textBlock.paragraphs.push(paragraph);
145
+ const textBlock = TextBlock.create({ styleOverrides: { font: { name: "grandparent" } } });
146
+ const run = TextRun.create({ content: "test", styleOverrides: { font: { name: "child" } } });
147
+ textBlock.appendParagraph({ styleOverrides: { font: { name: "parent" } } });
143
148
  textBlock.appendRun(run);
144
149
  const tb = doLayout(textBlock, {
145
150
  findTextStyle: findTextStyleImpl,
@@ -147,7 +152,7 @@ describe("layoutTextBlock", () => {
147
152
  expect(tb.lines.length).to.equal(1);
148
153
  expect(tb.lines[0].runs.length).to.equal(1);
149
154
  const runStyle = tb.lines[0].runs[0].style;
150
- expect(runStyle.fontName).to.equal("child");
155
+ expect(runStyle.font.name).to.equal("child");
151
156
  });
152
157
  });
153
158
  it("has consistent data when converted to a layout result", function () {
@@ -155,14 +160,14 @@ describe("layoutTextBlock", () => {
155
160
  this.skip();
156
161
  }
157
162
  // Initialize a new TextBlockLayout object
158
- const textBlock = TextBlock.create({ width: 50, styleId: "", styleOverrides: { widthFactor: 34, color: 0x00ff00, fontName: "arial" } });
163
+ const textBlock = TextBlock.create({ width: 50, styleOverrides: { widthFactor: 34, color: 0x00ff00, font: { name: "arial" } } });
159
164
  const run0 = TextRun.create({
160
165
  content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium mi sit amet magna malesuada, at venenatis ante eleifend.",
161
- styleOverrides: { lineHeight: 56, color: 0xff0000 },
166
+ styleOverrides: { textHeight: 56, color: 0xff0000 },
162
167
  });
163
168
  const run1 = TextRun.create({
164
169
  content: "Donec sit amet semper sapien. Nullam commodo, libero a accumsan lacinia, metus enim pharetra lacus, eu facilisis sem nisi eu dui.",
165
- styleOverrides: { widthFactor: 78, fontName: "run1" },
170
+ styleOverrides: { widthFactor: 78, font: { name: "run1" } },
166
171
  });
167
172
  const run2 = TextRun.create({
168
173
  content: "Duis dui quam, suscipit quis feugiat id, fermentum ut augue. Mauris iaculis odio rhoncus lorem eleifend, posuere viverra turpis elementum.",
@@ -194,8 +199,6 @@ describe("layoutTextBlock", () => {
194
199
  for (let i = 0; i < result.lines.length; i++) {
195
200
  const resultLine = result.lines[i];
196
201
  const originalLine = textBlockLayout.lines[i];
197
- // Source paragraph index matches
198
- expect(resultLine.sourceParagraphIndex).to.equal(textBlock.paragraphs.indexOf(originalLine.source));
199
202
  // Ranges match
200
203
  expect(resultLine.range).to.deep.equal(originalLine.range.toJSON());
201
204
  expect(resultLine.justificationRange).to.deep.equal(originalLine.justificationRange.toJSON());
@@ -204,8 +207,6 @@ describe("layoutTextBlock", () => {
204
207
  for (let j = 0; j < resultLine.runs.length; j++) {
205
208
  const resultRun = resultLine.runs[j];
206
209
  const originalRun = originalLine.runs[j];
207
- // Source run index matches
208
- expect(resultRun.sourceRunIndex).to.equal(textBlock.paragraphs[resultLine.sourceParagraphIndex].runs.indexOf(originalRun.source));
209
210
  // FontId matches
210
211
  expect(resultRun.fontId).to.equal(originalRun.fontId);
211
212
  // Offsets match
@@ -245,7 +246,7 @@ describe("layoutTextBlock", () => {
245
246
  expect(resultRun.denominatorRange).to.deep.equal(originalRun.denominatorRange.toJSON());
246
247
  }
247
248
  // Check that the result string matches what we expect
248
- const inputRun = textBlock.paragraphs[resultLine.sourceParagraphIndex].runs[resultRun.sourceRunIndex].clone();
249
+ const inputRun = originalRun.source;
249
250
  if (inputRun.type === "text") {
250
251
  const resultText = inputRun.content.substring(resultRun.characterOffset, resultRun.characterOffset + resultRun.characterCount);
251
252
  const originalText = inputRun.content.substring(originalRun.charOffset, originalRun.charOffset + originalRun.numChars);
@@ -261,51 +262,120 @@ describe("layoutTextBlock", () => {
261
262
  expect(marginRange.low.y).to.equal(layoutRange.low.y - (margins.bottom ?? 0));
262
263
  expect(marginRange.high.y).to.equal(layoutRange.high.y + (margins.top ?? 0));
263
264
  };
264
- const makeTextBlock = (margins) => {
265
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor: 0 }, margins });
266
- textBlock.appendRun(makeTextRun("abc"));
267
- textBlock.appendRun(makeTextRun("defg"));
268
- return textBlock;
265
+ const textBlock = TextBlock.create({ styleOverrides: { lineSpacingFactor: 0 } });
266
+ textBlock.appendRun(makeTextRun("abc"));
267
+ textBlock.appendRun(makeTextRun("defg"));
268
+ const marginStyleCallback = (margins) => {
269
+ return () => TextStyleSettings.fromJSON({ margins: { ...margins } });
269
270
  };
270
- let block = makeTextBlock({});
271
- let layout = doLayout(block);
271
+ let layout = doLayout(textBlock, {
272
+ findTextStyle: marginStyleCallback({}),
273
+ });
272
274
  // Margins should be 0 by default
273
275
  expect(layout.range.isAlmostEqual(layout.textRange)).to.be.true;
274
276
  expectMargins(layout.textRange, layout.range, {});
275
277
  // All margins should be applied to the range
276
- block = makeTextBlock({ left: 1, right: 2, top: 3, bottom: 4 });
277
- layout = doLayout(block);
278
+ layout = doLayout(textBlock, {
279
+ findTextStyle: marginStyleCallback({ left: 1, right: 2, top: 3, bottom: 4 }),
280
+ });
278
281
  expectMargins(layout.textRange, layout.range, { left: 1, right: 2, top: 3, bottom: 4 });
279
282
  // Just horizontal margins should be applied
280
- block = makeTextBlock({ left: 1, right: 2 });
281
- layout = doLayout(block);
283
+ layout = doLayout(textBlock, {
284
+ findTextStyle: marginStyleCallback({ left: 1, right: 2 }),
285
+ });
282
286
  expectMargins(layout.textRange, layout.range, { left: 1, right: 2 });
283
287
  // Just vertical margins should be applied
284
- block = makeTextBlock({ top: 1, bottom: 2 });
285
- layout = doLayout(block);
288
+ layout = doLayout(textBlock, {
289
+ findTextStyle: marginStyleCallback({ top: 1, bottom: 2 }),
290
+ });
286
291
  expectMargins(layout.textRange, layout.range, { top: 1, bottom: 2 });
287
292
  });
288
293
  describe("range", () => {
289
- it("aligns text to center based on height of stacked fraction", () => {
290
- const textBlock = TextBlock.create({ styleId: "" });
291
- const fractionRun = FractionRun.create({ numerator: "1", denominator: "2" });
292
- const textRun = TextRun.create({ content: "text" });
294
+ const round = (num, numDecimalPlaces) => {
295
+ const multiplier = Math.pow(100, numDecimalPlaces);
296
+ return Math.round(num * multiplier) / multiplier;
297
+ };
298
+ it("aligns text of the same size on the bottom of the line", () => {
299
+ const textBlock = TextBlock.create();
300
+ const run1 = TextRun.create({ content: "abc" });
301
+ const run2 = TextRun.create({ content: "defg" });
302
+ textBlock.appendRun(run1);
303
+ textBlock.appendRun(run2);
304
+ const layout = doLayout(textBlock);
305
+ const run1Layout = layout.lines[0].runs[0];
306
+ const run2Layout = layout.lines[0].runs[1];
307
+ expect(run1Layout.range.yLength()).to.equal(1);
308
+ expect(run2Layout.range.yLength()).to.equal(1);
309
+ expect(run1Layout.offsetFromLine.y).to.equal(0);
310
+ expect(run2Layout.offsetFromLine.y).to.equal(0);
311
+ });
312
+ it("aligns text of varying sizes to the baseline of the largest text", () => {
313
+ const textBlock = TextBlock.create();
314
+ const smallText = TextRun.create({ content: "small", styleOverrides: { textHeight: 1 } });
315
+ const largeText = TextRun.create({ content: "large", styleOverrides: { textHeight: 3 } });
316
+ textBlock.appendRun(smallText);
317
+ textBlock.appendRun(largeText);
318
+ const layout = doLayout(textBlock);
319
+ const smallLayout = layout.lines[0].runs[0];
320
+ const largeLayout = layout.lines[0].runs[1];
321
+ expect(smallLayout.range.yLength()).to.equal(1);
322
+ expect(largeLayout.range.yLength()).to.equal(3);
323
+ expect(largeLayout.offsetFromLine.y).to.equal(0);
324
+ expect(smallLayout.offsetFromLine.y).to.equal(0);
325
+ });
326
+ it("aligns text to center based on height of the largest stacked fraction", () => {
327
+ const textBlock = TextBlock.create();
328
+ const fractionRun = FractionRun.create({ numerator: "1", denominator: "2", styleOverrides: { textHeight: 4 } });
329
+ const textRun = TextRun.create({ content: "text", styleOverrides: { textHeight: 2 } });
293
330
  textBlock.appendRun(fractionRun);
294
331
  textBlock.appendRun(textRun);
295
332
  const layout = doLayout(textBlock);
296
333
  const fractionLayout = layout.lines[0].runs[0];
297
334
  const textLayout = layout.lines[0].runs[1];
298
- const round = (num, numDecimalPlaces) => {
299
- const multiplier = Math.pow(100, numDecimalPlaces);
300
- return Math.round(num * multiplier) / multiplier;
301
- };
302
- expect(textLayout.range.yLength()).to.equal(1);
303
- expect(round(fractionLayout.range.yLength(), 2)).to.equal(1.75);
335
+ expect(round(fractionLayout.range.yLength(), 2)).to.equal(7);
336
+ expect(textLayout.range.yLength()).to.equal(2);
337
+ // Fraction should be defining the line height
304
338
  expect(fractionLayout.offsetFromLine.y).to.equal(0);
305
- expect(round(textLayout.offsetFromLine.y, 3)).to.equal(.375);
339
+ expect(round(textLayout.offsetFromLine.y, 2)).to.equal(2.5);
340
+ });
341
+ it("aligns the largest non-fraction text to the center based on height of stacked fraction and aligns all other text to the baseline", () => {
342
+ const textBlock = TextBlock.create();
343
+ const smallText = TextRun.create({ content: "s", styleOverrides: { textHeight: 1 } });
344
+ const mediumText = TextRun.create({ content: "m", styleOverrides: { textHeight: 2 } });
345
+ const fraction = FractionRun.create({ numerator: "1", denominator: "2", styleOverrides: { textHeight: 4 } });
346
+ textBlock.appendRun(smallText);
347
+ textBlock.appendRun(mediumText);
348
+ textBlock.appendRun(fraction);
349
+ const layout = doLayout(textBlock);
350
+ const smallLayout = layout.lines[0].runs[0];
351
+ const mediumLayout = layout.lines[0].runs[1];
352
+ const fractionLayout = layout.lines[0].runs[2];
353
+ expect(smallLayout.range.yLength()).to.equal(1);
354
+ expect(mediumLayout.range.yLength()).to.equal(2);
355
+ expect(round(fractionLayout.range.yLength(), 2)).to.equal(7);
356
+ expect(round(mediumLayout.offsetFromLine.y, 2)).to.equal(2.5);
357
+ expect(round(smallLayout.offsetFromLine.y, 2)).to.equal(2.5);
358
+ expect(fractionLayout.offsetFromLine.y).to.equal(0);
359
+ });
360
+ it("aligns fractions to the baseline of same sized text", () => {
361
+ const textBlock = TextBlock.create();
362
+ const text = TextRun.create({ content: "t", styleOverrides: { textHeight: 3 } });
363
+ const fraction = FractionRun.create({ numerator: "1", denominator: "2", styleOverrides: { textHeight: 3 } });
364
+ textBlock.appendRun(text);
365
+ textBlock.appendRun(fraction);
366
+ const layout = doLayout(textBlock);
367
+ const textLayout = layout.lines[0].runs[0];
368
+ const fractionLayout = layout.lines[0].runs[1];
369
+ expect(textLayout.range.yLength()).to.equal(3);
370
+ expect(round(fractionLayout.range.yLength(), 2)).to.equal(5.25);
371
+ expect(round(textLayout.offsetFromLine.y, 3)).to.equal(1.125);
372
+ // Slightly lower than text baseline so that the fraction appears centered on the text
373
+ expect(round(fractionLayout.offsetFromLine.y, 3)).to.equal(0.075);
306
374
  });
307
375
  it("produces one line per paragraph if document width <= 0", () => {
308
- const textBlock = TextBlock.create({ styleId: "" });
376
+ const lineSpacingFactor = 0.5;
377
+ const paragraphSpacingFactor = 0.25;
378
+ const textBlock = TextBlock.create({ styleOverrides: { paragraphSpacingFactor, lineSpacingFactor } });
309
379
  for (let i = 0; i < 4; i++) {
310
380
  const layout = doLayout(textBlock);
311
381
  if (i === 0) {
@@ -314,7 +384,7 @@ describe("layoutTextBlock", () => {
314
384
  else {
315
385
  expect(layout.lines.length).to.equal(i);
316
386
  expect(layout.range.low.x).to.equal(0);
317
- expect(layout.range.low.y).to.equal(-i - (0.5 * (i - 1))); // lineSpacingFactor=0.5
387
+ expect(layout.range.low.y).to.equal(-i - ((i - 1) * (lineSpacingFactor + paragraphSpacingFactor)));
318
388
  expect(layout.range.high.x).to.equal(i * 3);
319
389
  expect(layout.range.high.y).to.equal(0);
320
390
  }
@@ -336,14 +406,14 @@ describe("layoutTextBlock", () => {
336
406
  }
337
407
  const p = textBlock.appendParagraph();
338
408
  for (let j = 0; j <= i; j++) {
339
- p.runs.push(TextRun.create({ content: "Run" }));
409
+ p.children.push(TextRun.create({ content: "Run" }));
340
410
  }
341
411
  }
342
412
  });
343
413
  it("produces a new line for each LineBreakRun", () => {
344
414
  const lineSpacingFactor = 0.5;
345
- const lineHeight = 1;
346
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor, lineHeight } });
415
+ const textHeight = 1;
416
+ const textBlock = TextBlock.create({ styleOverrides: { lineSpacingFactor, textHeight } });
347
417
  textBlock.appendRun(TextRun.create({ content: "abc" }));
348
418
  textBlock.appendRun(LineBreakRun.create());
349
419
  textBlock.appendRun(TextRun.create({ content: "def" }));
@@ -358,12 +428,13 @@ describe("layoutTextBlock", () => {
358
428
  expect(tb.range.low.x).to.equal(0);
359
429
  expect(tb.range.high.x).to.equal(6);
360
430
  expect(tb.range.high.y).to.equal(0);
361
- expect(tb.range.low.y).to.equal(-(lineSpacingFactor * 2 + lineHeight * 3));
431
+ // paragraphSpacingFactor should not be applied to linebreaks, but lineSpacingFactor should.
432
+ expect(tb.range.low.y).to.equal(-(lineSpacingFactor * 2 + textHeight * 3));
362
433
  });
363
434
  it("applies tab shifts", () => {
364
- const lineHeight = 1;
435
+ const textHeight = 1;
365
436
  const tabInterval = 6;
366
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight, tabInterval } });
437
+ const textBlock = TextBlock.create({ styleOverrides: { textHeight, tabInterval } });
367
438
  // Appends a line that looks like `stringOne` TAB `stringTwo` LINEBREAK
368
439
  const appendLine = (stringOne, stringTwo, wantLineBreak = true) => {
369
440
  if (stringOne.length > 0)
@@ -374,15 +445,15 @@ describe("layoutTextBlock", () => {
374
445
  if (wantLineBreak)
375
446
  textBlock.appendRun(LineBreakRun.create());
376
447
  };
377
- // The extra whitespace is intentional to show where the tab stops should be.
378
- appendLine("", "a");
379
- appendLine("", "bc");
380
- appendLine("a", "a");
381
- appendLine("bc", "bc");
382
- appendLine("cde", "cde");
383
- appendLine("cdefg", "cde"); // this one is the max tab distance before needing to move to the next tab stop
384
- appendLine("cdefgh", "cde"); // This one should push to the next tab stop.
385
- appendLine("cdefghi", "cde", false); // This one should push to the next tab stop.
448
+ // The extra comments are intentional to show where the tab stops should be.
449
+ appendLine("", /*______*/ "a");
450
+ appendLine("", /*______*/ "bc");
451
+ appendLine("a", /*_____*/ "a");
452
+ appendLine("bc", /*____*/ "bc");
453
+ appendLine("cde", /*___*/ "cde");
454
+ appendLine("cdefg", /*_*/ "cde"); // this one is the max tab distance before needing to move to the next tab stop
455
+ appendLine("cdefgh", /*______*/ "cde"); // This one should push to the next tab stop.
456
+ appendLine("cdefghi", /*_____*/ "cde", false); // This one should push to the next tab stop.
386
457
  const tb = doLayout(textBlock);
387
458
  tb.lines.forEach((line, index) => {
388
459
  const firstTextRun = (line.runs[0].source.type === "text") ? line.runs[0] : undefined;
@@ -393,9 +464,9 @@ describe("layoutTextBlock", () => {
393
464
  });
394
465
  });
395
466
  it("applies consecutive tab shifts", () => {
396
- const lineHeight = 1;
467
+ const textHeight = 1;
397
468
  const tabInterval = 6;
398
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight, tabInterval } });
469
+ const textBlock = TextBlock.create({ styleOverrides: { textHeight, tabInterval } });
399
470
  // line 0: ----->----->----->LINEBREAK
400
471
  textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
401
472
  textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
@@ -426,7 +497,7 @@ describe("layoutTextBlock", () => {
426
497
  const line2 = tb.lines[2];
427
498
  const line3 = tb.lines[3];
428
499
  expect(line0.runs.length).to.equal(4);
429
- expect(line0.range.xLength()).to.equal(3 * tabInterval, `Lines with only tabs should have the correct range length`);
500
+ expect(line0.range.xLength()).to.equal(3 * tabInterval, `Lines with tabs should have the correct range length`);
430
501
  expect(line1.runs.length).to.equal(4);
431
502
  expect(line1.range.xLength()).to.equal(2 * tabInterval, `Tabs should be applied correctly when they are at the end of a line`);
432
503
  expect(line2.runs.length).to.equal(5);
@@ -434,10 +505,12 @@ describe("layoutTextBlock", () => {
434
505
  expect(line3.runs.length).to.equal(7);
435
506
  expect(line3.range.xLength()).to.equal(7 + 3 + 7, `Multiple tabs with different intervals should be applied correctly`);
436
507
  });
437
- it("computes ranges based on custom line spacing and line height", () => {
508
+ it("computes ranges based on custom line spacing, text height, and indentation", () => {
438
509
  const lineSpacingFactor = 2;
439
- const lineHeight = 3;
440
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor, lineHeight } });
510
+ const textHeight = 3;
511
+ const paragraphSpacingFactor = 13;
512
+ const indentation = 7;
513
+ const textBlock = TextBlock.create({ styleOverrides: { lineSpacingFactor, textHeight, paragraphSpacingFactor, indentation } });
441
514
  textBlock.appendRun(TextRun.create({ content: "abc" }));
442
515
  textBlock.appendRun(LineBreakRun.create());
443
516
  textBlock.appendRun(TextRun.create({ content: "def" }));
@@ -449,15 +522,85 @@ describe("layoutTextBlock", () => {
449
522
  expect(tb.lines[0].runs.length).to.equal(2);
450
523
  expect(tb.lines[1].runs.length).to.equal(3);
451
524
  expect(tb.lines[2].runs.length).to.equal(1);
452
- // We have 3 lines each `lineHeight` high, plus 2 line breaks in between each `lineHeight*lineSpacingFactor` high.
453
- expect(tb.range.low.x).to.equal(0);
454
- expect(tb.range.high.x).to.equal(6);
525
+ /* Final TextBlock should look like:
526
+ ⇥abc↵
527
+ ⇥defghi↵
528
+ ⇥jkl
529
+
530
+ Where ↵ = LineBreak, ¶ = ParagraphBreak, ⇥ = indentation
531
+
532
+ We have 3 lines each `textHeight` high, plus 2 line breaks in between each `textHeight*lineSpacingFactor` high.
533
+ No paragraph spacing should be applied since there is one paragraph.
534
+ */
535
+ expect(tb.range.low.x).to.equal(7);
536
+ expect(tb.range.high.x).to.equal(6 + 7); // 7 for indentation, 6 for the length of "defghi"
537
+ expect(tb.range.high.y).to.equal(0);
538
+ expect(tb.range.low.y).to.equal(-(textHeight * 3 + (textHeight * lineSpacingFactor) * 2));
539
+ expect(tb.lines[0].offsetFromDocument.y).to.equal(-textHeight);
540
+ expect(tb.lines[1].offsetFromDocument.y).to.equal(tb.lines[0].offsetFromDocument.y - (textHeight + textHeight * lineSpacingFactor));
541
+ expect(tb.lines[2].offsetFromDocument.y).to.equal(tb.lines[1].offsetFromDocument.y - (textHeight + textHeight * lineSpacingFactor));
542
+ tb.lines.forEach((line) => expect(line.offsetFromDocument.x).to.equal(7));
543
+ });
544
+ it("computes paragraph spacing and indentation", () => {
545
+ const lineSpacingFactor = 2;
546
+ const textHeight = 3;
547
+ const paragraphSpacingFactor = 13;
548
+ const indentation = 7;
549
+ const tabInterval = 5;
550
+ const textBlock = TextBlock.create({ styleOverrides: { lineSpacingFactor, textHeight, paragraphSpacingFactor, indentation, tabInterval } });
551
+ const p1 = textBlock.appendParagraph();
552
+ p1.children.push(TextRun.create({ content: "abc" })); // Line 1
553
+ p1.children.push(LineBreakRun.create());
554
+ p1.children.push(TextRun.create({ content: "def" })); // Line 2
555
+ const p2 = textBlock.appendParagraph();
556
+ p2.children.push(TextRun.create({ content: "ghi" })); // Line 3
557
+ const list = List.create();
558
+ list.children.push(Paragraph.create({ children: [{ type: "text", content: "list item 1" }] })); // Line 4
559
+ list.children.push(Paragraph.create({ children: [{ type: "text", content: "list item 2" }] })); // Line 5
560
+ list.children.push(Paragraph.create({ children: [{ type: "text", content: "list item 3" }] })); // Line 6
561
+ p2.children.push(list);
562
+ const tb = doLayout(textBlock);
563
+ expect(tb.lines.length).to.equal(6);
564
+ /* Final TextBlock should look like:
565
+ ⇥abc↵
566
+ ⇥def¶
567
+ ⇥ghi¶
568
+ ⇥→1. list item 1¶
569
+ ⇥→2. list item 2¶
570
+ ⇥→3. list item 3
571
+
572
+ Where ↵ = LineBreak, ¶ = ParagraphBreak, → = tabInterval/2, ⇥ = indentation
573
+
574
+ We have:
575
+ 6 lines each `textHeight` high
576
+ 5 line breaks in between each `textHeight*lineSpacingFactor` high
577
+ 4 paragraph breaks in between each `textHeight*paragraphSpacingFactor` high
578
+ */
579
+ expect(tb.range.low.x).to.equal(7); // 7 for indentation
580
+ expect(tb.range.high.x).to.equal(7 + 5 + 11); // 7 for indentation, 5 for the tab stop, 11 for the length of "list item 1"
455
581
  expect(tb.range.high.y).to.equal(0);
456
- expect(tb.range.low.y).to.equal(-(lineHeight * 3 + (lineHeight * lineSpacingFactor) * 2));
457
- expect(tb.lines[0].offsetFromDocument.y).to.equal(-lineHeight);
458
- expect(tb.lines[1].offsetFromDocument.y).to.equal(tb.lines[0].offsetFromDocument.y - (lineHeight + lineHeight * lineSpacingFactor));
459
- expect(tb.lines[2].offsetFromDocument.y).to.equal(tb.lines[1].offsetFromDocument.y - (lineHeight + lineHeight * lineSpacingFactor));
460
- expect(tb.lines.every((line) => line.offsetFromDocument.x === 0)).to.be.true;
582
+ expect(tb.range.low.y).to.equal(-(textHeight * 6 + (textHeight * lineSpacingFactor) * 5 + (textHeight * paragraphSpacingFactor) * 4));
583
+ // Cumulative vertical offsets to help make the test more readable.
584
+ let offsetY = -textHeight;
585
+ let offsetX = indentation;
586
+ expect(tb.lines[0].offsetFromDocument.y).to.equal(offsetY);
587
+ expect(tb.lines[0].offsetFromDocument.x).to.equal(offsetX);
588
+ offsetY -= (textHeight + textHeight * lineSpacingFactor);
589
+ expect(tb.lines[1].offsetFromDocument.y).to.equal(offsetY);
590
+ expect(tb.lines[1].offsetFromDocument.x).to.equal(offsetX);
591
+ offsetY -= (textHeight + textHeight * lineSpacingFactor + textHeight * paragraphSpacingFactor);
592
+ expect(tb.lines[2].offsetFromDocument.y).to.equal(offsetY);
593
+ expect(tb.lines[2].offsetFromDocument.x).to.equal(offsetX);
594
+ offsetX += tabInterval; // List items are indented using tabInterval.
595
+ offsetY -= (textHeight + textHeight * lineSpacingFactor + textHeight * paragraphSpacingFactor);
596
+ expect(tb.lines[3].offsetFromDocument.y).to.equal(offsetY);
597
+ expect(tb.lines[3].offsetFromDocument.x).to.equal(offsetX);
598
+ offsetY -= (textHeight + textHeight * lineSpacingFactor + textHeight * paragraphSpacingFactor);
599
+ expect(tb.lines[4].offsetFromDocument.y).to.equal(offsetY);
600
+ expect(tb.lines[4].offsetFromDocument.x).to.equal(offsetX);
601
+ offsetY -= (textHeight + textHeight * lineSpacingFactor + textHeight * paragraphSpacingFactor);
602
+ expect(tb.lines[5].offsetFromDocument.y).to.equal(offsetY);
603
+ expect(tb.lines[5].offsetFromDocument.x).to.equal(offsetX);
461
604
  });
462
605
  function expectRange(width, height, range) {
463
606
  expect(range.xLength()).to.equal(width);
@@ -467,7 +610,7 @@ describe("layoutTextBlock", () => {
467
610
  if (!isIntlSupported()) {
468
611
  this.skip();
469
612
  }
470
- const block = TextBlock.create({ styleId: "", width: 3, styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
613
+ const block = TextBlock.create({ width: 3, styleOverrides: { textHeight: 1, lineSpacingFactor: 0 } });
471
614
  function expectBlockRange(width, height) {
472
615
  const layout = doLayout(block);
473
616
  expectRange(width, height, layout.range);
@@ -491,7 +634,7 @@ describe("layoutTextBlock", () => {
491
634
  if (!isIntlSupported()) {
492
635
  this.skip();
493
636
  }
494
- const block = TextBlock.create({ styleId: "", styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
637
+ const block = TextBlock.create({ styleOverrides: { textHeight: 1, lineSpacingFactor: 0 } });
495
638
  function expectBlockRange(width, height) {
496
639
  const layout = doLayout(block);
497
640
  expectRange(width, height, layout.range);
@@ -504,17 +647,155 @@ describe("layoutTextBlock", () => {
504
647
  block.width = 10;
505
648
  expectBlockRange(10, 2);
506
649
  });
650
+ it("computes range for list markers and list items based on indentation", function () {
651
+ const lineSpacingFactor = 2;
652
+ const textHeight = 3;
653
+ const paragraphSpacingFactor = 13;
654
+ const indentation = 7;
655
+ const tabInterval = 5;
656
+ const listChildren = [
657
+ {
658
+ children: [
659
+ {
660
+ type: "text",
661
+ content: "Oranges",
662
+ }
663
+ ]
664
+ },
665
+ {
666
+ children: [
667
+ {
668
+ type: "text",
669
+ content: "Apples",
670
+ },
671
+ {
672
+ type: "list",
673
+ styleOverrides: { listMarker: { enumerator: ListMarkerEnumerator.Bullet } },
674
+ children: [
675
+ {
676
+ children: [
677
+ {
678
+ type: "text",
679
+ content: "Red",
680
+ }
681
+ ]
682
+ },
683
+ {
684
+ children: [
685
+ {
686
+ type: "text",
687
+ content: "Green",
688
+ },
689
+ {
690
+ type: "list",
691
+ styleOverrides: { listMarker: { enumerator: ListMarkerEnumerator.RomanNumeral, case: "lower", terminator: "period" } },
692
+ children: [
693
+ {
694
+ children: [
695
+ {
696
+ type: "text",
697
+ content: "Granny Smith",
698
+ }
699
+ ]
700
+ },
701
+ {
702
+ children: [
703
+ {
704
+ type: "text",
705
+ content: "Rhode Island Greening",
706
+ }
707
+ ]
708
+ }
709
+ ]
710
+ }
711
+ ]
712
+ },
713
+ {
714
+ children: [
715
+ {
716
+ type: "text",
717
+ content: "Yellow",
718
+ }
719
+ ]
720
+ }
721
+ ]
722
+ }
723
+ ]
724
+ }
725
+ ];
726
+ const textBlock = TextBlock.create({ styleOverrides: { lineSpacingFactor, textHeight, paragraphSpacingFactor, indentation, tabInterval } });
727
+ const p1 = textBlock.appendParagraph();
728
+ p1.children.push(List.create({ children: listChildren }));
729
+ /* Final TextBlock should look like:
730
+ →1.→Oranges¶
731
+ →2.→Apples¶
732
+ →→•→Red¶
733
+ →→•→Green¶
734
+ → →→i. →Granny Smith¶
735
+ → →→ii.→Rhode Island Greening¶
736
+ →→•→Yellow
737
+
738
+ Where ↵ = LineBreak, ¶ = ParagraphBreak, → = tab, → = tabInterval/2, ⇥ = indentation
739
+
740
+ We have:
741
+ 7 lines each `textHeight` high
742
+ 6 line breaks in between each `textHeight*lineSpacingFactor` high
743
+ 6 paragraph breaks in between each `textHeight*paragraphSpacingFactor` high
744
+ */
745
+ const tb = doLayout(textBlock);
746
+ expect(tb.lines.length).to.equal(7);
747
+ expect(tb.range.low.x).to.equal(7 + 5 - 5 / 2 - 2); // indentation + tabInterval - tabInterval/2 (for marker offset) + 2 (for the marker "1." justification, it's 2 characters wide)
748
+ expect(tb.range.high.x).to.equal(7 + 3 * 5 + 21); // 7 for indentation, 3 * 5 for the most nested tab stops, 21 for the length of "Rhode Island Greening"
749
+ expect(tb.range.high.y).to.equal(0);
750
+ expect(tb.range.low.y).to.equal(-(textHeight * 7 + (textHeight * lineSpacingFactor) * 6 + (textHeight * paragraphSpacingFactor) * 6));
751
+ // Cumulative vertical offsets to help make the test more readable.
752
+ let offsetY = -textHeight;
753
+ for (const line of tb.lines) {
754
+ expect(line.offsetFromDocument.y).to.equal(offsetY);
755
+ expect(line.marker).to.not.be.undefined;
756
+ expect(line.marker?.offsetFromLine.y).to.equal((textHeight - line.marker.range.yLength()) / 2);
757
+ offsetY -= (textHeight + textHeight * lineSpacingFactor + textHeight * paragraphSpacingFactor);
758
+ }
759
+ let markerXLength = tb.lines[0].marker.range.xLength();
760
+ let inset = indentation + tabInterval;
761
+ expect(tb.lines[0].offsetFromDocument.x).to.equal(inset); // →Oranges
762
+ expect(markerXLength).to.equal(2); // "1." is 2 characters wide
763
+ expect(tb.lines[0].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
764
+ markerXLength = tb.lines[1].marker.range.xLength();
765
+ expect(tb.lines[1].offsetFromDocument.x).to.equal(inset); // →Apples
766
+ expect(tb.lines[1].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
767
+ markerXLength = tb.lines[2].marker.range.xLength();
768
+ inset = indentation + tabInterval * 2;
769
+ expect(tb.lines[2].offsetFromDocument.x).to.equal(indentation + tabInterval * 2); // →→Red
770
+ expect(tb.lines[2].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
771
+ markerXLength = tb.lines[3].marker.range.xLength();
772
+ expect(tb.lines[3].offsetFromDocument.x).to.equal(indentation + tabInterval * 2); // →→Green
773
+ expect(tb.lines[3].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
774
+ markerXLength = tb.lines[4].marker.range.xLength();
775
+ expect(tb.lines[4].offsetFromDocument.x).to.equal(indentation + tabInterval * 3); // →→→Granny Smith
776
+ expect(tb.lines[4].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
777
+ markerXLength = tb.lines[5].marker.range.xLength();
778
+ expect(tb.lines[5].offsetFromDocument.x).to.equal(indentation + tabInterval * 3); // →→→Rhode Island Greening
779
+ expect(tb.lines[5].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
780
+ markerXLength = tb.lines[6].marker.range.xLength();
781
+ expect(tb.lines[6].offsetFromDocument.x).to.equal(indentation + tabInterval * 2); // →→Yellow
782
+ expect(tb.lines[6].marker.offsetFromLine.x).to.equal(0 - markerXLength - (tabInterval / 2));
783
+ });
507
784
  it("justifies lines", function () {
508
785
  if (!isIntlSupported()) {
509
786
  this.skip();
510
787
  }
511
- const block = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor: 0 } });
512
- function expectBlockRange(width, height) {
513
- const layout = doLayout(block);
788
+ const block = TextBlock.create({ styleOverrides: { lineSpacingFactor: 0 } });
789
+ function expectBlockRange(width, height, justification) {
790
+ const layout = doLayout(block, {
791
+ findTextStyle: () => TextStyleSettings.fromJSON({ justification })
792
+ });
514
793
  expectRange(width, height, layout.range);
515
794
  }
516
- function expectLineOffset(offset, lineIndex) {
517
- const layout = doLayout(block);
795
+ function expectLineOffset(offset, lineIndex, justification) {
796
+ const layout = doLayout(block, {
797
+ findTextStyle: () => TextStyleSettings.fromJSON({ justification }),
798
+ });
518
799
  expect(layout.lines.length).least(lineIndex + 1);
519
800
  const line = layout.lines[lineIndex];
520
801
  expect(line.offsetFromDocument.y).to.equal(-(lineIndex + 1));
@@ -524,70 +805,59 @@ describe("layoutTextBlock", () => {
524
805
  block.appendRun(makeTextRun("abc"));
525
806
  block.appendRun(makeTextRun("defg"));
526
807
  // 1 line of text with width 0: left, right, center justification.
527
- block.justification = "left";
528
- expectBlockRange(7, 1);
529
- expectLineOffset(0, 0);
530
- block.justification = "right";
531
- expectBlockRange(7, 1);
532
- expectLineOffset(0, 0);
533
- block.justification = "center";
534
- expectBlockRange(7, 1);
535
- expectLineOffset(0, 0);
808
+ expectBlockRange(7, 1, "left");
809
+ expectLineOffset(0, 0, "left");
810
+ expectBlockRange(7, 1, "right");
811
+ expectLineOffset(0, 0, "right");
812
+ expectBlockRange(7, 1, "center");
813
+ expectLineOffset(0, 0, "center");
536
814
  // 1 line of text from a width greater than number of characters: left, right, center justification.
537
815
  block.width = 10;
538
- block.justification = "left";
539
- expectBlockRange(10, 1);
540
- expectLineOffset(0, 0);
541
- block.justification = "right";
542
- expectBlockRange(10, 1);
543
- expectLineOffset(3, 0); // 3 = 10 - 7
544
- block.justification = "center";
545
- expectBlockRange(10, 1);
546
- expectLineOffset(1.5, 0); // 1.5 = (10 - 7) / 2
816
+ expectBlockRange(10, 1, "left");
817
+ expectLineOffset(0, 0, "left");
818
+ expectBlockRange(10, 1, "right");
819
+ expectLineOffset(3, 0, "right"); // 3 = 10 - 7
820
+ expectBlockRange(10, 1, "center");
821
+ expectLineOffset(1.5, 0, "center"); // 1.5 = (10 - 7) / 2
547
822
  // 2 line of text from a width less than number of characters: left, right, center justification.
548
- block.justification = "left";
549
823
  block.width = 4;
550
- expectBlockRange(4, 2);
551
- expectLineOffset(0, 0);
552
- expectLineOffset(0, 1);
553
- block.justification = "right";
554
- expectBlockRange(4, 2);
555
- expectLineOffset(1, 0);
556
- expectLineOffset(0, 1);
557
- block.justification = "center";
558
- expectBlockRange(4, 2);
559
- expectLineOffset(0.5, 0);
560
- expectLineOffset(0, 1);
824
+ expectBlockRange(4, 2, "left");
825
+ expectLineOffset(0, 0, "left");
826
+ expectLineOffset(0, 1, "left");
827
+ expectBlockRange(4, 2, "right");
828
+ expectLineOffset(1, 0, "right");
829
+ expectLineOffset(0, 1, "right");
830
+ expectBlockRange(4, 2, "center");
831
+ expectLineOffset(0.5, 0, "center");
832
+ expectLineOffset(0, 1, "center");
561
833
  // Testing text longer the the width of the text block.
562
834
  block.width = 2;
563
- block.justification = "left";
564
- expectBlockRange(4, 2);
565
- expectLineOffset(0, 0);
566
- expectLineOffset(0, 1);
567
- block.justification = "right";
568
- expectBlockRange(4, 2);
569
- expectLineOffset(-1, 0);
570
- expectLineOffset(-2, 1);
835
+ expectBlockRange(4, 2, "left");
836
+ expectLineOffset(0, 0, "left");
837
+ expectLineOffset(0, 1, "left");
838
+ expectBlockRange(4, 2, "right");
839
+ expectLineOffset(-1, 0, "right");
840
+ expectLineOffset(-2, 1, "right");
571
841
  block.appendRun(makeTextRun("123456789"));
572
- expectBlockRange(9, 3);
573
- expectLineOffset(-1, 0);
574
- expectLineOffset(-2, 1);
575
- expectLineOffset(-7, 2);
576
- block.justification = "center";
577
- expectBlockRange(9, 3);
578
- expectLineOffset(-0.5, 0);
579
- expectLineOffset(-1, 1);
580
- expectLineOffset(-3.5, 2);
842
+ expectBlockRange(9, 3, "right");
843
+ expectLineOffset(-1, 0, "right");
844
+ expectLineOffset(-2, 1, "right");
845
+ expectLineOffset(-7, 2, "right");
846
+ expectBlockRange(9, 3, "center");
847
+ expectLineOffset(-0.5, 0, "center");
848
+ expectLineOffset(-1, 1, "center");
849
+ expectLineOffset(-3.5, 2, "center");
581
850
  });
582
851
  });
583
852
  describe("word-wrapping", () => {
584
853
  function expectLines(input, width, expectedLines) {
585
- const textBlock = TextBlock.create({ styleId: "" });
854
+ const textBlock = TextBlock.create({ styleOverrides: { paragraphSpacingFactor: 0, lineSpacingFactor: 0, textHeight: 1 } });
586
855
  textBlock.width = width;
587
856
  const run = makeTextRun(input);
588
857
  textBlock.appendRun(run);
589
858
  const layout = doLayout(textBlock);
590
- expect(layout.lines.every((line) => line.runs.every((r) => r.source === run))).to.be.true;
859
+ const content = run.stringify();
860
+ expect(layout.lines.every((line) => line.runs.every((r) => r.source.stringify() === content))).to.be.true;
591
861
  const actual = layout.lines.map((line) => line.runs.map((runLayout) => runLayout.source.content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)).join(""));
592
862
  expect(actual).to.deep.equal(expectedLines);
593
863
  return layout;
@@ -596,7 +866,7 @@ describe("layoutTextBlock", () => {
596
866
  if (!isIntlSupported()) {
597
867
  this.skip();
598
868
  }
599
- const textBlock = TextBlock.create({ styleId: "" });
869
+ const textBlock = TextBlock.create();
600
870
  textBlock.width = 6;
601
871
  textBlock.appendRun(makeTextRun("ab"));
602
872
  expect(doLayout(textBlock).lines.length).to.equal(1);
@@ -684,8 +954,8 @@ describe("layoutTextBlock", () => {
684
954
  if (!isIntlSupported()) {
685
955
  this.skip();
686
956
  }
687
- const lineHeight = 1;
688
- const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight } });
957
+ const textHeight = 1;
958
+ const textBlock = TextBlock.create({ styleOverrides: { textHeight } });
689
959
  // line 0: -->-->------> LINEBREAK
690
960
  textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
691
961
  textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
@@ -755,7 +1025,7 @@ describe("layoutTextBlock", () => {
755
1025
  if (!isIntlSupported()) {
756
1026
  this.skip();
757
1027
  }
758
- const textBlock = TextBlock.create({ styleId: "" });
1028
+ const textBlock = TextBlock.create();
759
1029
  for (const str of ["The ", "quick brown", " fox jumped over ", "the lazy ", "dog"]) {
760
1030
  textBlock.appendRun(makeTextRun(str));
761
1031
  }
@@ -799,7 +1069,7 @@ describe("layoutTextBlock", () => {
799
1069
  if (!isIntlSupported()) {
800
1070
  this.skip();
801
1071
  }
802
- const block = TextBlock.create({ styleId: "" });
1072
+ const block = TextBlock.create();
803
1073
  block.appendRun(makeTextRun("aa")); // 2 chars wide
804
1074
  block.appendRun(makeTextRun("bb ccc d ee")); // 11 chars wide
805
1075
  block.appendRun(makeTextRun("ff ggg h")); // 8 chars wide
@@ -839,7 +1109,7 @@ describe("layoutTextBlock", () => {
839
1109
  if (!isIntlSupported()) {
840
1110
  this.skip();
841
1111
  }
842
- const block = TextBlock.create({ styleId: "", styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
1112
+ const block = TextBlock.create({ styleOverrides: { textHeight: 1, lineSpacingFactor: 0 } });
843
1113
  block.appendRun(makeTextRun("abc defg"));
844
1114
  const layout1 = doLayout(block);
845
1115
  let width = layout1.range.xLength();
@@ -849,6 +1119,56 @@ describe("layoutTextBlock", () => {
849
1119
  const layout2 = doLayout(block);
850
1120
  expect(layout2.range.yLength()).to.equal(1);
851
1121
  });
1122
+ it("wraps list items and applies indentation/insets for narrow text block width", function () {
1123
+ if (!isIntlSupported()) {
1124
+ this.skip();
1125
+ }
1126
+ const textBlock = TextBlock.create({ styleOverrides: { indentation: 2, tabInterval: 3, textHeight: 1, lineSpacingFactor: 0, paragraphSpacingFactor: 0 } });
1127
+ /* Final TextBlock should look like:
1128
+ ⇥→1.→Lorem ipsum dolor sit amet, consectetur adipiscing elit¶ | Inset by 5
1129
+ ⇥→2.→sed do¶ | Inset by 5
1130
+ ⇥→→a.→eiusmod tempor¶ | Inset by 8
1131
+ ⇥→→b.→incididunt ut labore et dolore magna aliqua | Inset by 8
1132
+
1133
+ Where ↵ = LineBreak, ¶ = ParagraphBreak, → = tab, → = tabInterval/2, ⇥ = indentation
1134
+ */
1135
+ // Create nested list structure
1136
+ const list = List.create();
1137
+ list.children.push(Paragraph.create({ children: [TextRun.create({ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" })] }));
1138
+ const apples = Paragraph.create({ children: [TextRun.create({ content: "sed do" })] });
1139
+ const subList = List.create({ styleOverrides: { listMarker: { enumerator: ListMarkerEnumerator.Letter, case: "lower", terminator: "period" } } });
1140
+ subList.children.push(Paragraph.create({ children: [TextRun.create({ content: "eiusmod tempor" })] }));
1141
+ subList.children.push(Paragraph.create({ children: [TextRun.create({ content: "incididunt ut labore et dolore magna aliqua" })] }));
1142
+ apples.children.push(subList);
1143
+ list.children.push(apples);
1144
+ textBlock.appendParagraph().children.push(list);
1145
+ function expectLayout(width, expected) {
1146
+ textBlock.width = width;
1147
+ const layout = doLayout(textBlock);
1148
+ // Check that each line is wrapped to width
1149
+ const minWidth = Math.max(19, width); // 19 for the width of the longest word with inset: "⇥→→b.→incididunt "
1150
+ if (width > 0) {
1151
+ layout.lines.forEach((line) => {
1152
+ expect(line.justificationRange.xLength() + line.offsetFromDocument.x).to.be.at.most(minWidth);
1153
+ });
1154
+ }
1155
+ expect(layout.stringify()).to.equal(expected);
1156
+ // Top-level items should have indentation + tabInterval
1157
+ let inset = 2 + 3;
1158
+ layout.lines.forEach((line) => {
1159
+ if (line.stringify().includes("eiusmod"))
1160
+ inset += 3; // SubList items should have increased indentation
1161
+ expect(line.offsetFromDocument.x).to.equal(inset);
1162
+ });
1163
+ }
1164
+ // Check indentation/insets for each line, indentation: 2, tabInterval: 5
1165
+ expectLayout(0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit\nsed do\neiusmod tempor\nincididunt ut labore et dolore magna aliqua");
1166
+ expectLayout(70, "Lorem ipsum dolor sit amet, consectetur adipiscing elit\nsed do\neiusmod tempor\nincididunt ut labore et dolore magna aliqua");
1167
+ expectLayout(40, "Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit\nsed do\neiusmod tempor\nincididunt ut labore et dolore \nmagna aliqua");
1168
+ // TODO: layout should not pay attention to trailing whitespace when wrapping. I'll do this in another PR.
1169
+ expectLayout(21, "Lorem ipsum \ndolor sit amet, \nconsectetur \nadipiscing elit\nsed do\neiusmod \ntempor\nincididunt \nut labore et \ndolore magna \naliqua");
1170
+ expectLayout(15, "Lorem \nipsum \ndolor sit \namet, \nconsectetur \nadipiscing \nelit\nsed do\neiusmod \ntempor\nincididunt \nut \nlabore \net \ndolore \nmagna \naliqua");
1171
+ });
852
1172
  });
853
1173
  describe("grapheme offsets", () => {
854
1174
  function getLayoutResultAndStyleResolver(textBlock) {
@@ -856,24 +1176,24 @@ describe("layoutTextBlock", () => {
856
1176
  const result = layout.toResult();
857
1177
  const textStyleResolver = new TextStyleResolver({
858
1178
  textBlock,
1179
+ textStyleId: "",
859
1180
  iModel: {},
860
- modelId: undefined,
861
1181
  findTextStyle: () => TextStyleSettings.defaults
862
1182
  });
863
1183
  return { textStyleResolver, result };
864
1184
  }
865
1185
  it("should return an empty array if source type is not text", function () {
866
- const textBlock = TextBlock.create({ styleId: "" });
1186
+ const textBlock = TextBlock.create();
867
1187
  const fractionRun = FractionRun.create({ numerator: "1", denominator: "2" });
868
1188
  textBlock.appendRun(fractionRun);
869
1189
  const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
1190
+ const source = textBlock.children[0]; // FractionRun is not a TextRun
870
1191
  const args = {
871
- textBlock,
1192
+ source,
872
1193
  iModel: {},
873
1194
  textStyleResolver,
874
1195
  findFontId: () => 0,
875
1196
  computeTextRange: computeTextRangeAsStringLength,
876
- paragraphIndex: result.lines[0].sourceParagraphIndex,
877
1197
  runLayoutResult: result.lines[0].runs[0],
878
1198
  graphemeCharIndexes: [0],
879
1199
  };
@@ -881,17 +1201,17 @@ describe("layoutTextBlock", () => {
881
1201
  expect(graphemeRanges).to.be.an("array").that.is.empty;
882
1202
  });
883
1203
  it("should handle empty text content", function () {
884
- const textBlock = TextBlock.create({ styleId: "" });
1204
+ const textBlock = TextBlock.create();
885
1205
  const textRun = TextRun.create({ content: "" });
886
1206
  textBlock.appendRun(textRun);
887
1207
  const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
1208
+ const source = textBlock.children[0]; // FractionRun is not a TextRun
888
1209
  const args = {
889
- textBlock,
1210
+ source,
890
1211
  iModel: {},
891
1212
  textStyleResolver,
892
1213
  findFontId: () => 0,
893
1214
  computeTextRange: computeTextRangeAsStringLength,
894
- paragraphIndex: result.lines[0].sourceParagraphIndex,
895
1215
  runLayoutResult: result.lines[0].runs[0],
896
1216
  graphemeCharIndexes: [0], // Supply a grapheme index even though there is no text
897
1217
  };
@@ -899,17 +1219,17 @@ describe("layoutTextBlock", () => {
899
1219
  expect(graphemeRanges).to.be.an("array").that.is.empty;
900
1220
  });
901
1221
  it("should compute grapheme offsets correctly for a given text", function () {
902
- const textBlock = TextBlock.create({ styleId: "" });
1222
+ const textBlock = TextBlock.create();
903
1223
  const textRun = TextRun.create({ content: "hello" });
904
1224
  textBlock.appendRun(textRun);
905
1225
  const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
1226
+ const source = textBlock.children[0].children[0];
906
1227
  const args = {
907
- textBlock,
1228
+ source,
908
1229
  iModel: {},
909
1230
  textStyleResolver,
910
1231
  findFontId: () => 0,
911
1232
  computeTextRange: computeTextRangeAsStringLength,
912
- paragraphIndex: result.lines[0].sourceParagraphIndex,
913
1233
  runLayoutResult: result.lines[0].runs[0],
914
1234
  graphemeCharIndexes: [0, 1, 2, 3, 4],
915
1235
  };
@@ -919,18 +1239,18 @@ describe("layoutTextBlock", () => {
919
1239
  expect(graphemeRanges[4].high.x).to.equal(5);
920
1240
  });
921
1241
  it("should compute grapheme offsets correctly for non-English text", function () {
922
- const textBlock = TextBlock.create({ styleId: "" });
1242
+ const textBlock = TextBlock.create();
923
1243
  // Hindi - "Paragraph"
924
1244
  const textRun = TextRun.create({ content: "अनुच्छेद" });
925
1245
  textBlock.appendRun(textRun);
926
1246
  const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
1247
+ const source = textBlock.children[0].children[0];
927
1248
  const args = {
928
- textBlock,
1249
+ source,
929
1250
  iModel: {},
930
1251
  textStyleResolver,
931
1252
  findFontId: () => 0,
932
1253
  computeTextRange: computeTextRangeAsStringLength,
933
- paragraphIndex: result.lines[0].sourceParagraphIndex,
934
1254
  runLayoutResult: result.lines[0].runs[0],
935
1255
  graphemeCharIndexes: [0, 1, 3, 7],
936
1256
  };
@@ -942,17 +1262,17 @@ describe("layoutTextBlock", () => {
942
1262
  expect(graphemeRanges[3].high.x).to.equal(8);
943
1263
  });
944
1264
  it("should compute grapheme offsets correctly for emoji content", function () {
945
- const textBlock = TextBlock.create({ styleId: "" });
1265
+ const textBlock = TextBlock.create();
946
1266
  const textRun = TextRun.create({ content: "👨‍👦" });
947
1267
  textBlock.appendRun(textRun);
948
1268
  const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
1269
+ const source = textBlock.children[0].children[0];
949
1270
  const args = {
950
- textBlock,
1271
+ source,
951
1272
  iModel: {},
952
1273
  textStyleResolver,
953
1274
  findFontId: () => 0,
954
1275
  computeTextRange: computeTextRangeAsStringLength,
955
- paragraphIndex: result.lines[0].sourceParagraphIndex,
956
1276
  runLayoutResult: result.lines[0].runs[0],
957
1277
  graphemeCharIndexes: [0],
958
1278
  };
@@ -979,9 +1299,9 @@ describe("layoutTextBlock", () => {
979
1299
  expect(comic).to.equal(3);
980
1300
  expect(iModel.fonts.findId({ name: "Consolas" })).to.be.undefined;
981
1301
  function test(fontName, expectedFontId) {
982
- const textBlock = TextBlock.create({ styleId: "" });
983
- textBlock.appendRun(TextRun.create({ styleOverrides: { fontName } }));
984
- const textStyleResolver = new TextStyleResolver({ textBlock, iModel });
1302
+ const textBlock = TextBlock.create();
1303
+ textBlock.appendRun(TextRun.create({ styleOverrides: { font: { name: fontName } } }));
1304
+ const textStyleResolver = new TextStyleResolver({ textBlock, textStyleId: "", iModel });
985
1305
  const layout = layoutTextBlock({ textBlock, iModel, textStyleResolver });
986
1306
  const run = layout.lines[0].runs[0];
987
1307
  expect(run).not.to.be.undefined;
@@ -995,9 +1315,8 @@ describe("layoutTextBlock", () => {
995
1315
  });
996
1316
  function computeDimensions(args) {
997
1317
  const textBlock = TextBlock.create({
998
- styleId: "",
999
1318
  styleOverrides: {
1000
- lineHeight: args.height,
1319
+ textHeight: args.height,
1001
1320
  widthFactor: args.width,
1002
1321
  },
1003
1322
  });
@@ -1006,10 +1325,10 @@ describe("layoutTextBlock", () => {
1006
1325
  styleOverrides: {
1007
1326
  isBold: args.bold,
1008
1327
  isItalic: args.italic,
1009
- fontName: args.font ?? "Vera",
1328
+ font: { name: args.font ?? "Vera" },
1010
1329
  },
1011
1330
  }));
1012
- const textStyleResolver = new TextStyleResolver({ textBlock, iModel });
1331
+ const textStyleResolver = new TextStyleResolver({ textBlock, textStyleId: "", iModel });
1013
1332
  const range = layoutTextBlock({ textBlock, iModel, textStyleResolver }).range;
1014
1333
  return { x: range.high.x - range.low.x, y: range.high.y - range.low.y };
1015
1334
  }
@@ -1038,7 +1357,7 @@ describe("layoutTextBlock", () => {
1038
1357
  italic: false,
1039
1358
  fontId: 1,
1040
1359
  widthFactor: 1,
1041
- lineHeight: 1,
1360
+ textHeight: 1,
1042
1361
  baselineShift: "none",
1043
1362
  });
1044
1363
  }
@@ -1085,7 +1404,7 @@ describe("produceTextBlockGeometry", () => {
1085
1404
  return LineBreakRun.create({ styleOverrides });
1086
1405
  }
1087
1406
  function makeTextBlock(runs) {
1088
- const block = TextBlock.create({ styleId: "" });
1407
+ const block = TextBlock.create();
1089
1408
  for (const run of runs) {
1090
1409
  block.appendRun(run);
1091
1410
  }
@@ -1097,10 +1416,18 @@ describe("produceTextBlockGeometry", () => {
1097
1416
  const layout = doLayout(block);
1098
1417
  return produceTextBlockGeometry(layout, annotation.computeTransform(layout.range)).entries;
1099
1418
  }
1419
+ function makeListGeometry(children) {
1420
+ const textBlock = TextBlock.create();
1421
+ const p1 = textBlock.appendParagraph();
1422
+ p1.children.push(List.create({ children }));
1423
+ const annotation = TextAnnotation.fromJSON({ textBlock: textBlock.toJSON() });
1424
+ const layout = doLayout(textBlock);
1425
+ return produceTextBlockGeometry(layout, annotation.computeTransform(layout.range)).entries;
1426
+ }
1100
1427
  it("produces an empty array for an empty text block", () => {
1101
1428
  expect(makeGeometry([])).to.deep.equal([]);
1102
1429
  });
1103
- it("produces an empty array for a block consisting only of line breaks", () => {
1430
+ it("produces an empty array for a block consisting of line breaks", () => {
1104
1431
  expect(makeGeometry([makeBreak(), makeBreak(), makeBreak()])).to.deep.equal([]);
1105
1432
  });
1106
1433
  it("produces one appearance entry if all runs use subcategory color", () => {
@@ -1153,14 +1480,121 @@ describe("produceTextBlockGeometry", () => {
1153
1480
  "text",
1154
1481
  ]);
1155
1482
  });
1483
+ it("produces entries for list markers", () => {
1484
+ /* Final TextBlock should look like:
1485
+ 1. Oranges // Oranges -> default "subcategory" text
1486
+ 2. Apples // Apples -> Switch to red text
1487
+ • Red
1488
+ • Green // Green -> Switch to green text, not including the bullet.
1489
+ i. Granny Smith
1490
+ ii. Rhode Island Greening
1491
+ • Yellow // Yellow -> Back to red text
1492
+
1493
+ We have:
1494
+ 7 lines each containing one TextString for the list marker and one for the text,
1495
+ 4 appearance overrides
1496
+ */
1497
+ const listChildren = [
1498
+ {
1499
+ children: [
1500
+ {
1501
+ type: "text",
1502
+ content: "Oranges",
1503
+ }
1504
+ ]
1505
+ },
1506
+ {
1507
+ children: [
1508
+ {
1509
+ type: "text",
1510
+ content: "Apples",
1511
+ },
1512
+ {
1513
+ type: "list",
1514
+ styleOverrides: { listMarker: { enumerator: ListMarkerEnumerator.Bullet }, color: ColorDef.red.tbgr },
1515
+ children: [
1516
+ {
1517
+ children: [
1518
+ {
1519
+ type: "text",
1520
+ content: "Red",
1521
+ }
1522
+ ]
1523
+ },
1524
+ {
1525
+ styleOverrides: { color: ColorDef.green.tbgr },
1526
+ children: [
1527
+ {
1528
+ type: "text",
1529
+ content: "Green",
1530
+ },
1531
+ {
1532
+ type: "list",
1533
+ styleOverrides: { listMarker: { enumerator: ListMarkerEnumerator.RomanNumeral, case: "lower", terminator: "period" } },
1534
+ children: [
1535
+ {
1536
+ children: [
1537
+ {
1538
+ type: "text",
1539
+ content: "Granny Smith",
1540
+ }
1541
+ ]
1542
+ },
1543
+ {
1544
+ children: [
1545
+ {
1546
+ type: "text",
1547
+ content: "Rhode Island Greening",
1548
+ }
1549
+ ]
1550
+ }
1551
+ ]
1552
+ }
1553
+ ]
1554
+ },
1555
+ {
1556
+ children: [
1557
+ {
1558
+ type: "text",
1559
+ content: "Yellow",
1560
+ }
1561
+ ]
1562
+ }
1563
+ ]
1564
+ }
1565
+ ]
1566
+ }
1567
+ ];
1568
+ const entries = makeListGeometry(listChildren);
1569
+ expect(entries.length).to.equal(14 + 4); // 14 text strings + 4 appearance entry
1570
+ expect(entries[0].color).to.equal("subcategory");
1571
+ expect(entries[1].text?.text).to.equal("1.");
1572
+ expect(entries[2].text?.text).to.equal("Oranges");
1573
+ expect(entries[3].text?.text).to.equal("2.");
1574
+ expect(entries[4].text?.text).to.equal("Apples");
1575
+ expect(entries[5].color).to.equal(ColorDef.red.tbgr);
1576
+ expect(entries[6].text?.text).to.equal("•");
1577
+ expect(entries[7].text?.text).to.equal("Red");
1578
+ expect(entries[8].text?.text).to.equal("•");
1579
+ expect(entries[9].color).to.equal(ColorDef.green.tbgr);
1580
+ expect(entries[10].text?.text).to.equal("Green");
1581
+ expect(entries[11].text?.text).to.equal("i.");
1582
+ expect(entries[12].text?.text).to.equal("Granny Smith");
1583
+ expect(entries[13].text?.text).to.equal("ii.");
1584
+ expect(entries[14].text?.text).to.equal("Rhode Island Greening");
1585
+ expect(entries[15].color).to.equal(ColorDef.red.tbgr);
1586
+ expect(entries[16].text?.text).to.equal("•");
1587
+ expect(entries[17].text?.text).to.equal("Yellow");
1588
+ });
1156
1589
  it("offsets geometry entries by margins", () => {
1157
1590
  function makeGeometryWithMargins(anchor, margins) {
1158
1591
  const runs = [makeText()];
1159
1592
  const block = makeTextBlock(runs);
1160
- block.margins = margins;
1161
1593
  const annotation = TextAnnotation.fromJSON({ textBlock: block.toJSON() });
1162
1594
  annotation.anchor = anchor;
1163
- const layout = doLayout(block);
1595
+ const layout = doLayout(block, {
1596
+ findTextStyle: () => TextStyleSettings.fromJSON({ margins: { ...margins } }),
1597
+ });
1164
1598
  const geom = produceTextBlockGeometry(layout, annotation.computeTransform(layout.range)).entries;
1165
1599
  return geom[1].text;
1166
1600
  }
@@ -1195,5 +1629,5 @@ describe("produceTextBlockGeometry", () => {
1195
1629
  });
1196
1630
  });
1197
1631
  // Ignoring the text strings from the spell checker
1198
- // cspell:ignore jklmnop vwxyz defg hijk ghij klmno pqrstu Tanuki aabb eeff nggg amet adipiscing elit Phasellus pretium malesuada venenatis eleifend Donec sapien Nullam commodo accumsan lacinia metus enim pharetra lacus facilisis Duis suscipit quis feugiat fermentum ut augue Mauris iaculis odio rhoncus lorem viverra turpis elementum posuere Consolas अनुच्छेद cdefg cdefgh cdefghi
1632
+ // cspell:ignore jklmnop vwxyz defg hijk ghij klmno pqrstu Tanuki aabb eeff nggg amet adipiscing elit Phasellus pretium malesuada venenatis eleifend Donec sapien Nullam commodo accumsan lacinia metus enim pharetra lacus facilisis Duis suscipit quis feugiat fermentum ut augue Mauris iaculis odio rhoncus lorem viverra turpis elementum posuere Consolas अनुच्छेद cdefg cdefgh cdefghi eiusmod tempor incididunt ut labore et dolore magna aliqua sed defghi
1199
1633
  //# sourceMappingURL=TextBlock.test.js.map