obsidian-dev-utils 88.5.0 → 88.7.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 (61) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/integration-test-plugin/main.js +2250 -1908
  3. package/dist/lib/cjs/__merged.cjs +6 -1
  4. package/dist/lib/cjs/__merged.d.cts +2 -1
  5. package/dist/lib/cjs/generated-during-build.cjs +1 -1
  6. package/dist/lib/cjs/obsidian/components/component-ex.cjs +42 -4
  7. package/dist/lib/cjs/obsidian/components/component-ex.d.cts +29 -1
  8. package/dist/lib/cjs/obsidian/components/index.cjs +6 -3
  9. package/dist/lib/cjs/obsidian/components/index.d.cts +1 -0
  10. package/dist/lib/cjs/obsidian/components/syntax-highlighting-component.cjs +244 -0
  11. package/dist/lib/cjs/obsidian/components/syntax-highlighting-component.d.cts +149 -0
  12. package/dist/lib/cjs/obsidian/plugin/plugin-settings-tab.cjs +186 -11
  13. package/dist/lib/cjs/obsidian/plugin/plugin-settings-tab.d.cts +151 -4
  14. package/dist/lib/cjs/obsidian/setting-ex.cjs +13 -3
  15. package/dist/lib/cjs/obsidian/setting-ex.d.cts +14 -0
  16. package/dist/lib/cjs/script-utils/cli-utils.cjs +9 -1
  17. package/dist/lib/cjs/script-utils/cli-utils.d.cts +6 -0
  18. package/dist/lib/cjs/script-utils/env-toggle.cjs +180 -0
  19. package/dist/lib/cjs/script-utils/env-toggle.d.cts +42 -0
  20. package/dist/lib/cjs/script-utils/git.cjs +156 -0
  21. package/dist/lib/cjs/script-utils/git.d.cts +37 -0
  22. package/dist/lib/cjs/script-utils/index.cjs +7 -1
  23. package/dist/lib/cjs/script-utils/index.d.cts +2 -0
  24. package/dist/lib/cjs/script-utils/linters/cspell.cjs +11 -2
  25. package/dist/lib/cjs/script-utils/linters/cspell.d.cts +7 -0
  26. package/dist/lib/cjs/script-utils/linters/markdownlint-cli2-config.cjs +7 -4
  27. package/dist/lib/cjs/script-utils/linters/markdownlint.cjs +17 -8
  28. package/dist/lib/cjs/script-utils/nano-staged-config.cjs +7 -11
  29. package/dist/lib/cjs/script-utils/nano-staged-config.d.cts +7 -5
  30. package/dist/lib/esm/__merged.d.mts +2 -1
  31. package/dist/lib/esm/__merged.mjs +8 -2
  32. package/dist/lib/esm/generated-during-build.mjs +1 -1
  33. package/dist/lib/esm/obsidian/components/component-ex.d.mts +29 -1
  34. package/dist/lib/esm/obsidian/components/component-ex.mjs +46 -5
  35. package/dist/lib/esm/obsidian/components/index.d.mts +1 -0
  36. package/dist/lib/esm/obsidian/components/index.mjs +4 -2
  37. package/dist/lib/esm/obsidian/components/syntax-highlighting-component.d.mts +149 -0
  38. package/dist/lib/esm/obsidian/components/syntax-highlighting-component.mjs +136 -0
  39. package/dist/lib/esm/obsidian/plugin/plugin-settings-tab.d.mts +151 -4
  40. package/dist/lib/esm/obsidian/plugin/plugin-settings-tab.mjs +191 -12
  41. package/dist/lib/esm/obsidian/setting-ex.d.mts +14 -0
  42. package/dist/lib/esm/obsidian/setting-ex.mjs +11 -2
  43. package/dist/lib/esm/script-utils/cli-utils.d.mts +6 -0
  44. package/dist/lib/esm/script-utils/cli-utils.mjs +9 -1
  45. package/dist/lib/esm/script-utils/env-toggle.d.mts +42 -0
  46. package/dist/lib/esm/script-utils/env-toggle.mjs +60 -0
  47. package/dist/lib/esm/script-utils/git.d.mts +37 -0
  48. package/dist/lib/esm/script-utils/git.mjs +48 -0
  49. package/dist/lib/esm/script-utils/index.d.mts +2 -0
  50. package/dist/lib/esm/script-utils/index.mjs +5 -1
  51. package/dist/lib/esm/script-utils/linters/cspell.d.mts +7 -0
  52. package/dist/lib/esm/script-utils/linters/cspell.mjs +15 -3
  53. package/dist/lib/esm/script-utils/linters/markdownlint-cli2-config.mjs +7 -4
  54. package/dist/lib/esm/script-utils/linters/markdownlint.mjs +17 -8
  55. package/dist/lib/esm/script-utils/nano-staged-config.d.mts +7 -5
  56. package/dist/lib/esm/script-utils/nano-staged-config.mjs +10 -11
  57. package/dist/templates/dprint.json +2 -2
  58. package/obsidian/components/syntax-highlighting-component/package.json +6 -0
  59. package/package.json +7 -6
  60. package/script-utils/env-toggle/package.json +6 -0
  61. package/script-utils/git/package.json +6 -0
@@ -41,6 +41,7 @@ import * as plugin_settings_tab_component from "./plugin-settings-tab-component.
41
41
  import * as pointer_position_component from "./pointer-position-component.mjs";
42
42
  import * as registry_component from "./registry-component.mjs";
43
43
  import * as rename_delete_handler_component from "./rename-delete-handler-component.mjs";
44
+ import * as syntax_highlighting_component from "./syntax-highlighting-component.mjs";
44
45
  export {
45
46
  abort_signal_component as "abort-signal-component",
46
47
  all_windows_event_component as "all-windows-event-component",
@@ -61,6 +62,7 @@ export {
61
62
  plugin_settings_tab_component as "plugin-settings-tab-component",
62
63
  pointer_position_component as "pointer-position-component",
63
64
  registry_component as "registry-component",
64
- rename_delete_handler_component as "rename-delete-handler-component"
65
+ rename_delete_handler_component as "rename-delete-handler-component",
66
+ syntax_highlighting_component as "syntax-highlighting-component"
65
67
  };
66
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2NvbXBvbmVudHMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIFRISVMgSVMgQSBHRU5FUkFURUQvQlVORExFRCBGSUxFIEJZIEJVSUxEIFNDUklQVCAqL1xuXG5leHBvcnQgKiBhcyAnYWJvcnQtc2lnbmFsLWNvbXBvbmVudCcgZnJvbSAnLi9hYm9ydC1zaWduYWwtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdhbGwtd2luZG93cy1ldmVudC1jb21wb25lbnQnIGZyb20gJy4vYWxsLXdpbmRvd3MtZXZlbnQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdhc3luYy1lcnJvci1oYW5kbGVyLWNvbXBvbmVudCcgZnJvbSAnLi9hc3luYy1lcnJvci1oYW5kbGVyLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAnYXN5bmMtZXZlbnRzLWNvbXBvbmVudCcgZnJvbSAnLi9hc3luYy1ldmVudHMtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdjYXNlLWluc2Vuc2l0aXZlLWZpbGUtaW5kZXgtY29tcG9uZW50JyBmcm9tICcuL2Nhc2UtaW5zZW5zaXRpdmUtZmlsZS1pbmRleC1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ2NvbXBvbmVudC1leCcgZnJvbSAnLi9jb21wb25lbnQtZXgudHMnO1xuZXhwb3J0ICogYXMgJ2NvbnNvbGUtZGVidWctY29tcG9uZW50JyBmcm9tICcuL2NvbnNvbGUtZGVidWctY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdkaXNwb3NhYmxlLWNvbXBvbmVudCcgZnJvbSAnLi9kaXNwb3NhYmxlLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAnZW1iZWQtZXh0ZW5zaW9ucy1jb21wb25lbnQnIGZyb20gJy4vZW1iZWQtZXh0ZW5zaW9ucy1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ2dlbmVyYXRlLW1hcmtkb3duLWxpbmstZGVmYXVsdC1wYXJhbXMtY29tcG9uZW50JyBmcm9tICcuL2dlbmVyYXRlLW1hcmtkb3duLWxpbmstZGVmYXVsdC1wYXJhbXMtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdsYXlvdXQtcmVhZHktY29tcG9uZW50JyBmcm9tICcuL2xheW91dC1yZWFkeS1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ21lbnUtZXZlbnQtcmVnaXN0cmFyLWNvbXBvbmVudCcgZnJvbSAnLi9tZW51LWV2ZW50LXJlZ2lzdHJhci1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ21vbmtleS1hcm91bmQtY29tcG9uZW50JyBmcm9tICcuL21vbmtleS1hcm91bmQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tY29udGV4dC1jb21wb25lbnQnIGZyb20gJy4vcGx1Z2luLWNvbnRleHQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tbm90aWNlLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tbm90aWNlLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAncGx1Z2luLXNldHRpbmdzLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tc2V0dGluZ3MtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tc2V0dGluZ3MtdGFiLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tc2V0dGluZ3MtdGFiLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAncG9pbnRlci1wb3NpdGlvbi1jb21wb25lbnQnIGZyb20gJy4vcG9pbnRlci1wb3NpdGlvbi1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ3JlZ2lzdHJ5LWNvbXBvbmVudCcgZnJvbSAnLi9yZWdpc3RyeS1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ3JlbmFtZS1kZWxldGUtaGFuZGxlci1jb21wb25lbnQnIGZyb20gJy4vcmVuYW1lLWRlbGV0ZS1oYW5kbGVyLWNvbXBvbmVudC50cyc7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLFlBQVlBLDRCQUE4QjtBQUMxQyxZQUFZQyxpQ0FBbUM7QUFDL0MsWUFBWUMsbUNBQXFDO0FBQ2pELFlBQVlDLDRCQUE4QjtBQUMxQyxZQUFZQywyQ0FBNkM7QUFDekQsWUFBWUMsa0JBQW9CO0FBQ2hDLFlBQVlDLDZCQUErQjtBQUMzQyxZQUFZQywwQkFBNEI7QUFDeEMsWUFBWUMsZ0NBQWtDO0FBQzlDLFlBQVlDLHFEQUF1RDtBQUNuRSxZQUFZQyw0QkFBOEI7QUFDMUMsWUFBWUMsb0NBQXNDO0FBQ2xELFlBQVlDLDZCQUErQjtBQUMzQyxZQUFZQyw4QkFBZ0M7QUFDNUMsWUFBWUMsNkJBQStCO0FBQzNDLFlBQVlDLCtCQUFpQztBQUM3QyxZQUFZQyxtQ0FBcUM7QUFDakQsWUFBWUMsZ0NBQWtDO0FBQzlDLFlBQVlDLHdCQUEwQjtBQUN0QyxZQUFZQyxxQ0FBdUM7IiwKICAibmFtZXMiOiBbImFib3J0LXNpZ25hbC1jb21wb25lbnQiLCAiYWxsLXdpbmRvd3MtZXZlbnQtY29tcG9uZW50IiwgImFzeW5jLWVycm9yLWhhbmRsZXItY29tcG9uZW50IiwgImFzeW5jLWV2ZW50cy1jb21wb25lbnQiLCAiY2FzZS1pbnNlbnNpdGl2ZS1maWxlLWluZGV4LWNvbXBvbmVudCIsICJjb21wb25lbnQtZXgiLCAiY29uc29sZS1kZWJ1Zy1jb21wb25lbnQiLCAiZGlzcG9zYWJsZS1jb21wb25lbnQiLCAiZW1iZWQtZXh0ZW5zaW9ucy1jb21wb25lbnQiLCAiZ2VuZXJhdGUtbWFya2Rvd24tbGluay1kZWZhdWx0LXBhcmFtcy1jb21wb25lbnQiLCAibGF5b3V0LXJlYWR5LWNvbXBvbmVudCIsICJtZW51LWV2ZW50LXJlZ2lzdHJhci1jb21wb25lbnQiLCAibW9ua2V5LWFyb3VuZC1jb21wb25lbnQiLCAicGx1Z2luLWNvbnRleHQtY29tcG9uZW50IiwgInBsdWdpbi1ub3RpY2UtY29tcG9uZW50IiwgInBsdWdpbi1zZXR0aW5ncy1jb21wb25lbnQiLCAicGx1Z2luLXNldHRpbmdzLXRhYi1jb21wb25lbnQiLCAicG9pbnRlci1wb3NpdGlvbi1jb21wb25lbnQiLCAicmVnaXN0cnktY29tcG9uZW50IiwgInJlbmFtZS1kZWxldGUtaGFuZGxlci1jb21wb25lbnQiXQp9Cg==
68
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2NvbXBvbmVudHMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIFRISVMgSVMgQSBHRU5FUkFURUQvQlVORExFRCBGSUxFIEJZIEJVSUxEIFNDUklQVCAqL1xuXG5leHBvcnQgKiBhcyAnYWJvcnQtc2lnbmFsLWNvbXBvbmVudCcgZnJvbSAnLi9hYm9ydC1zaWduYWwtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdhbGwtd2luZG93cy1ldmVudC1jb21wb25lbnQnIGZyb20gJy4vYWxsLXdpbmRvd3MtZXZlbnQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdhc3luYy1lcnJvci1oYW5kbGVyLWNvbXBvbmVudCcgZnJvbSAnLi9hc3luYy1lcnJvci1oYW5kbGVyLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAnYXN5bmMtZXZlbnRzLWNvbXBvbmVudCcgZnJvbSAnLi9hc3luYy1ldmVudHMtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdjYXNlLWluc2Vuc2l0aXZlLWZpbGUtaW5kZXgtY29tcG9uZW50JyBmcm9tICcuL2Nhc2UtaW5zZW5zaXRpdmUtZmlsZS1pbmRleC1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ2NvbXBvbmVudC1leCcgZnJvbSAnLi9jb21wb25lbnQtZXgudHMnO1xuZXhwb3J0ICogYXMgJ2NvbnNvbGUtZGVidWctY29tcG9uZW50JyBmcm9tICcuL2NvbnNvbGUtZGVidWctY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdkaXNwb3NhYmxlLWNvbXBvbmVudCcgZnJvbSAnLi9kaXNwb3NhYmxlLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAnZW1iZWQtZXh0ZW5zaW9ucy1jb21wb25lbnQnIGZyb20gJy4vZW1iZWQtZXh0ZW5zaW9ucy1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ2dlbmVyYXRlLW1hcmtkb3duLWxpbmstZGVmYXVsdC1wYXJhbXMtY29tcG9uZW50JyBmcm9tICcuL2dlbmVyYXRlLW1hcmtkb3duLWxpbmstZGVmYXVsdC1wYXJhbXMtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdsYXlvdXQtcmVhZHktY29tcG9uZW50JyBmcm9tICcuL2xheW91dC1yZWFkeS1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ21lbnUtZXZlbnQtcmVnaXN0cmFyLWNvbXBvbmVudCcgZnJvbSAnLi9tZW51LWV2ZW50LXJlZ2lzdHJhci1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ21vbmtleS1hcm91bmQtY29tcG9uZW50JyBmcm9tICcuL21vbmtleS1hcm91bmQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tY29udGV4dC1jb21wb25lbnQnIGZyb20gJy4vcGx1Z2luLWNvbnRleHQtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tbm90aWNlLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tbm90aWNlLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAncGx1Z2luLXNldHRpbmdzLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tc2V0dGluZ3MtY29tcG9uZW50LnRzJztcbmV4cG9ydCAqIGFzICdwbHVnaW4tc2V0dGluZ3MtdGFiLWNvbXBvbmVudCcgZnJvbSAnLi9wbHVnaW4tc2V0dGluZ3MtdGFiLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAncG9pbnRlci1wb3NpdGlvbi1jb21wb25lbnQnIGZyb20gJy4vcG9pbnRlci1wb3NpdGlvbi1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ3JlZ2lzdHJ5LWNvbXBvbmVudCcgZnJvbSAnLi9yZWdpc3RyeS1jb21wb25lbnQudHMnO1xuZXhwb3J0ICogYXMgJ3JlbmFtZS1kZWxldGUtaGFuZGxlci1jb21wb25lbnQnIGZyb20gJy4vcmVuYW1lLWRlbGV0ZS1oYW5kbGVyLWNvbXBvbmVudC50cyc7XG5leHBvcnQgKiBhcyAnc3ludGF4LWhpZ2hsaWdodGluZy1jb21wb25lbnQnIGZyb20gJy4vc3ludGF4LWhpZ2hsaWdodGluZy1jb21wb25lbnQudHMnO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxZQUFZQSw0QkFBOEI7QUFDMUMsWUFBWUMsaUNBQW1DO0FBQy9DLFlBQVlDLG1DQUFxQztBQUNqRCxZQUFZQyw0QkFBOEI7QUFDMUMsWUFBWUMsMkNBQTZDO0FBQ3pELFlBQVlDLGtCQUFvQjtBQUNoQyxZQUFZQyw2QkFBK0I7QUFDM0MsWUFBWUMsMEJBQTRCO0FBQ3hDLFlBQVlDLGdDQUFrQztBQUM5QyxZQUFZQyxxREFBdUQ7QUFDbkUsWUFBWUMsNEJBQThCO0FBQzFDLFlBQVlDLG9DQUFzQztBQUNsRCxZQUFZQyw2QkFBK0I7QUFDM0MsWUFBWUMsOEJBQWdDO0FBQzVDLFlBQVlDLDZCQUErQjtBQUMzQyxZQUFZQywrQkFBaUM7QUFDN0MsWUFBWUMsbUNBQXFDO0FBQ2pELFlBQVlDLGdDQUFrQztBQUM5QyxZQUFZQyx3QkFBMEI7QUFDdEMsWUFBWUMscUNBQXVDO0FBQ25ELFlBQVlDLG1DQUFxQzsiLAogICJuYW1lcyI6IFsiYWJvcnQtc2lnbmFsLWNvbXBvbmVudCIsICJhbGwtd2luZG93cy1ldmVudC1jb21wb25lbnQiLCAiYXN5bmMtZXJyb3ItaGFuZGxlci1jb21wb25lbnQiLCAiYXN5bmMtZXZlbnRzLWNvbXBvbmVudCIsICJjYXNlLWluc2Vuc2l0aXZlLWZpbGUtaW5kZXgtY29tcG9uZW50IiwgImNvbXBvbmVudC1leCIsICJjb25zb2xlLWRlYnVnLWNvbXBvbmVudCIsICJkaXNwb3NhYmxlLWNvbXBvbmVudCIsICJlbWJlZC1leHRlbnNpb25zLWNvbXBvbmVudCIsICJnZW5lcmF0ZS1tYXJrZG93bi1saW5rLWRlZmF1bHQtcGFyYW1zLWNvbXBvbmVudCIsICJsYXlvdXQtcmVhZHktY29tcG9uZW50IiwgIm1lbnUtZXZlbnQtcmVnaXN0cmFyLWNvbXBvbmVudCIsICJtb25rZXktYXJvdW5kLWNvbXBvbmVudCIsICJwbHVnaW4tY29udGV4dC1jb21wb25lbnQiLCAicGx1Z2luLW5vdGljZS1jb21wb25lbnQiLCAicGx1Z2luLXNldHRpbmdzLWNvbXBvbmVudCIsICJwbHVnaW4tc2V0dGluZ3MtdGFiLWNvbXBvbmVudCIsICJwb2ludGVyLXBvc2l0aW9uLWNvbXBvbmVudCIsICJyZWdpc3RyeS1jb21wb25lbnQiLCAicmVuYW1lLWRlbGV0ZS1oYW5kbGVyLWNvbXBvbmVudCIsICJzeW50YXgtaGlnaGxpZ2h0aW5nLWNvbXBvbmVudCJdCn0K
@@ -0,0 +1,149 @@
1
+ /// <reference path="../../library.d.mts" />
2
+ /**
3
+ * @file
4
+ *
5
+ * Contains class {@link SyntaxHighlightingComponent} that registers syntax highlighting languages.
6
+ *
7
+ * Obsidian highlights code in two independent places, through two separate registries, and a plugin adding
8
+ * its own language usually has to touch both:
9
+ *
10
+ * - **Prism** (`prism.languages[language]`) highlights code in reading view and in every `<pre><code>` the
11
+ * library renders — including the {@link CodeHighlighterComponent} settings field.
12
+ * - **The CodeMirror 5 mode registry** (`window.CodeMirror.modes[language]`) highlights a fenced code block
13
+ * inside the editor.
14
+ *
15
+ * The CodeMirror 5 half looks like legacy that should be migrated to CodeMirror 6. **It is not** — verified
16
+ * against the Obsidian 1.13.4 runtime:
17
+ *
18
+ * - Obsidian's own CodeMirror 6 editor language is a bridged CodeMirror 5 mode:
19
+ * `StreamLanguage.define(CodeMirror.getMode({}, { name: 'hypermd' }))`.
20
+ * - Obsidian registers that `hypermd` mode through `window.CodeMirror.defineMode` with
21
+ * `fencedCodeBlockHighlighting: true`, and that option resolves each fence's language through the
22
+ * **CodeMirror 5 mode registry**.
23
+ * - There is no public or internal CodeMirror 6 language-registration API for fences.
24
+ *
25
+ * So `window.CodeMirror.defineMode` is the sanctioned extension point, not legacy debt. Do not reopen this
26
+ * as a migration.
27
+ *
28
+ * Teardown REMOVES the mode rather than redefining it to `null`. Plugins predating this component redefined
29
+ * the mode to `null` on unload, because it was unclear whether CodeMirror's `getMode` needs the entry to
30
+ * stay present. It does not — verified against a live Obsidian 1.13.4 by
31
+ * `syntax-highlighting-component.obsidian.integration.test.ts`: after the entry is deleted, the fence
32
+ * renders its text with no error and drops back to the exact token count it had before the language was
33
+ * ever registered.
34
+ */
35
+ import type { Grammar, PrismModule } from '@obsidian-typings/obsidian-public-latest';
36
+ import { ComponentEx } from './component-ex.mjs';
37
+ /**
38
+ * The loaded Prism module, handed to a grammar factory.
39
+ */
40
+ export interface SyntaxHighlightingComponentGrammarFactoryParams {
41
+ /**
42
+ * The loaded Prism module.
43
+ */
44
+ readonly prism: PrismModule;
45
+ /**
46
+ * Returns the grammar of an already registered Prism language, for nesting into the built grammar.
47
+ *
48
+ * @param language - The language to look up.
49
+ * @returns The grammar of the language.
50
+ * @throws An {@link Error} if the language is not registered.
51
+ */
52
+ requirePrismLanguage(language: string): Grammar;
53
+ }
54
+ /**
55
+ * A grammar, the name of an already registered language to alias, or a factory that builds the grammar from
56
+ * the loaded Prism module.
57
+ */
58
+ export type SyntaxHighlightingComponentGrammarSource = ((params: SyntaxHighlightingComponentGrammarFactoryParams) => Grammar) | Grammar | string;
59
+ /**
60
+ * Parameters for {@link SyntaxHighlightingComponent.registerCodeBlockLanguageAsync}.
61
+ */
62
+ export interface SyntaxHighlightingComponentRegisterCodeBlockLanguageAsyncParams {
63
+ /**
64
+ * The CodeMirror 5 mode name or MIME type the editor highlights the fence as, e.g. `text/typescript`.
65
+ */
66
+ readonly editorMode: string;
67
+ /**
68
+ * The fence language, e.g. the `foo` in a ` ```foo ` code block.
69
+ */
70
+ readonly language: string;
71
+ /**
72
+ * The grammar highlighting the fence in reading view. Omit when the fence is replaced in reading view —
73
+ * e.g. a fence rendered as a button.
74
+ */
75
+ readonly prismGrammar?: SyntaxHighlightingComponentGrammarSource | undefined;
76
+ }
77
+ /**
78
+ * Parameters for {@link SyntaxHighlightingComponent.registerPrismLanguageAsync}.
79
+ */
80
+ export interface SyntaxHighlightingComponentRegisterPrismLanguageAsyncParams {
81
+ /**
82
+ * The grammar to register.
83
+ */
84
+ readonly grammar: SyntaxHighlightingComponentGrammarSource;
85
+ /**
86
+ * The language to register the grammar as.
87
+ */
88
+ readonly language: string;
89
+ }
90
+ /**
91
+ * A component that registers and unregisters syntax highlighting languages.
92
+ *
93
+ * @remarks
94
+ * Every registration is undone when the component is unloaded: the previous entry is restored if the
95
+ * language was already registered, otherwise the entry is removed.
96
+ */
97
+ export declare class SyntaxHighlightingComponent extends ComponentEx {
98
+ /**
99
+ * Registers a fenced code block language, highlighting it in the editor and, optionally, in reading view.
100
+ *
101
+ * @param params - The parameters for registering the language.
102
+ * @returns A {@link Promise} that resolves when the language is registered.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * await component.registerCodeBlockLanguageAsync({
107
+ * editorMode: 'text/typescript',
108
+ * language: 'my-language',
109
+ * prismGrammar: 'typescript'
110
+ * });
111
+ * ```
112
+ */
113
+ registerCodeBlockLanguageAsync(params: SyntaxHighlightingComponentRegisterCodeBlockLanguageAsyncParams): Promise<void>;
114
+ /**
115
+ * Registers a Prism language, highlighting it everywhere Prism renders code — reading view and the
116
+ * {@link CodeHighlighterComponent} settings field.
117
+ *
118
+ * @param params - The parameters for registering the language.
119
+ * @returns A {@link Promise} that resolves when the language is registered.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * await component.registerPrismLanguageAsync({
124
+ * grammar: {
125
+ * keyword: /\bfoo\b/
126
+ * },
127
+ * language: 'my-language'
128
+ * });
129
+ * ```
130
+ */
131
+ registerPrismLanguageAsync(params: SyntaxHighlightingComponentRegisterPrismLanguageAsyncParams): Promise<void>;
132
+ /**
133
+ * Returns the grammar of an already registered Prism language.
134
+ *
135
+ * @param prism - The loaded Prism module.
136
+ * @param language - The language to look up.
137
+ * @returns The grammar of the language.
138
+ * @throws An {@link Error} if the language is not registered.
139
+ */
140
+ private requirePrismLanguage;
141
+ /**
142
+ * Resolves a grammar source into the grammar to register.
143
+ *
144
+ * @param prism - The loaded Prism module.
145
+ * @param grammarSource - The grammar source to resolve.
146
+ * @returns The resolved grammar.
147
+ */
148
+ private resolveGrammar;
149
+ }
@@ -0,0 +1,136 @@
1
+ /*
2
+ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
3
+ if you want to view the source, please visit the github repository of this plugin
4
+ */
5
+
6
+ (function initEsm() {
7
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
8
+ if (globalThis.process) {
9
+ return;
10
+ }
11
+
12
+ const browserProcess = {
13
+ browser: true,
14
+ cwd() {
15
+ return '/';
16
+ },
17
+ env: {},
18
+ platform: 'android'
19
+ };
20
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
21
+ globalThis.process = browserProcess;
22
+ })();
23
+
24
+ import { loadPrism } from "@obsidian-typings/obsidian-public-latest/implementations";
25
+ import { throwExpression } from "../../error.mjs";
26
+ import { ComponentEx } from "./component-ex.mjs";
27
+ class SyntaxHighlightingComponent extends ComponentEx {
28
+ /**
29
+ * Registers a fenced code block language, highlighting it in the editor and, optionally, in reading view.
30
+ *
31
+ * @param params - The parameters for registering the language.
32
+ * @returns A {@link Promise} that resolves when the language is registered.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * await component.registerCodeBlockLanguageAsync({
37
+ * editorMode: 'text/typescript',
38
+ * language: 'my-language',
39
+ * prismGrammar: 'typescript'
40
+ * });
41
+ * ```
42
+ */
43
+ async registerCodeBlockLanguageAsync(params) {
44
+ const {
45
+ editorMode,
46
+ language,
47
+ prismGrammar
48
+ } = params;
49
+ this.ensureLoaded();
50
+ if (prismGrammar !== void 0) {
51
+ await this.registerPrismLanguageAsync({
52
+ grammar: prismGrammar,
53
+ language
54
+ });
55
+ }
56
+ this.ensureLoaded();
57
+ const previousModeFactory = window.CodeMirror.modes[language];
58
+ window.CodeMirror.defineMode(language, (config) => window.CodeMirror.getMode(config, editorMode));
59
+ this.register(() => {
60
+ if (previousModeFactory !== void 0) {
61
+ window.CodeMirror.modes[language] = previousModeFactory;
62
+ return;
63
+ }
64
+ delete window.CodeMirror.modes[language];
65
+ });
66
+ }
67
+ /**
68
+ * Registers a Prism language, highlighting it everywhere Prism renders code — reading view and the
69
+ * {@link CodeHighlighterComponent} settings field.
70
+ *
71
+ * @param params - The parameters for registering the language.
72
+ * @returns A {@link Promise} that resolves when the language is registered.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * await component.registerPrismLanguageAsync({
77
+ * grammar: {
78
+ * keyword: /\bfoo\b/
79
+ * },
80
+ * language: 'my-language'
81
+ * });
82
+ * ```
83
+ */
84
+ async registerPrismLanguageAsync(params) {
85
+ const {
86
+ grammar,
87
+ language
88
+ } = params;
89
+ this.ensureLoaded();
90
+ const prism = await loadPrism();
91
+ this.ensureLoaded();
92
+ const previousGrammar = prism.languages[language];
93
+ prism.languages[language] = this.resolveGrammar(prism, grammar);
94
+ this.register(() => {
95
+ if (previousGrammar !== void 0) {
96
+ prism.languages[language] = previousGrammar;
97
+ return;
98
+ }
99
+ delete prism.languages[language];
100
+ });
101
+ }
102
+ /**
103
+ * Returns the grammar of an already registered Prism language.
104
+ *
105
+ * @param prism - The loaded Prism module.
106
+ * @param language - The language to look up.
107
+ * @returns The grammar of the language.
108
+ * @throws An {@link Error} if the language is not registered.
109
+ */
110
+ requirePrismLanguage(prism, language) {
111
+ return prism.languages[language] ?? throwExpression(new Error(`Prism language "${language}" is not registered.`));
112
+ }
113
+ /**
114
+ * Resolves a grammar source into the grammar to register.
115
+ *
116
+ * @param prism - The loaded Prism module.
117
+ * @param grammarSource - The grammar source to resolve.
118
+ * @returns The resolved grammar.
119
+ */
120
+ resolveGrammar(prism, grammarSource) {
121
+ if (typeof grammarSource === "string") {
122
+ return this.requirePrismLanguage(prism, grammarSource);
123
+ }
124
+ if (typeof grammarSource === "function") {
125
+ return grammarSource({
126
+ prism,
127
+ requirePrismLanguage: (language) => this.requirePrismLanguage(prism, language)
128
+ });
129
+ }
130
+ return grammarSource;
131
+ }
132
+ }
133
+ export {
134
+ SyntaxHighlightingComponent
135
+ };
136
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2NvbXBvbmVudHMvc3ludGF4LWhpZ2hsaWdodGluZy1jb21wb25lbnQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBDb250YWlucyBjbGFzcyB7QGxpbmsgU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50fSB0aGF0IHJlZ2lzdGVycyBzeW50YXggaGlnaGxpZ2h0aW5nIGxhbmd1YWdlcy5cbiAqXG4gKiBPYnNpZGlhbiBoaWdobGlnaHRzIGNvZGUgaW4gdHdvIGluZGVwZW5kZW50IHBsYWNlcywgdGhyb3VnaCB0d28gc2VwYXJhdGUgcmVnaXN0cmllcywgYW5kIGEgcGx1Z2luIGFkZGluZ1xuICogaXRzIG93biBsYW5ndWFnZSB1c3VhbGx5IGhhcyB0byB0b3VjaCBib3RoOlxuICpcbiAqIC0gKipQcmlzbSoqIChgcHJpc20ubGFuZ3VhZ2VzW2xhbmd1YWdlXWApIGhpZ2hsaWdodHMgY29kZSBpbiByZWFkaW5nIHZpZXcgYW5kIGluIGV2ZXJ5IGA8cHJlPjxjb2RlPmAgdGhlXG4gKiAgIGxpYnJhcnkgcmVuZGVycyBcdTIwMTQgaW5jbHVkaW5nIHRoZSB7QGxpbmsgQ29kZUhpZ2hsaWdodGVyQ29tcG9uZW50fSBzZXR0aW5ncyBmaWVsZC5cbiAqIC0gKipUaGUgQ29kZU1pcnJvciA1IG1vZGUgcmVnaXN0cnkqKiAoYHdpbmRvdy5Db2RlTWlycm9yLm1vZGVzW2xhbmd1YWdlXWApIGhpZ2hsaWdodHMgYSBmZW5jZWQgY29kZSBibG9ja1xuICogICBpbnNpZGUgdGhlIGVkaXRvci5cbiAqXG4gKiBUaGUgQ29kZU1pcnJvciA1IGhhbGYgbG9va3MgbGlrZSBsZWdhY3kgdGhhdCBzaG91bGQgYmUgbWlncmF0ZWQgdG8gQ29kZU1pcnJvciA2LiAqKkl0IGlzIG5vdCoqIFx1MjAxNCB2ZXJpZmllZFxuICogYWdhaW5zdCB0aGUgT2JzaWRpYW4gMS4xMy40IHJ1bnRpbWU6XG4gKlxuICogLSBPYnNpZGlhbidzIG93biBDb2RlTWlycm9yIDYgZWRpdG9yIGxhbmd1YWdlIGlzIGEgYnJpZGdlZCBDb2RlTWlycm9yIDUgbW9kZTpcbiAqICAgYFN0cmVhbUxhbmd1YWdlLmRlZmluZShDb2RlTWlycm9yLmdldE1vZGUoe30sIHsgbmFtZTogJ2h5cGVybWQnIH0pKWAuXG4gKiAtIE9ic2lkaWFuIHJlZ2lzdGVycyB0aGF0IGBoeXBlcm1kYCBtb2RlIHRocm91Z2ggYHdpbmRvdy5Db2RlTWlycm9yLmRlZmluZU1vZGVgIHdpdGhcbiAqICAgYGZlbmNlZENvZGVCbG9ja0hpZ2hsaWdodGluZzogdHJ1ZWAsIGFuZCB0aGF0IG9wdGlvbiByZXNvbHZlcyBlYWNoIGZlbmNlJ3MgbGFuZ3VhZ2UgdGhyb3VnaCB0aGVcbiAqICAgKipDb2RlTWlycm9yIDUgbW9kZSByZWdpc3RyeSoqLlxuICogLSBUaGVyZSBpcyBubyBwdWJsaWMgb3IgaW50ZXJuYWwgQ29kZU1pcnJvciA2IGxhbmd1YWdlLXJlZ2lzdHJhdGlvbiBBUEkgZm9yIGZlbmNlcy5cbiAqXG4gKiBTbyBgd2luZG93LkNvZGVNaXJyb3IuZGVmaW5lTW9kZWAgaXMgdGhlIHNhbmN0aW9uZWQgZXh0ZW5zaW9uIHBvaW50LCBub3QgbGVnYWN5IGRlYnQuIERvIG5vdCByZW9wZW4gdGhpc1xuICogYXMgYSBtaWdyYXRpb24uXG4gKlxuICogVGVhcmRvd24gUkVNT1ZFUyB0aGUgbW9kZSByYXRoZXIgdGhhbiByZWRlZmluaW5nIGl0IHRvIGBudWxsYC4gUGx1Z2lucyBwcmVkYXRpbmcgdGhpcyBjb21wb25lbnQgcmVkZWZpbmVkXG4gKiB0aGUgbW9kZSB0byBgbnVsbGAgb24gdW5sb2FkLCBiZWNhdXNlIGl0IHdhcyB1bmNsZWFyIHdoZXRoZXIgQ29kZU1pcnJvcidzIGBnZXRNb2RlYCBuZWVkcyB0aGUgZW50cnkgdG9cbiAqIHN0YXkgcHJlc2VudC4gSXQgZG9lcyBub3QgXHUyMDE0IHZlcmlmaWVkIGFnYWluc3QgYSBsaXZlIE9ic2lkaWFuIDEuMTMuNCBieVxuICogYHN5bnRheC1oaWdobGlnaHRpbmctY29tcG9uZW50Lm9ic2lkaWFuLmludGVncmF0aW9uLnRlc3QudHNgOiBhZnRlciB0aGUgZW50cnkgaXMgZGVsZXRlZCwgdGhlIGZlbmNlXG4gKiByZW5kZXJzIGl0cyB0ZXh0IHdpdGggbm8gZXJyb3IgYW5kIGRyb3BzIGJhY2sgdG8gdGhlIGV4YWN0IHRva2VuIGNvdW50IGl0IGhhZCBiZWZvcmUgdGhlIGxhbmd1YWdlIHdhc1xuICogZXZlciByZWdpc3RlcmVkLlxuICovXG5cbmltcG9ydCB0eXBlIHtcbiAgR3JhbW1hcixcbiAgUHJpc21Nb2R1bGVcbn0gZnJvbSAnQG9ic2lkaWFuLXR5cGluZ3Mvb2JzaWRpYW4tcHVibGljLWxhdGVzdCc7XG5cbmltcG9ydCB7IGxvYWRQcmlzbSB9IGZyb20gJ0BvYnNpZGlhbi10eXBpbmdzL29ic2lkaWFuLXB1YmxpYy1sYXRlc3QvaW1wbGVtZW50YXRpb25zJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAtLSBXZSBuZWVkIHRvIGltcG9ydCBgQ29kZUhpZ2hsaWdodGVyQ29tcG9uZW50YCB0byB1c2UgaXQgaW4gdGhlIHRzZG9jcy5cbmltcG9ydCB0eXBlIHsgQ29kZUhpZ2hsaWdodGVyQ29tcG9uZW50IH0gZnJvbSAnLi4vc2V0dGluZy1jb21wb25lbnRzL2NvZGUtaGlnaGxpZ2h0ZXItY29tcG9uZW50LnRzJztcblxuaW1wb3J0IHsgdGhyb3dFeHByZXNzaW9uIH0gZnJvbSAnLi4vLi4vZXJyb3IudHMnO1xuaW1wb3J0IHsgQ29tcG9uZW50RXggfSBmcm9tICcuL2NvbXBvbmVudC1leC50cyc7XG5cbi8qKlxuICogVGhlIGxvYWRlZCBQcmlzbSBtb2R1bGUsIGhhbmRlZCB0byBhIGdyYW1tYXIgZmFjdG9yeS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTeW50YXhIaWdobGlnaHRpbmdDb21wb25lbnRHcmFtbWFyRmFjdG9yeVBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgbG9hZGVkIFByaXNtIG1vZHVsZS5cbiAgICovXG4gIHJlYWRvbmx5IHByaXNtOiBQcmlzbU1vZHVsZTtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZ3JhbW1hciBvZiBhbiBhbHJlYWR5IHJlZ2lzdGVyZWQgUHJpc20gbGFuZ3VhZ2UsIGZvciBuZXN0aW5nIGludG8gdGhlIGJ1aWx0IGdyYW1tYXIuXG4gICAqXG4gICAqIEBwYXJhbSBsYW5ndWFnZSAtIFRoZSBsYW5ndWFnZSB0byBsb29rIHVwLlxuICAgKiBAcmV0dXJucyBUaGUgZ3JhbW1hciBvZiB0aGUgbGFuZ3VhZ2UuXG4gICAqIEB0aHJvd3MgQW4ge0BsaW5rIEVycm9yfSBpZiB0aGUgbGFuZ3VhZ2UgaXMgbm90IHJlZ2lzdGVyZWQuXG4gICAqL1xuICByZXF1aXJlUHJpc21MYW5ndWFnZShsYW5ndWFnZTogc3RyaW5nKTogR3JhbW1hcjtcbn1cblxuLyoqXG4gKiBBIGdyYW1tYXIsIHRoZSBuYW1lIG9mIGFuIGFscmVhZHkgcmVnaXN0ZXJlZCBsYW5ndWFnZSB0byBhbGlhcywgb3IgYSBmYWN0b3J5IHRoYXQgYnVpbGRzIHRoZSBncmFtbWFyIGZyb21cbiAqIHRoZSBsb2FkZWQgUHJpc20gbW9kdWxlLlxuICovXG5leHBvcnQgdHlwZSBTeW50YXhIaWdobGlnaHRpbmdDb21wb25lbnRHcmFtbWFyU291cmNlID0gKChwYXJhbXM6IFN5bnRheEhpZ2hsaWdodGluZ0NvbXBvbmVudEdyYW1tYXJGYWN0b3J5UGFyYW1zKSA9PiBHcmFtbWFyKSB8IEdyYW1tYXIgfCBzdHJpbmc7XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIFN5bnRheEhpZ2hsaWdodGluZ0NvbXBvbmVudC5yZWdpc3RlckNvZGVCbG9ja0xhbmd1YWdlQXN5bmN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN5bnRheEhpZ2hsaWdodGluZ0NvbXBvbmVudFJlZ2lzdGVyQ29kZUJsb2NrTGFuZ3VhZ2VBc3luY1BhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgQ29kZU1pcnJvciA1IG1vZGUgbmFtZSBvciBNSU1FIHR5cGUgdGhlIGVkaXRvciBoaWdobGlnaHRzIHRoZSBmZW5jZSBhcywgZS5nLiBgdGV4dC90eXBlc2NyaXB0YC5cbiAgICovXG4gIHJlYWRvbmx5IGVkaXRvck1vZGU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGZlbmNlIGxhbmd1YWdlLCBlLmcuIHRoZSBgZm9vYCBpbiBhIGAgYGBgZm9vIGAgY29kZSBibG9jay5cbiAgICovXG4gIHJlYWRvbmx5IGxhbmd1YWdlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBncmFtbWFyIGhpZ2hsaWdodGluZyB0aGUgZmVuY2UgaW4gcmVhZGluZyB2aWV3LiBPbWl0IHdoZW4gdGhlIGZlbmNlIGlzIHJlcGxhY2VkIGluIHJlYWRpbmcgdmlldyBcdTIwMTRcbiAgICogZS5nLiBhIGZlbmNlIHJlbmRlcmVkIGFzIGEgYnV0dG9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJpc21HcmFtbWFyPzogU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50R3JhbW1hclNvdXJjZSB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50LnJlZ2lzdGVyUHJpc21MYW5ndWFnZUFzeW5jfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTeW50YXhIaWdobGlnaHRpbmdDb21wb25lbnRSZWdpc3RlclByaXNtTGFuZ3VhZ2VBc3luY1BhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgZ3JhbW1hciB0byByZWdpc3Rlci5cbiAgICovXG4gIHJlYWRvbmx5IGdyYW1tYXI6IFN5bnRheEhpZ2hsaWdodGluZ0NvbXBvbmVudEdyYW1tYXJTb3VyY2U7XG5cbiAgLyoqXG4gICAqIFRoZSBsYW5ndWFnZSB0byByZWdpc3RlciB0aGUgZ3JhbW1hciBhcy5cbiAgICovXG4gIHJlYWRvbmx5IGxhbmd1YWdlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBjb21wb25lbnQgdGhhdCByZWdpc3RlcnMgYW5kIHVucmVnaXN0ZXJzIHN5bnRheCBoaWdobGlnaHRpbmcgbGFuZ3VhZ2VzLlxuICpcbiAqIEByZW1hcmtzXG4gKiBFdmVyeSByZWdpc3RyYXRpb24gaXMgdW5kb25lIHdoZW4gdGhlIGNvbXBvbmVudCBpcyB1bmxvYWRlZDogdGhlIHByZXZpb3VzIGVudHJ5IGlzIHJlc3RvcmVkIGlmIHRoZVxuICogbGFuZ3VhZ2Ugd2FzIGFscmVhZHkgcmVnaXN0ZXJlZCwgb3RoZXJ3aXNlIHRoZSBlbnRyeSBpcyByZW1vdmVkLlxuICovXG5leHBvcnQgY2xhc3MgU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50RXgge1xuICAvKipcbiAgICogUmVnaXN0ZXJzIGEgZmVuY2VkIGNvZGUgYmxvY2sgbGFuZ3VhZ2UsIGhpZ2hsaWdodGluZyBpdCBpbiB0aGUgZWRpdG9yIGFuZCwgb3B0aW9uYWxseSwgaW4gcmVhZGluZyB2aWV3LlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHJlZ2lzdGVyaW5nIHRoZSBsYW5ndWFnZS5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBsYW5ndWFnZSBpcyByZWdpc3RlcmVkLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0c1xuICAgKiBhd2FpdCBjb21wb25lbnQucmVnaXN0ZXJDb2RlQmxvY2tMYW5ndWFnZUFzeW5jKHtcbiAgICogICBlZGl0b3JNb2RlOiAndGV4dC90eXBlc2NyaXB0JyxcbiAgICogICBsYW5ndWFnZTogJ215LWxhbmd1YWdlJyxcbiAgICogICBwcmlzbUdyYW1tYXI6ICd0eXBlc2NyaXB0J1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJDb2RlQmxvY2tMYW5ndWFnZUFzeW5jKHBhcmFtczogU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50UmVnaXN0ZXJDb2RlQmxvY2tMYW5ndWFnZUFzeW5jUGFyYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qge1xuICAgICAgZWRpdG9yTW9kZSxcbiAgICAgIGxhbmd1YWdlLFxuICAgICAgcHJpc21HcmFtbWFyXG4gICAgfSA9IHBhcmFtcztcblxuICAgIHRoaXMuZW5zdXJlTG9hZGVkKCk7XG5cbiAgICBpZiAocHJpc21HcmFtbWFyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJQcmlzbUxhbmd1YWdlQXN5bmMoe1xuICAgICAgICBncmFtbWFyOiBwcmlzbUdyYW1tYXIsXG4gICAgICAgIGxhbmd1YWdlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmVuc3VyZUxvYWRlZCgpO1xuXG4gICAgY29uc3QgcHJldmlvdXNNb2RlRmFjdG9yeSA9IHdpbmRvdy5Db2RlTWlycm9yLm1vZGVzW2xhbmd1YWdlXTtcbiAgICB3aW5kb3cuQ29kZU1pcnJvci5kZWZpbmVNb2RlKGxhbmd1YWdlLCAoY29uZmlnKSA9PiB3aW5kb3cuQ29kZU1pcnJvci5nZXRNb2RlKGNvbmZpZywgZWRpdG9yTW9kZSkpO1xuXG4gICAgdGhpcy5yZWdpc3RlcigoKSA9PiB7XG4gICAgICBpZiAocHJldmlvdXNNb2RlRmFjdG9yeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHdpbmRvdy5Db2RlTWlycm9yLm1vZGVzW2xhbmd1YWdlXSA9IHByZXZpb3VzTW9kZUZhY3Rvcnk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1keW5hbWljLWRlbGV0ZSAtLSBUaGUgbGFuZ3VhZ2UgaXMgb25seSBrbm93biBhdCBydW50aW1lLlxuICAgICAgZGVsZXRlIHdpbmRvdy5Db2RlTWlycm9yLm1vZGVzW2xhbmd1YWdlXTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSBQcmlzbSBsYW5ndWFnZSwgaGlnaGxpZ2h0aW5nIGl0IGV2ZXJ5d2hlcmUgUHJpc20gcmVuZGVycyBjb2RlIFx1MjAxNCByZWFkaW5nIHZpZXcgYW5kIHRoZVxuICAgKiB7QGxpbmsgQ29kZUhpZ2hsaWdodGVyQ29tcG9uZW50fSBzZXR0aW5ncyBmaWVsZC5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwYXJhbWV0ZXJzIGZvciByZWdpc3RlcmluZyB0aGUgbGFuZ3VhZ2UuXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbGFuZ3VhZ2UgaXMgcmVnaXN0ZXJlZC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHNcbiAgICogYXdhaXQgY29tcG9uZW50LnJlZ2lzdGVyUHJpc21MYW5ndWFnZUFzeW5jKHtcbiAgICogICBncmFtbWFyOiB7XG4gICAqICAgICBrZXl3b3JkOiAvXFxiZm9vXFxiL1xuICAgKiAgIH0sXG4gICAqICAgbGFuZ3VhZ2U6ICdteS1sYW5ndWFnZSdcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyUHJpc21MYW5ndWFnZUFzeW5jKHBhcmFtczogU3ludGF4SGlnaGxpZ2h0aW5nQ29tcG9uZW50UmVnaXN0ZXJQcmlzbUxhbmd1YWdlQXN5bmNQYXJhbXMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7XG4gICAgICBncmFtbWFyLFxuICAgICAgbGFuZ3VhZ2VcbiAgICB9ID0gcGFyYW1zO1xuXG4gICAgdGhpcy5lbnN1cmVMb2FkZWQoKTtcblxuICAgIGNvbnN0IHByaXNtID0gYXdhaXQgbG9hZFByaXNtKCk7XG5cbiAgICAvLyBUaGUgY29tcG9uZW50IG1pZ2h0IGhhdmUgYmVlbiB1bmxvYWRlZCB3aGlsZSBQcmlzbSB3YXMgbG9hZGluZy5cbiAgICB0aGlzLmVuc3VyZUxvYWRlZCgpO1xuXG4gICAgY29uc3QgcHJldmlvdXNHcmFtbWFyID0gcHJpc20ubGFuZ3VhZ2VzW2xhbmd1YWdlXTtcbiAgICBwcmlzbS5sYW5ndWFnZXNbbGFuZ3VhZ2VdID0gdGhpcy5yZXNvbHZlR3JhbW1hcihwcmlzbSwgZ3JhbW1hcik7XG5cbiAgICB0aGlzLnJlZ2lzdGVyKCgpID0+IHtcbiAgICAgIGlmIChwcmV2aW91c0dyYW1tYXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwcmlzbS5sYW5ndWFnZXNbbGFuZ3VhZ2VdID0gcHJldmlvdXNHcmFtbWFyO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZHluYW1pYy1kZWxldGUgLS0gVGhlIGxhbmd1YWdlIGlzIG9ubHkga25vd24gYXQgcnVudGltZS5cbiAgICAgIGRlbGV0ZSBwcmlzbS5sYW5ndWFnZXNbbGFuZ3VhZ2VdO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGdyYW1tYXIgb2YgYW4gYWxyZWFkeSByZWdpc3RlcmVkIFByaXNtIGxhbmd1YWdlLlxuICAgKlxuICAgKiBAcGFyYW0gcHJpc20gLSBUaGUgbG9hZGVkIFByaXNtIG1vZHVsZS5cbiAgICogQHBhcmFtIGxhbmd1YWdlIC0gVGhlIGxhbmd1YWdlIHRvIGxvb2sgdXAuXG4gICAqIEByZXR1cm5zIFRoZSBncmFtbWFyIG9mIHRoZSBsYW5ndWFnZS5cbiAgICogQHRocm93cyBBbiB7QGxpbmsgRXJyb3J9IGlmIHRoZSBsYW5ndWFnZSBpcyBub3QgcmVnaXN0ZXJlZC5cbiAgICovXG4gIHByaXZhdGUgcmVxdWlyZVByaXNtTGFuZ3VhZ2UocHJpc206IFByaXNtTW9kdWxlLCBsYW5ndWFnZTogc3RyaW5nKTogR3JhbW1hciB7XG4gICAgcmV0dXJuIHByaXNtLmxhbmd1YWdlc1tsYW5ndWFnZV0gPz8gdGhyb3dFeHByZXNzaW9uKG5ldyBFcnJvcihgUHJpc20gbGFuZ3VhZ2UgXCIke2xhbmd1YWdlfVwiIGlzIG5vdCByZWdpc3RlcmVkLmApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyBhIGdyYW1tYXIgc291cmNlIGludG8gdGhlIGdyYW1tYXIgdG8gcmVnaXN0ZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcmlzbSAtIFRoZSBsb2FkZWQgUHJpc20gbW9kdWxlLlxuICAgKiBAcGFyYW0gZ3JhbW1hclNvdXJjZSAtIFRoZSBncmFtbWFyIHNvdXJjZSB0byByZXNvbHZlLlxuICAgKiBAcmV0dXJucyBUaGUgcmVzb2x2ZWQgZ3JhbW1hci5cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZUdyYW1tYXIocHJpc206IFByaXNtTW9kdWxlLCBncmFtbWFyU291cmNlOiBTeW50YXhIaWdobGlnaHRpbmdDb21wb25lbnRHcmFtbWFyU291cmNlKTogR3JhbW1hciB7XG4gICAgaWYgKHR5cGVvZiBncmFtbWFyU291cmNlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMucmVxdWlyZVByaXNtTGFuZ3VhZ2UocHJpc20sIGdyYW1tYXJTb3VyY2UpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZ3JhbW1hclNvdXJjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIGdyYW1tYXJTb3VyY2Uoe1xuICAgICAgICBwcmlzbSxcbiAgICAgICAgcmVxdWlyZVByaXNtTGFuZ3VhZ2U6IChsYW5ndWFnZSkgPT4gdGhpcy5yZXF1aXJlUHJpc21MYW5ndWFnZShwcmlzbSwgbGFuZ3VhZ2UpXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JhbW1hclNvdXJjZTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF1Q0EsU0FBUyxpQkFBaUI7QUFLMUIsU0FBUyx1QkFBdUI7QUFDaEMsU0FBUyxtQkFBbUI7QUFzRXJCLE1BQU0sb0NBQW9DLFlBQVk7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQWdCM0QsTUFBYSwrQkFBK0IsUUFBd0Y7QUFDbEksVUFBTTtBQUFBLE1BQ0o7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLElBQ0YsSUFBSTtBQUVKLFNBQUssYUFBYTtBQUVsQixRQUFJLGlCQUFpQixRQUFXO0FBQzlCLFlBQU0sS0FBSywyQkFBMkI7QUFBQSxRQUNwQyxTQUFTO0FBQUEsUUFDVDtBQUFBLE1BQ0YsQ0FBQztBQUFBLElBQ0g7QUFFQSxTQUFLLGFBQWE7QUFFbEIsVUFBTSxzQkFBc0IsT0FBTyxXQUFXLE1BQU0sUUFBUTtBQUM1RCxXQUFPLFdBQVcsV0FBVyxVQUFVLENBQUMsV0FBVyxPQUFPLFdBQVcsUUFBUSxRQUFRLFVBQVUsQ0FBQztBQUVoRyxTQUFLLFNBQVMsTUFBTTtBQUNsQixVQUFJLHdCQUF3QixRQUFXO0FBQ3JDLGVBQU8sV0FBVyxNQUFNLFFBQVEsSUFBSTtBQUNwQztBQUFBLE1BQ0Y7QUFHQSxhQUFPLE9BQU8sV0FBVyxNQUFNLFFBQVE7QUFBQSxJQUN6QyxDQUFDO0FBQUEsRUFDSDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQW1CQSxNQUFhLDJCQUEyQixRQUFvRjtBQUMxSCxVQUFNO0FBQUEsTUFDSjtBQUFBLE1BQ0E7QUFBQSxJQUNGLElBQUk7QUFFSixTQUFLLGFBQWE7QUFFbEIsVUFBTSxRQUFRLE1BQU0sVUFBVTtBQUc5QixTQUFLLGFBQWE7QUFFbEIsVUFBTSxrQkFBa0IsTUFBTSxVQUFVLFFBQVE7QUFDaEQsVUFBTSxVQUFVLFFBQVEsSUFBSSxLQUFLLGVBQWUsT0FBTyxPQUFPO0FBRTlELFNBQUssU0FBUyxNQUFNO0FBQ2xCLFVBQUksb0JBQW9CLFFBQVc7QUFDakMsY0FBTSxVQUFVLFFBQVEsSUFBSTtBQUM1QjtBQUFBLE1BQ0Y7QUFHQSxhQUFPLE1BQU0sVUFBVSxRQUFRO0FBQUEsSUFDakMsQ0FBQztBQUFBLEVBQ0g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFVUSxxQkFBcUIsT0FBb0IsVUFBMkI7QUFDMUUsV0FBTyxNQUFNLFVBQVUsUUFBUSxLQUFLLGdCQUFnQixJQUFJLE1BQU0sbUJBQW1CLFFBQVEsc0JBQXNCLENBQUM7QUFBQSxFQUNsSDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFTUSxlQUFlLE9BQW9CLGVBQWtFO0FBQzNHLFFBQUksT0FBTyxrQkFBa0IsVUFBVTtBQUNyQyxhQUFPLEtBQUsscUJBQXFCLE9BQU8sYUFBYTtBQUFBLElBQ3ZEO0FBRUEsUUFBSSxPQUFPLGtCQUFrQixZQUFZO0FBQ3ZDLGFBQU8sY0FBYztBQUFBLFFBQ25CO0FBQUEsUUFDQSxzQkFBc0IsQ0FBQyxhQUFhLEtBQUsscUJBQXFCLE9BQU8sUUFBUTtBQUFBLE1BQy9FLENBQUM7QUFBQSxJQUNIO0FBRUEsV0FBTztBQUFBLEVBQ1Q7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
@@ -5,12 +5,13 @@
5
5
  * This module defines a base class for creating plugin setting tabs in Obsidian.
6
6
  * It provides a utility method to bind value components to plugin settings and handle changes.
7
7
  */
8
- import type { Plugin } from 'obsidian';
9
- import type { ConditionalKeys, Promisable, ReadonlyDeep } from 'type-fest';
8
+ import type { Plugin, SettingDefinitionGroup, SettingDefinitionItem, SettingDefinitionRender, SettingGroup } from 'obsidian';
9
+ import type { ConditionalKeys, Except, Promisable, ReadonlyDeep } from 'type-fest';
10
10
  import { PluginSettingTab } from 'obsidian';
11
11
  import type { StringKeys } from '../../type.mjs';
12
12
  import type { PluginSettingsComponentBase, ReadonlyPluginSettingsState } from '../components/plugin-settings-component.mjs';
13
13
  import type { ValueComponentWithChangeTracking } from '../setting-components/value-component-with-change-tracking.mjs';
14
+ import type { SettingEx } from '../setting-ex.mjs';
14
15
  import type { ValidationMessageHolder } from '../validation.mjs';
15
16
  /**
16
17
  * A context passed to the {@link PluginSettingsComponentBase.saveToFile} method.
@@ -120,6 +121,60 @@ export interface PluginSettingsTabBaseConstructorParams<PluginSettings extends o
120
121
  */
121
122
  readonly pluginSettingsComponent: PluginSettingsComponentBase<PluginSettings>;
122
123
  }
124
+ /**
125
+ * Params for {@link PluginSettingsTabBase.settingEx}.
126
+ */
127
+ export interface PluginSettingsTabBaseSettingExParams {
128
+ /**
129
+ * Additional search terms for the setting.
130
+ */
131
+ readonly aliases?: string[];
132
+ /**
133
+ * The description of the setting. Used for rendering; the text content of a fragment is used for search.
134
+ */
135
+ readonly desc?: DocumentFragment | string;
136
+ /**
137
+ * Whether the setting row is disabled.
138
+ *
139
+ * A function form is re-evaluated on every render AND on every {@link PluginSettingsTabBase.refreshDomState}
140
+ * call, so it can reflect runtime state. Obsidian applies it with `Setting.setDisabled`, which disables the
141
+ * row and every component registered on it.
142
+ */
143
+ readonly disabled?: (() => boolean) | boolean;
144
+ /**
145
+ * The display name of the setting. Used for rendering and search.
146
+ */
147
+ readonly name: string;
148
+ /**
149
+ * Renders the setting row imperatively, typically via the {@link SettingEx} adders and
150
+ * {@link PluginSettingsTabBase.bind}.
151
+ *
152
+ * The setting Obsidian creates for the row is adopted into a {@link SettingEx} before it is handed over, so
153
+ * an imperative row body carries over unchanged. May return a cleanup function, invoked before the row is
154
+ * torn down or re-rendered.
155
+ *
156
+ * @param setting - The setting to render into.
157
+ * @param group - The group the setting belongs to.
158
+ * @returns An optional cleanup function.
159
+ */
160
+ render(setting: SettingEx, group: SettingGroup): (() => void) | void;
161
+ /**
162
+ * Controls whether the setting is included in the settings search. Defaults to `true`.
163
+ */
164
+ readonly searchable?: (() => boolean) | boolean;
165
+ /**
166
+ * Controls whether the setting row is rendered. A function form is re-evaluated on every render and on
167
+ * every {@link PluginSettingsTabBase.refreshDomState} call. Defaults to `true`.
168
+ */
169
+ readonly visible?: (() => boolean) | boolean;
170
+ }
171
+ /**
172
+ * Params for {@link PluginSettingsTabBase.settingGroupEx}.
173
+ *
174
+ * Every member of {@link SettingDefinitionGroup} except its discriminator, which
175
+ * {@link PluginSettingsTabBase.settingGroupEx} sets.
176
+ */
177
+ export type PluginSettingsTabBaseSettingGroupExParams = Except<SettingDefinitionGroup, 'type'>;
123
178
  interface PluginSettingsTabBaseEventMap {
124
179
  validationMessageChanged: [propertyName: string, validationMessage: string];
125
180
  }
@@ -149,6 +204,7 @@ export declare abstract class PluginSettingsTabBase<PluginSettings extends objec
149
204
  protected get saveSettingsDebounceTimeoutInMilliseconds(): number;
150
205
  private _isOpen;
151
206
  private readonly component;
207
+ private currentRenderComponent;
152
208
  private readonly saveSettingsDebounced;
153
209
  private get pluginSettings();
154
210
  /**
@@ -181,11 +237,33 @@ export declare abstract class PluginSettingsTabBase<PluginSettings extends objec
181
237
  */
182
238
  display(): void;
183
239
  /**
184
- * Legacy way to render the plugin settings tab.
240
+ * Legacy way to render the plugin settings tab imperatively.
185
241
  *
186
- * Temporary workaround to avoid dealing with `@deprecated`.
242
+ * The pre-declarative fallback: Obsidian only calls it when {@link getSettingDefinitions} returns an empty
243
+ * array, i.e. when the consumer has not overridden {@link getSettingDefinitionItems}. Such a consumer
244
+ * overrides this method and builds the UI with {@link SettingEx} and {@link bind}.
187
245
  */
188
246
  displayLegacy(): void;
247
+ /**
248
+ * Reads the value backing a native `control` setting definition.
249
+ *
250
+ * Obsidian calls it on every render of a `control`-type definition. The inherited implementation reads
251
+ * `plugin.settings`, which a plugin built on {@link PluginSettingsComponentBase} never populates, so it is
252
+ * routed to the settings component instead.
253
+ *
254
+ * @param key - The settings property name.
255
+ * @returns The current value.
256
+ */
257
+ getControlValue(key: string): unknown;
258
+ /**
259
+ * Returns the declarative setting definitions rendered by Obsidian 1.13+.
260
+ *
261
+ * Delegates to {@link getSettingDefinitionItems}. When a consumer has not overridden that hook it returns
262
+ * an empty array, and Obsidian falls back to the imperative {@link displayLegacy} path.
263
+ *
264
+ * @returns The setting definitions.
265
+ */
266
+ getSettingDefinitions(): SettingDefinitionItem[];
189
267
  /**
190
268
  * Hides the plugin settings tab.
191
269
  */
@@ -196,10 +274,50 @@ export declare abstract class PluginSettingsTabBase<PluginSettings extends objec
196
274
  * @returns A {@link Promise} that resolves when the settings tab is hidden.
197
275
  */
198
276
  hideAsync(): Promise<void>;
277
+ /**
278
+ * Re-renders the settings tab after the underlying state changed.
279
+ *
280
+ * Rebuilds the definitions and re-renders, which covers both paths: Obsidian renders the declarative
281
+ * definitions when {@link getSettingDefinitionItems} provides them, and falls back to
282
+ * {@link displayLegacy} when it does not. Nothing is rendered while the tab is not the one on screen.
283
+ *
284
+ * Use it only for changes that alter the STRUCTURE of the tab — rows added or removed. When only a
285
+ * {@link PluginSettingsTabBaseSettingExParams.disabled} / {@link PluginSettingsTabBaseSettingExParams.visible}
286
+ * predicate has to be re-evaluated, call the much cheaper {@link refreshDomState} instead, which toggles the
287
+ * rendered DOM in place.
288
+ */
289
+ refresh(): void;
290
+ /**
291
+ * Persists the value of a native `control` setting definition.
292
+ *
293
+ * The counterpart of {@link getControlValue}: it routes the write to the settings component instead of the
294
+ * inherited `plugin.saveData` path, so validation, transformers and the debounced save all apply as they do
295
+ * for a {@link bind}-ed component.
296
+ *
297
+ * @param key - The settings property name.
298
+ * @param value - The value to persist.
299
+ * @returns A {@link Promise} that resolves when the value is set.
300
+ */
301
+ setControlValue(key: string, value: unknown): Promise<void>;
199
302
  /**
200
303
  * Shows the plugin settings tab.
201
304
  */
202
305
  show(): void;
306
+ /**
307
+ * The declarative setting definitions for the tab (Obsidian 1.13+).
308
+ *
309
+ * Consumers override this, typically building each row with {@link settingEx} and {@link bind} and grouping
310
+ * them with `settingGroupEx`. Returning an empty array — the default — makes Obsidian fall back to the
311
+ * imperative {@link displayLegacy} path.
312
+ *
313
+ * MUST be a pure builder. Obsidian calls it when the tab is registered (`addSettingTab`), long before the
314
+ * tab is ever opened, in order to index the settings for search. Anything with a side effect belongs inside
315
+ * a row's {@link PluginSettingsTabBaseSettingExParams.render} callback, which runs only when the row is
316
+ * actually rendered.
317
+ *
318
+ * @returns The setting definitions.
319
+ */
320
+ protected getSettingDefinitionItems(): SettingDefinitionItem[];
203
321
  /**
204
322
  * Called when the plugin settings are loaded.
205
323
  *
@@ -214,8 +332,37 @@ export declare abstract class PluginSettingsTabBase<PluginSettings extends objec
214
332
  * @returns A {@link Promise} that resolves when the settings are revalidated.
215
333
  */
216
334
  protected revalidate(): Promise<void>;
335
+ /**
336
+ * Builds a search-indexable declarative row that is rendered imperatively.
337
+ *
338
+ * The bridge between the declarative API and ODU's imperative building blocks: Obsidian owns the row (so it
339
+ * indexes it for search and evaluates its {@link PluginSettingsTabBaseSettingExParams.visible} /
340
+ * {@link PluginSettingsTabBaseSettingExParams.disabled} predicates on every
341
+ * {@link refreshDomState}), while {@link PluginSettingsTabBaseSettingExParams.render} fills it in with
342
+ * {@link SettingEx} adders and {@link bind} exactly as an imperative tab would.
343
+ *
344
+ * @param params - The row params.
345
+ * @returns The setting definition.
346
+ */
347
+ protected settingEx(params: PluginSettingsTabBaseSettingExParams): SettingDefinitionRender;
348
+ /**
349
+ * Builds a declarative heading group.
350
+ *
351
+ * The declarative counterpart of `SettingGroupEx`: where that class appends a group to a container
352
+ * imperatively, this returns the definition Obsidian renders, so a group-structured tab keeps its shape
353
+ * after the migration.
354
+ *
355
+ * @param params - The group params.
356
+ * @returns The group definition.
357
+ */
358
+ protected settingGroupEx(params: PluginSettingsTabBaseSettingGroupExParams): SettingDefinitionGroup;
359
+ private beginRenderCycle;
360
+ private createRenderComponent;
361
+ private endRenderCycle;
217
362
  private getPluginSettingsProperty;
363
+ private getRenderComponent;
218
364
  private onSaveSettings;
365
+ private renderSettingEx;
219
366
  private updateValidations;
220
367
  }
221
368
  export {};