@jwilleke/ngdpbase-types 0.0.0 → 5.18.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 (302) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -2
  3. package/lib/packages/ngdpbase-types/index.d.ts +32 -0
  4. package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
  5. package/lib/packages/ngdpbase-types/testing.js +53 -0
  6. package/lib/src/cache/CacheDependencies.d.ts +50 -0
  7. package/lib/src/cache/CacheDependencies.js +50 -0
  8. package/lib/src/cache/ICacheAdapter.d.ts +86 -0
  9. package/lib/src/cache/RegionCache.d.ts +171 -0
  10. package/lib/src/context/ActorContext.d.ts +48 -0
  11. package/lib/src/context/ActorContext.js +33 -0
  12. package/lib/src/context/ApiContext.d.ts +194 -0
  13. package/lib/src/context/ApiContext.js +273 -0
  14. package/lib/src/context/BaseContext.d.ts +110 -0
  15. package/lib/src/context/BaseContext.js +143 -0
  16. package/lib/src/context/JobContext.d.ts +153 -0
  17. package/lib/src/context/JobContext.js +144 -0
  18. package/lib/src/context/WikiContext.d.ts +404 -0
  19. package/lib/src/context/bootActions.d.ts +64 -0
  20. package/lib/src/context/bootActions.js +111 -0
  21. package/lib/src/converters/HtmlConverter.d.ts +70 -0
  22. package/lib/src/converters/IContentConverter.d.ts +94 -0
  23. package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
  24. package/lib/src/converters/conversionWarning.d.ts +15 -0
  25. package/lib/src/converters/ncm/bridge.d.ts +22 -0
  26. package/lib/src/converters/ncm/existing.d.ts +23 -0
  27. package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
  28. package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
  29. package/lib/src/converters/ncm/fix/index.d.ts +36 -0
  30. package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
  31. package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
  32. package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
  33. package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
  34. package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
  35. package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
  36. package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
  37. package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
  38. package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
  39. package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
  40. package/lib/src/converters/ncm/fix/types.d.ts +33 -0
  41. package/lib/src/converters/ncm/footnotes.d.ts +39 -0
  42. package/lib/src/converters/ncm/images.d.ts +49 -0
  43. package/lib/src/converters/ncm/index.d.ts +20 -0
  44. package/lib/src/converters/ncm/links.d.ts +21 -0
  45. package/lib/src/converters/ncm/normalize.d.ts +39 -0
  46. package/lib/src/converters/ncm/placeholder.d.ts +25 -0
  47. package/lib/src/converters/ncm/tables.d.ts +36 -0
  48. package/lib/src/converters/ncm/types.d.ts +42 -0
  49. package/lib/src/http/egressPolicy.d.ts +52 -0
  50. package/lib/src/http/guardedFetch.d.ts +89 -0
  51. package/lib/src/http/guardedFetch.js +113 -0
  52. package/lib/src/http/guardedLookup.d.ts +48 -0
  53. package/lib/src/http/guardedLookup.js +73 -0
  54. package/lib/src/http/ssrf.d.ts +83 -0
  55. package/lib/src/http/ssrf.js +311 -0
  56. package/lib/src/mail/MailProvider.d.ts +36 -0
  57. package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
  58. package/lib/src/managers/AddonsManager.d.ts +691 -0
  59. package/lib/src/managers/AgentTokenManager.d.ts +269 -0
  60. package/lib/src/managers/AssetManager.d.ts +116 -0
  61. package/lib/src/managers/AttachmentManager.d.ts +1032 -0
  62. package/lib/src/managers/AuthManager.d.ts +1257 -0
  63. package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
  64. package/lib/src/managers/BaseManager.d.ts +391 -0
  65. package/lib/src/managers/BaseManager.js +415 -0
  66. package/lib/src/managers/CacheManager.d.ts +159 -0
  67. package/lib/src/managers/CatalogManager.d.ts +235 -0
  68. package/lib/src/managers/CommentManager.d.ts +75 -0
  69. package/lib/src/managers/ConfigurationManager.d.ts +747 -0
  70. package/lib/src/managers/DatabaseManager.d.ts +89 -0
  71. package/lib/src/managers/DatabaseManager.js +236 -0
  72. package/lib/src/managers/EmailManager.d.ts +47 -0
  73. package/lib/src/managers/ExportManager.d.ts +129 -0
  74. package/lib/src/managers/ExportManager.js +420 -0
  75. package/lib/src/managers/FootnoteManager.d.ts +118 -0
  76. package/lib/src/managers/MediaManager.d.ts +279 -0
  77. package/lib/src/managers/MetricsManager.d.ts +89 -0
  78. package/lib/src/managers/NotificationManager.d.ts +165 -0
  79. package/lib/src/managers/OidcManager.d.ts +210 -0
  80. package/lib/src/managers/OrganizationManager.d.ts +107 -0
  81. package/lib/src/managers/PageManager.d.ts +1645 -0
  82. package/lib/src/managers/PersonManager.d.ts +48 -0
  83. package/lib/src/managers/PluginManager.d.ts +179 -0
  84. package/lib/src/managers/PluginManager.js +393 -0
  85. package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
  86. package/lib/src/managers/RenderingManager.d.ts +358 -0
  87. package/lib/src/managers/RoleManager.d.ts +134 -0
  88. package/lib/src/managers/SearchManager.d.ts +402 -0
  89. package/lib/src/managers/ShareManager.d.ts +251 -0
  90. package/lib/src/managers/TemplateManager.d.ts +176 -0
  91. package/lib/src/managers/ThemeManager.d.ts +56 -0
  92. package/lib/src/managers/UserManager.d.ts +480 -0
  93. package/lib/src/managers/ValidationManager.d.ts +426 -0
  94. package/lib/src/managers/VariableManager.d.ts +145 -0
  95. package/lib/src/middleware/csrf.d.ts +3 -0
  96. package/lib/src/parsers/LinkParser.d.ts +457 -0
  97. package/lib/src/parsers/MarkupParser.d.ts +769 -0
  98. package/lib/src/parsers/context/ParseContext.d.ts +314 -0
  99. package/lib/src/parsers/data/emoji-map.d.ts +18 -0
  100. package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
  101. package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
  102. package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
  103. package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
  104. package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
  105. package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
  106. package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
  107. package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
  108. package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
  109. package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
  110. package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
  111. package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
  112. package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
  113. package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
  114. package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
  115. package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
  116. package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
  117. package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
  118. package/lib/src/plugins/types.d.ts +79 -0
  119. package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
  120. package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
  121. package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
  122. package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
  123. package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
  124. package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
  125. package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
  126. package/lib/src/providers/BaseDatabaseProvider.js +12 -0
  127. package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
  128. package/lib/src/providers/BaseLoggingProvider.js +37 -0
  129. package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
  130. package/lib/src/providers/BasePageProvider.d.ts +337 -0
  131. package/lib/src/providers/BaseProvider.d.ts +98 -0
  132. package/lib/src/providers/BaseProvider.js +74 -0
  133. package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
  134. package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
  135. package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
  136. package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
  137. package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
  138. package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
  139. package/lib/src/providers/FileLoggingProvider.js +120 -0
  140. package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
  141. package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
  142. package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
  143. package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
  144. package/lib/src/providers/NullCacheProvider.d.ts +72 -0
  145. package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
  146. package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
  147. package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
  148. package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
  149. package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
  150. package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
  151. package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
  152. package/lib/src/providers/databaseMigrations.d.ts +8 -0
  153. package/lib/src/providers/databaseMigrations.js +47 -0
  154. package/lib/src/providers/jobState.d.ts +99 -0
  155. package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
  156. package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
  157. package/lib/src/providers/sqliteLocation.d.ts +17 -0
  158. package/lib/src/providers/sqliteLocation.js +55 -0
  159. package/lib/src/providers/sqliteMigrations.d.ts +48 -0
  160. package/lib/src/providers/sqliteMigrations.js +72 -0
  161. package/lib/src/rendering/githubAlerts.d.ts +22 -0
  162. package/lib/src/rendering/htmlPolicy.d.ts +76 -0
  163. package/lib/src/rendering/markdownConverter.d.ts +73 -0
  164. package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
  165. package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
  166. package/lib/src/security/pageActions.d.ts +40 -0
  167. package/lib/src/security/permissions.generated.d.ts +78 -0
  168. package/lib/src/types/Asset.d.ts +414 -0
  169. package/lib/src/types/Catalog.d.ts +61 -0
  170. package/lib/src/types/Comment.d.ts +11 -0
  171. package/lib/src/types/Config.d.ts +388 -0
  172. package/lib/src/types/Organization.d.ts +78 -0
  173. package/lib/src/types/OrganizationProvider.d.ts +38 -0
  174. package/lib/src/types/Page.d.ts +220 -0
  175. package/lib/src/types/Person.d.ts +56 -0
  176. package/lib/src/types/PersonProvider.d.ts +25 -0
  177. package/lib/src/types/Policy.d.ts +139 -0
  178. package/lib/src/types/Policy.js +17 -0
  179. package/lib/src/types/Provider.d.ts +810 -0
  180. package/lib/src/types/Role.d.ts +84 -0
  181. package/lib/src/types/RoleProvider.d.ts +35 -0
  182. package/lib/src/types/Schema.d.ts +425 -0
  183. package/lib/src/types/Share.d.ts +172 -0
  184. package/lib/src/types/Share.js +81 -0
  185. package/lib/src/types/User.d.ts +304 -0
  186. package/lib/src/types/Version.d.ts +189 -0
  187. package/lib/src/types/WikiEngine.d.ts +128 -0
  188. package/lib/src/types/express.d.ts +120 -0
  189. package/lib/src/types/express.js +1 -0
  190. package/lib/src/types/guards.d.ts +78 -0
  191. package/lib/src/types/heic-decode.d.ts +16 -0
  192. package/lib/src/types/index.d.ts +19 -0
  193. package/lib/src/types/linkedom.d.ts +77 -0
  194. package/lib/src/types/markdown-it-plugins.d.ts +21 -0
  195. package/lib/src/utils/DeltaStorage.d.ts +118 -0
  196. package/lib/src/utils/LocaleUtils.d.ts +105 -0
  197. package/lib/src/utils/LocaleUtils.js +294 -0
  198. package/lib/src/utils/PageNameMatcher.d.ts +98 -0
  199. package/lib/src/utils/PathPreflight.d.ts +38 -0
  200. package/lib/src/utils/PathPreflight.js +50 -0
  201. package/lib/src/utils/SectionUtils.d.ts +40 -0
  202. package/lib/src/utils/addonConfigLayer.d.ts +144 -0
  203. package/lib/src/utils/addonConfigLayer.js +382 -0
  204. package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
  205. package/lib/src/utils/addonDatabaseRules.js +57 -0
  206. package/lib/src/utils/addonHost.d.ts +51 -0
  207. package/lib/src/utils/addonHost.js +72 -0
  208. package/lib/src/utils/addonInstaller.d.ts +109 -0
  209. package/lib/src/utils/addonLock.d.ts +37 -0
  210. package/lib/src/utils/addonLock.js +48 -0
  211. package/lib/src/utils/addonPageSync.d.ts +45 -0
  212. package/lib/src/utils/addonProvenance.d.ts +48 -0
  213. package/lib/src/utils/addonTarball.d.ts +41 -0
  214. package/lib/src/utils/addonsPathResolver.d.ts +76 -0
  215. package/lib/src/utils/addonsPathResolver.js +129 -0
  216. package/lib/src/utils/assetMetadataTags.d.ts +66 -0
  217. package/lib/src/utils/atomicWrite.d.ts +28 -0
  218. package/lib/src/utils/auditConfigChange.d.ts +57 -0
  219. package/lib/src/utils/auditEventNames.d.ts +50 -0
  220. package/lib/src/utils/auditEventNames.generated.d.ts +163 -0
  221. package/lib/src/utils/auditEventNames.generated.js +168 -0
  222. package/lib/src/utils/auditEventNames.js +49 -0
  223. package/lib/src/utils/auditEvents.d.ts +265 -0
  224. package/lib/src/utils/auditEvents.js +309 -0
  225. package/lib/src/utils/auditRegistry.d.ts +102 -0
  226. package/lib/src/utils/auditRegistry.js +168 -0
  227. package/lib/src/utils/bip39English.d.ts +2 -0
  228. package/lib/src/utils/configEnvKeys.d.ts +68 -0
  229. package/lib/src/utils/configFiles.d.ts +74 -0
  230. package/lib/src/utils/configFiles.js +150 -0
  231. package/lib/src/utils/delegation.d.ts +48 -0
  232. package/lib/src/utils/deriveUsername.d.ts +21 -0
  233. package/lib/src/utils/explainMediaPath.d.ts +123 -0
  234. package/lib/src/utils/formerTitles.d.ts +69 -0
  235. package/lib/src/utils/frontmatterAccess.d.ts +54 -0
  236. package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
  237. package/lib/src/utils/imageTransform.d.ts +52 -0
  238. package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
  239. package/lib/src/utils/jobSlots.d.ts +43 -0
  240. package/lib/src/utils/keywordNormalizer.d.ts +127 -0
  241. package/lib/src/utils/logger.d.ts +70 -0
  242. package/lib/src/utils/logger.js +106 -0
  243. package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
  244. package/lib/src/utils/managerUtils.d.ts +40 -0
  245. package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
  246. package/lib/src/utils/orgFilename.d.ts +22 -0
  247. package/lib/src/utils/pageFeature.d.ts +27 -0
  248. package/lib/src/utils/pageFrontmatter.d.ts +21 -0
  249. package/lib/src/utils/pageNotes.d.ts +150 -0
  250. package/lib/src/utils/pageTitleRule.d.ts +37 -0
  251. package/lib/src/utils/pageToArticle.d.ts +59 -0
  252. package/lib/src/utils/pageUrl.d.ts +18 -0
  253. package/lib/src/utils/passwordChange.d.ts +12 -0
  254. package/lib/src/utils/passwordHash.d.ts +60 -0
  255. package/lib/src/utils/permissionCatalog.d.ts +52 -0
  256. package/lib/src/utils/pluginFormatters.d.ts +452 -0
  257. package/lib/src/utils/pluginFormatters.js +714 -0
  258. package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
  259. package/lib/src/utils/privateStoreAccess.d.ts +57 -0
  260. package/lib/src/utils/privateStoreAccess.js +65 -0
  261. package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
  262. package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
  263. package/lib/src/utils/privateStoreDoor.d.ts +181 -0
  264. package/lib/src/utils/privateStoreExport.d.ts +72 -0
  265. package/lib/src/utils/privateStoreFiles.d.ts +120 -0
  266. package/lib/src/utils/privateStoreMeta.d.ts +64 -0
  267. package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
  268. package/lib/src/utils/privateStorePath.d.ts +259 -0
  269. package/lib/src/utils/privateStorePath.js +436 -0
  270. package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
  271. package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
  272. package/lib/src/utils/proxyClaim.d.ts +59 -0
  273. package/lib/src/utils/proxyClaim.js +30 -0
  274. package/lib/src/utils/redactPrivateNames.d.ts +21 -0
  275. package/lib/src/utils/redactPrivateNames.js +89 -0
  276. package/lib/src/utils/redactSecrets.d.ts +58 -0
  277. package/lib/src/utils/redactSecrets.js +171 -0
  278. package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
  279. package/lib/src/utils/roleGrants.d.ts +35 -0
  280. package/lib/src/utils/safeRedirect.d.ts +32 -0
  281. package/lib/src/utils/schedule.d.ts +54 -0
  282. package/lib/src/utils/secretFileMode.d.ts +17 -0
  283. package/lib/src/utils/seededShippedPages.d.ts +45 -0
  284. package/lib/src/utils/sensitiveValues.d.ts +59 -0
  285. package/lib/src/utils/sensitiveValues.js +106 -0
  286. package/lib/src/utils/sessionEnd.d.ts +12 -0
  287. package/lib/src/utils/sessionGeneration.d.ts +24 -0
  288. package/lib/src/utils/sessionIdle.d.ts +41 -0
  289. package/lib/src/utils/sessionLimits.d.ts +68 -0
  290. package/lib/src/utils/shareLockbox.d.ts +64 -0
  291. package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
  292. package/lib/src/utils/sniffMime.d.ts +21 -0
  293. package/lib/src/utils/storeSearchIndex.d.ts +75 -0
  294. package/lib/src/utils/subjectMayDo.d.ts +21 -0
  295. package/lib/src/utils/systemCategoryRules.d.ts +30 -0
  296. package/lib/src/utils/systemCategoryRules.js +41 -0
  297. package/lib/src/utils/userCreateError.d.ts +62 -0
  298. package/lib/src/utils/username.d.ts +53 -0
  299. package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
  300. package/lib/src/utils/version.d.ts +84 -0
  301. package/lib/src/utils/videoFrame.d.ts +21 -0
  302. package/package.json +54 -3
@@ -0,0 +1,420 @@
1
+ import BaseManager from './BaseManager.js';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import LocaleUtils from '../utils/LocaleUtils.js';
5
+ import logger from '../utils/logger.js';
6
+ /**
7
+ * ExportManager - Handles page exports to multiple formats
8
+ *
9
+ * Similar to JSPWiki's export functionality, provides page export capabilities
10
+ * to HTML, PDF, markdown, and other formats.
11
+ *
12
+ * @class ExportManager
13
+ * @extends BaseManager
14
+ *
15
+ * @property {string} exportDirectory - Directory for exported files
16
+ *
17
+ * @see {@link BaseManager} for base functionality
18
+ *
19
+ * @example
20
+ * const exportManager = engine.getManager('ExportManager');
21
+ * const html = await exportManager.exportPageToHtml('Main');
22
+ */
23
+ /** A text cell starting with one of these runs as a spreadsheet formula. */
24
+ const CSV_FORMULA_START = /^[=+\-@\t\r]/;
25
+ class ExportManager extends BaseManager {
26
+ exportDirectory;
27
+ /**
28
+ * Creates a new ExportManager instance
29
+ *
30
+ * @constructor
31
+ * @param {any} engine - The wiki engine instance
32
+ */
33
+ constructor(engine) {
34
+ super(engine);
35
+ this.exportDirectory = './exports';
36
+ }
37
+ /**
38
+ * One field of the one CSV writer for every export (RFC 4180): quoted when
39
+ * it holds a comma, quote or line break.
40
+ *
41
+ * A cell that starts with `=`, `+`, `-`, `@`, a tab or a carriage return is
42
+ * run as a formula by Excel, LibreOffice and Google Sheets ("CSV injection",
43
+ * OWASP), so a text cell starting with one gets a leading `'`. Numbers are
44
+ * written as numbers: a negative amount stays `-12550`.
45
+ *
46
+ * @param value - The cell value
47
+ * @returns The field, ready to join with commas
48
+ */
49
+ csvCell(value) {
50
+ if (value === null || value === undefined)
51
+ return '';
52
+ if (typeof value === 'number' || typeof value === 'bigint' || typeof value === 'boolean')
53
+ return String(value);
54
+ let text = typeof value === 'string' ? value : JSON.stringify(value);
55
+ if (CSV_FORMULA_START.test(text))
56
+ text = `'${text}`;
57
+ return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
58
+ }
59
+ /**
60
+ * A header row and data rows as one CSV document, each line ending CRLF.
61
+ * Every CSV export (the audit log, add-ons) goes through here.
62
+ *
63
+ * @param headers - The header row
64
+ * @param rows - The data rows
65
+ * @returns The CSV document
66
+ */
67
+ toCsv(headers, rows) {
68
+ return [headers, ...rows].map((row) => row.map((cell) => this.csvCell(cell)).join(',')).join('\r\n') + '\r\n';
69
+ }
70
+ /**
71
+ * Initialize the ExportManager
72
+ *
73
+ * @async
74
+ * @param {ExportConfig} [config={}] - Configuration object
75
+ * @param {string} [config.exportDirectory] - Export directory path
76
+ * @returns {Promise<void>}
77
+ */
78
+ async initialize(config = {}) {
79
+ await super.initialize(config);
80
+ // #1687: exports are files people generate — runtime data, so they live in
81
+ // the instance data folder, never in the checkout (root-owned in the image).
82
+ this.exportDirectory = config.exportDirectory
83
+ || this.engine.getManager('ConfigurationManager')?.getResolvedDataPath('ngdpbase.directories.exports', '${FAST_STORAGE}/exports')
84
+ || './exports';
85
+ const preflight = this.preflightConfiguredPath('exportDirectory', this.exportDirectory);
86
+ if (!preflight.ok) {
87
+ this.exportDirectory = '';
88
+ logger.info('ExportManager initialized (degraded — exports disabled)');
89
+ return;
90
+ }
91
+ // Create exports directory
92
+ await fs.mkdir(this.exportDirectory, { recursive: true });
93
+ logger.info('ExportManager initialized');
94
+ }
95
+ /**
96
+ * Export a single page to HTML
97
+ * @param {string} pageName - Page name to export
98
+ * @param {ExportUser|null} user - User object for locale-aware formatting
99
+ * @returns {Promise<string>} HTML content
100
+ */
101
+ async exportPageToHtml(pageName, ctx, user = null) {
102
+ const pageManager = this.engine.getManager('PageManager');
103
+ const renderingManager = this.engine.getManager('RenderingManager');
104
+ if (!pageManager || !renderingManager) {
105
+ throw new Error('Required managers not available');
106
+ }
107
+ const page = (await pageManager.getPage(pageName, ctx));
108
+ if (!page) {
109
+ throw new Error(`Page '${pageName}' not found`);
110
+ }
111
+ // Render the page content (without user context for exports)
112
+ const renderedContent = await renderingManager.renderMarkdown(page.content, pageName, null);
113
+ // Create full HTML document
114
+ const html = `<!DOCTYPE html>
115
+ <html lang="en">
116
+ <head>
117
+ <meta charset="UTF-8">
118
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
119
+ <title>${pageName} - ngdpbase Export</title>
120
+ <style>
121
+ body {
122
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
123
+ max-width: 800px;
124
+ margin: 0 auto;
125
+ padding: 2rem;
126
+ line-height: 1.6;
127
+ }
128
+ h1, h2, h3, h4, h5, h6 {
129
+ color: #333;
130
+ margin-top: 2rem;
131
+ margin-bottom: 1rem;
132
+ }
133
+ pre {
134
+ background: #f8f9fa;
135
+ padding: 1rem;
136
+ border-radius: 4px;
137
+ overflow-x: auto;
138
+ }
139
+ code {
140
+ background: #f8f9fa;
141
+ padding: 0.2rem 0.4rem;
142
+ border-radius: 3px;
143
+ font-size: 0.9em;
144
+ }
145
+ blockquote {
146
+ border-left: 4px solid #ddd;
147
+ padding-left: 1rem;
148
+ margin-left: 0;
149
+ color: #666;
150
+ }
151
+ table {
152
+ width: 100%;
153
+ border-collapse: collapse;
154
+ margin: 1rem 0;
155
+ }
156
+ th, td {
157
+ border: 1px solid #ddd;
158
+ padding: 0.75rem;
159
+ text-align: left;
160
+ }
161
+ th {
162
+ background: #f8f9fa;
163
+ font-weight: 600;
164
+ }
165
+ .export-meta {
166
+ border-top: 1px solid #eee;
167
+ margin-top: 3rem;
168
+ padding-top: 1rem;
169
+ color: #666;
170
+ font-size: 0.9em;
171
+ }
172
+ </style>
173
+ </head>
174
+ <body>
175
+ <h1>${pageName}</h1>
176
+ ${renderedContent}
177
+
178
+ <div class="export-meta">
179
+ <p>Exported from ngdpbase on ${this.getFormattedTimestamp(user)}</p>
180
+ <p>Last modified: ${page.lastModified || 'Unknown'}</p>
181
+ ${page['system-category'] ? `<p>System Category: ${page['system-category']}</p>` : ''}
182
+ ${page['user-keywords'] && page['user-keywords'].length > 0 ? `<p>User Keywords: ${page['user-keywords'].join(', ')}</p>` : ''}
183
+ </div>
184
+ </body>
185
+ </html>`;
186
+ return html;
187
+ }
188
+ /**
189
+ * Export multiple pages to a single HTML file
190
+ * @param {string[]} pageNames - Array of page names
191
+ * @param {ExportUser|null} user - User object for locale-aware formatting
192
+ * @returns {Promise<string>} Combined HTML content
193
+ */
194
+ async exportPagesToHtml(pageNames, ctx, user = null) {
195
+ const pageManager = this.engine.getManager('PageManager');
196
+ const renderingManager = this.engine.getManager('RenderingManager');
197
+ if (!pageManager || !renderingManager) {
198
+ throw new Error('Required managers not available');
199
+ }
200
+ let combinedContent = '';
201
+ const validPages = [];
202
+ for (const pageName of pageNames) {
203
+ const page = (await pageManager.getPage(pageName, ctx));
204
+ if (page) {
205
+ const renderedContent = await renderingManager.renderMarkdown(page.content, pageName, null);
206
+ combinedContent += `
207
+ <div class="page-section" id="page-${pageName.replace(/[^a-zA-Z0-9]/g, '-')}">
208
+ <h1>${pageName}</h1>
209
+ ${renderedContent}
210
+ <hr style="margin: 3rem 0; border: none; border-top: 1px solid #eee;">
211
+ </div>
212
+ `;
213
+ validPages.push({ name: pageName, ...page });
214
+ }
215
+ }
216
+ // Create table of contents
217
+ const toc = validPages.map((page) => `<li><a href="#page-${page.name.replace(/[^a-zA-Z0-9]/g, '-')}">${page.name}</a></li>`).join('\n');
218
+ const html = `<!DOCTYPE html>
219
+ <html lang="en">
220
+ <head>
221
+ <meta charset="UTF-8">
222
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
223
+ <title>ngdpbase Export - ${validPages.length} Pages</title>
224
+ <style>
225
+ body {
226
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
227
+ max-width: 900px;
228
+ margin: 0 auto;
229
+ padding: 2rem;
230
+ line-height: 1.6;
231
+ }
232
+ .toc {
233
+ background: #f8f9fa;
234
+ padding: 2rem;
235
+ border-radius: 8px;
236
+ margin-bottom: 3rem;
237
+ }
238
+ .toc h2 {
239
+ margin-top: 0;
240
+ }
241
+ .toc ul {
242
+ columns: 2;
243
+ column-gap: 2rem;
244
+ }
245
+ .page-section {
246
+ margin-bottom: 4rem;
247
+ }
248
+ h1, h2, h3, h4, h5, h6 {
249
+ color: #333;
250
+ margin-top: 2rem;
251
+ margin-bottom: 1rem;
252
+ }
253
+ pre {
254
+ background: #f8f9fa;
255
+ padding: 1rem;
256
+ border-radius: 4px;
257
+ overflow-x: auto;
258
+ }
259
+ code {
260
+ background: #f8f9fa;
261
+ padding: 0.2rem 0.4rem;
262
+ border-radius: 3px;
263
+ font-size: 0.9em;
264
+ }
265
+ blockquote {
266
+ border-left: 4px solid #ddd;
267
+ padding-left: 1rem;
268
+ margin-left: 0;
269
+ color: #666;
270
+ }
271
+ table {
272
+ width: 100%;
273
+ border-collapse: collapse;
274
+ margin: 1rem 0;
275
+ }
276
+ th, td {
277
+ border: 1px solid #ddd;
278
+ padding: 0.75rem;
279
+ text-align: left;
280
+ }
281
+ th {
282
+ background: #f8f9fa;
283
+ font-weight: 600;
284
+ }
285
+ .export-meta {
286
+ border-top: 1px solid #eee;
287
+ margin-top: 3rem;
288
+ padding-top: 1rem;
289
+ color: #666;
290
+ font-size: 0.9em;
291
+ }
292
+ @media print {
293
+ .page-section {
294
+ break-inside: avoid;
295
+ }
296
+ }
297
+ </style>
298
+ </head>
299
+ <body>
300
+ <div class="toc">
301
+ <h2>Table of Contents</h2>
302
+ <ul>
303
+ ${toc}
304
+ </ul>
305
+ <p><strong>${validPages.length}</strong> pages exported on ${this.getFormattedTimestamp(user)}</p>
306
+ </div>
307
+
308
+ ${combinedContent}
309
+
310
+ <div class="export-meta">
311
+ <p>Exported from ngdpbase on ${this.getFormattedTimestamp(user)}</p>
312
+ <p>Total pages: ${validPages.length}</p>
313
+ </div>
314
+ </body>
315
+ </html>`;
316
+ return html;
317
+ }
318
+ /**
319
+ * Export page(s) to markdown
320
+ * @param {string|string[]} pageNames - Single page name or array of page names
321
+ * @param {ExportUser|null} user - User object for locale-aware formatting
322
+ * @returns {Promise<string>} Markdown content
323
+ */
324
+ async exportToMarkdown(pageNames, ctx, user = null) {
325
+ const pageManager = this.engine.getManager('PageManager');
326
+ if (!pageManager) {
327
+ throw new Error('PageManager not available');
328
+ }
329
+ const names = Array.isArray(pageNames) ? pageNames : [pageNames];
330
+ let markdown = '';
331
+ if (names.length > 1) {
332
+ markdown += '# ngdpbase Export\n\n';
333
+ markdown += `*Exported on ${this.getFormattedTimestamp(user)}*\n\n`;
334
+ markdown += '## Table of Contents\n\n';
335
+ for (const pageName of names) {
336
+ markdown += `- [${pageName}](#${pageName.toLowerCase().replace(/[^a-z0-9]/g, '-')})\n`;
337
+ }
338
+ markdown += '\n---\n\n';
339
+ }
340
+ for (const pageName of names) {
341
+ const page = (await pageManager.getPage(pageName, ctx));
342
+ if (page) {
343
+ if (names.length > 1) {
344
+ markdown += `# ${pageName}\n\n`;
345
+ }
346
+ markdown += page.content;
347
+ if (names.length > 1) {
348
+ markdown += '\n\n---\n\n';
349
+ }
350
+ }
351
+ }
352
+ return markdown;
353
+ }
354
+ /**
355
+ * Save export to file
356
+ * @param {string} content - Content to save
357
+ * @param {string} filename - Filename
358
+ * @param {string} format - File format
359
+ * @returns {Promise<string>} File path
360
+ */
361
+ async saveExport(content, filename, format) {
362
+ const sanitizedFilename = filename.replace(/[^a-zA-Z0-9\-_]/g, '-');
363
+ const timestamp = new Date().toISOString().slice(0, 10);
364
+ const fullFilename = `${sanitizedFilename}_${timestamp}.${format}`;
365
+ const filePath = path.join(this.exportDirectory, fullFilename);
366
+ await fs.writeFile(filePath, content, 'utf8');
367
+ logger.info(`Exported to: ${fullFilename}`);
368
+ return filePath;
369
+ }
370
+ /**
371
+ * Get list of available exports
372
+ * @returns {Promise<ExportFileInfo[]>} List of export files
373
+ */
374
+ async getExports() {
375
+ try {
376
+ const files = await fs.readdir(this.exportDirectory);
377
+ const exports = [];
378
+ for (const file of files) {
379
+ const filePath = path.join(this.exportDirectory, file);
380
+ const stats = await fs.stat(filePath);
381
+ exports.push({
382
+ filename: file,
383
+ path: filePath,
384
+ size: stats.size,
385
+ created: stats.birthtime,
386
+ modified: stats.mtime
387
+ });
388
+ }
389
+ return exports.sort((a, b) => b.created.getTime() - a.created.getTime());
390
+ }
391
+ catch (err) {
392
+ logger.error('Error getting exports:', err);
393
+ return [];
394
+ }
395
+ }
396
+ /**
397
+ * Delete an export file
398
+ * @param {string} filename - Export filename
399
+ * @returns {Promise<void>}
400
+ */
401
+ async deleteExport(filename) {
402
+ const filePath = path.join(this.exportDirectory, filename);
403
+ await fs.unlink(filePath);
404
+ logger.info(`Deleted export: ${filename}`);
405
+ }
406
+ /**
407
+ * Get formatted timestamp using user's locale
408
+ * @param {ExportUser|null} user - User object (optional)
409
+ * @returns {string} Formatted timestamp
410
+ */
411
+ getFormattedTimestamp(user = null) {
412
+ const date = new Date();
413
+ if (user && user.preferences && user.preferences.locale) {
414
+ return LocaleUtils.formatDate(date, user.preferences.locale) + ' ' + LocaleUtils.formatTime(date, user.preferences.locale);
415
+ }
416
+ // Fallback to system default
417
+ return date.toLocaleString();
418
+ }
419
+ }
420
+ export default ExportManager;
@@ -0,0 +1,118 @@
1
+ import BaseManager from './BaseManager.js';
2
+ import type { WikiEngine } from '../types/WikiEngine.js';
3
+ import { type ActorContext } from '../context/ActorContext.js';
4
+ import { type VaultPageNotesOutside, type PageRef } from '../utils/pageNotes.js';
5
+ export interface PageFootnote {
6
+ id: string;
7
+ display: string;
8
+ url: string;
9
+ note: string;
10
+ createdBy: string;
11
+ createdAt: string;
12
+ }
13
+ export default class FootnoteManager extends BaseManager {
14
+ private storageDir;
15
+ private enabled;
16
+ /** Vault pages whose footnotes are still in the public folder (#1839), and the repair's re-check (#1842). */
17
+ private readonly outsideCheck;
18
+ constructor(engine: WikiEngine);
19
+ initialize(): Promise<void>;
20
+ isEnabled(): boolean;
21
+ /** The public folder and the vaults, as configured now (#1839). */
22
+ private roots;
23
+ /**
24
+ * Where `page`'s footnotes are (#1839): the public folder for a public page,
25
+ * the page's own vault for a vault page, read and written through that
26
+ * vault's store I/O. A locked vault, or a sealed kind's vault not yet
27
+ * opened, throws: a vault page's footnotes are never read or written in
28
+ * the clear.
29
+ */
30
+ private place;
31
+ private readMap;
32
+ private writeMap;
33
+ /**
34
+ * A page's footnotes, read as `ctx` may (#1839). Whether `ctx` may read the
35
+ * page is the caller's to decide, as for the page itself; this finds and
36
+ * opens them.
37
+ */
38
+ getFootnotes(page: PageRef, ctx: ActorContext): Promise<PageFootnote[]>;
39
+ /**
40
+ * Add a footnote on someone's behalf (#1233, security-posture P1).
41
+ *
42
+ * `ctx` is the request's subject — `wikiContext.userContext`, forwarded —
43
+ * or a JobContext for an import; never a name. `createdBy` is read from
44
+ * it, and the write is recorded as `footnote-edit` / `add`.
45
+ */
46
+ addFootnote(page: PageRef, data: {
47
+ display: string;
48
+ url: string;
49
+ note: string;
50
+ }, ctx: ActorContext): Promise<PageFootnote>;
51
+ /**
52
+ * #1125: import a footnote with an EXPLICIT id — the NCM conversion path.
53
+ *
54
+ * Unlike {@link addFootnote}, which assigns the next sequential id, this
55
+ * preserves the author's id verbatim: the body's `[^note-1]` refs resolve
56
+ * to `#footnote-note-1` in the rendered list, so renumbering would break
57
+ * every ref. Refuses to clobber an existing id (returns false) — the
58
+ * caller surfaces that as a warning and leaves the body definition alone.
59
+ */
60
+ importFootnote(page: PageRef, id: string, data: {
61
+ display: string;
62
+ url: string;
63
+ note: string;
64
+ }, ctx: ActorContext): Promise<boolean>;
65
+ /** The write behind `importFootnote` and `transferFromContent`; the callers record it, once each. */
66
+ private putImported;
67
+ /**
68
+ * #1125/#1126: transfer `[^id]: text` definitions from a body into this
69
+ * sidecar, returning the rewritten body. THE one implementation — the
70
+ * convert route, agent ingest, and ImportManager all delegate here, so the
71
+ * funnel cannot drift per-path. dryRun reports and rewrites without
72
+ * writing. A colliding id keeps its body definition and warns.
73
+ */
74
+ transferFromContent(page: PageRef, content: string, ctx: ActorContext, dryRun: boolean): Promise<{
75
+ content: string;
76
+ warnings: string[];
77
+ }>;
78
+ updateFootnote(page: PageRef, id: string, data: {
79
+ display: string;
80
+ url: string;
81
+ note: string;
82
+ }, ctx: ActorContext): Promise<PageFootnote | null>;
83
+ deleteFootnote(page: PageRef, id: string, ctx: ActorContext): Promise<boolean>;
84
+ /**
85
+ * `footnote-edit`, attributed from the context (#1233). Ids only — display,
86
+ * url and note are content, and the record does not repeat content.
87
+ * on-failure: continue, the page-edit footing.
88
+ */
89
+ private recordEdit;
90
+ hasFootnotes(page: PageRef, ctx: ActorContext): Promise<boolean>;
91
+ /**
92
+ * Take a page's footnotes with it when it changes place (#1839): into a
93
+ * vault, out of one, or between two, through both sides' store I/O as its
94
+ * history goes, sealed into a sealed vault and opened coming out. The page
95
+ * door calls this after the page itself has moved; a rename in place moves
96
+ * nothing.
97
+ */
98
+ movePageFootnotes(uuid: string, fromName: string, toName: string, ctx: ActorContext): Promise<boolean>;
99
+ /** Vault pages whose footnotes the last check found in the public folder (#1839): owner, vault, page uuid. */
100
+ vaultPageNotesOutside(): VaultPageNotesOutside[];
101
+ /** Run that check again (#1842): after a repair, so the subsystem banner clears once nothing is left. */
102
+ recheckVaultPageNotesOutside(): Promise<VaultPageNotesOutside[]>;
103
+ /**
104
+ * Move vault page `uuid`'s footnotes left in the public folder into its
105
+ * vault (#1842), sealed when the vault is; merged with any the vault already
106
+ * has. Who may ask, and that `uuid` is a page of `vault`, is the caller's
107
+ * (`PageManager.repairVaultPage`) to decide.
108
+ *
109
+ * @returns how many footnotes were (or, with `dryRun`, would be) moved
110
+ */
111
+ moveOutsideFootnotesIntoVault(vault: {
112
+ owner: string;
113
+ store: string;
114
+ }, uuid: string, ctx: ActorContext, opts?: {
115
+ dryRun?: boolean;
116
+ }): Promise<number>;
117
+ shutdown(): Promise<void>;
118
+ }