MetaList 0.3.13__tar.gz → 0.3.14__tar.gz

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 (376) hide show
  1. {metalist-0.3.13/metalist.egg-info → metalist-0.3.14}/PKG-INFO +16 -2
  2. {metalist-0.3.13 → metalist-0.3.14}/README.md +15 -1
  3. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/ontology.py +13 -4
  4. {metalist-0.3.13 → metalist-0.3.14}/app/services/content_formatting.py +29 -6
  5. {metalist-0.3.13 → metalist-0.3.14}/app/services/embedded_references.py +9 -4
  6. {metalist-0.3.13 → metalist-0.3.14}/app/services/ontology_rules_store.py +41 -0
  7. {metalist-0.3.13 → metalist-0.3.14}/app/services/tag_rename.py +77 -0
  8. {metalist-0.3.13 → metalist-0.3.14}/app/static/css/main.css +511 -56
  9. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/help-modal.js +1 -1
  10. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/ontology-modal.js +122 -37
  11. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/password-modal.js +1 -3
  12. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/random-password-modal.js +15 -27
  13. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/reminder-modal.js +1 -0
  14. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/sound-manager-modal.js +1 -0
  15. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/keyboard-events.js +168 -38
  16. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/mode-context.js +8 -16
  17. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +24 -5
  18. metalist-0.3.14/app/static/js/modules/mode-manager/services/tab-drag-service.js +42 -0
  19. metalist-0.3.14/app/usecases/delete_tag.py +66 -0
  20. {metalist-0.3.13 → metalist-0.3.14}/app/version.py +1 -1
  21. {metalist-0.3.13 → metalist-0.3.14/metalist.egg-info}/PKG-INFO +16 -2
  22. {metalist-0.3.13 → metalist-0.3.14}/metalist.egg-info/SOURCES.txt +2 -0
  23. {metalist-0.3.13 → metalist-0.3.14}/MANIFEST.in +0 -0
  24. {metalist-0.3.13 → metalist-0.3.14}/app/__init__.py +0 -0
  25. {metalist-0.3.13 → metalist-0.3.14}/app/api/__init__.py +0 -0
  26. {metalist-0.3.13 → metalist-0.3.14}/app/api/deps.py +0 -0
  27. {metalist-0.3.13 → metalist-0.3.14}/app/api/dev.py +0 -0
  28. {metalist-0.3.13 → metalist-0.3.14}/app/api/middleware/auth.py +0 -0
  29. {metalist-0.3.13 → metalist-0.3.14}/app/api/request_auth.py +0 -0
  30. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/auth.py +0 -0
  31. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/backups.py +0 -0
  32. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/files.py +0 -0
  33. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/notes.py +0 -0
  34. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/reminders.py +0 -0
  35. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/remote_images.py +0 -0
  36. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/sounds.py +0 -0
  37. {metalist-0.3.13 → metalist-0.3.14}/app/api/routes/test.py +0 -0
  38. {metalist-0.3.13 → metalist-0.3.14}/app/api/transactions.py +0 -0
  39. {metalist-0.3.13 → metalist-0.3.14}/app/config.py +0 -0
  40. {metalist-0.3.13 → metalist-0.3.14}/app/db/__init__.py +0 -0
  41. {metalist-0.3.13 → metalist-0.3.14}/app/db/backup_settings_sql.py +0 -0
  42. {metalist-0.3.13 → metalist-0.3.14}/app/db/engine.py +0 -0
  43. {metalist-0.3.13 → metalist-0.3.14}/app/db/file_schema.py +0 -0
  44. {metalist-0.3.13 → metalist-0.3.14}/app/db/file_session.py +0 -0
  45. {metalist-0.3.13 → metalist-0.3.14}/app/db/files_sql.py +0 -0
  46. {metalist-0.3.13 → metalist-0.3.14}/app/db/link_titles_sql.py +0 -0
  47. {metalist-0.3.13 → metalist-0.3.14}/app/db/migrations.py +0 -0
  48. {metalist-0.3.13 → metalist-0.3.14}/app/db/notes_sql.py +0 -0
  49. {metalist-0.3.13 → metalist-0.3.14}/app/db/ontology_rules_sql.py +0 -0
  50. {metalist-0.3.13 → metalist-0.3.14}/app/db/reminders_sql.py +0 -0
  51. {metalist-0.3.13 → metalist-0.3.14}/app/db/schema.py +0 -0
  52. {metalist-0.3.13 → metalist-0.3.14}/app/db/search_history_sql.py +0 -0
  53. {metalist-0.3.13 → metalist-0.3.14}/app/db/session.py +0 -0
  54. {metalist-0.3.13 → metalist-0.3.14}/app/db/settings_sql.py +0 -0
  55. {metalist-0.3.13 → metalist-0.3.14}/app/db/sounds_sql.py +0 -0
  56. {metalist-0.3.13 → metalist-0.3.14}/app/db/tab_state_sql.py +0 -0
  57. {metalist-0.3.13 → metalist-0.3.14}/app/db/version.py +0 -0
  58. {metalist-0.3.13 → metalist-0.3.14}/app/encryption_audit.py +0 -0
  59. {metalist-0.3.13 → metalist-0.3.14}/app/main.py +0 -0
  60. {metalist-0.3.13 → metalist-0.3.14}/app/models/commands.py +0 -0
  61. {metalist-0.3.13 → metalist-0.3.14}/app/models/database.py +0 -0
  62. {metalist-0.3.13 → metalist-0.3.14}/app/models/entities.py +0 -0
  63. {metalist-0.3.13 → metalist-0.3.14}/app/models/enums.py +0 -0
  64. {metalist-0.3.13 → metalist-0.3.14}/app/models/linked_list.py +0 -0
  65. {metalist-0.3.13 → metalist-0.3.14}/app/models/list_operations.py +0 -0
  66. {metalist-0.3.13 → metalist-0.3.14}/app/models/list_traversal.py +0 -0
  67. {metalist-0.3.13 → metalist-0.3.14}/app/models/note_crud.py +0 -0
  68. {metalist-0.3.13 → metalist-0.3.14}/app/models/utils.py +0 -0
  69. {metalist-0.3.13 → metalist-0.3.14}/app/presentation/__init__.py +0 -0
  70. {metalist-0.3.13 → metalist-0.3.14}/app/presentation/render/__init__.py +0 -0
  71. {metalist-0.3.13 → metalist-0.3.14}/app/presentation/render/note_renderer.py +0 -0
  72. {metalist-0.3.13 → metalist-0.3.14}/app/presentation/templates.py +0 -0
  73. {metalist-0.3.13 → metalist-0.3.14}/app/security/authenticated_logging.py +0 -0
  74. {metalist-0.3.13 → metalist-0.3.14}/app/security/encryption.py +0 -0
  75. {metalist-0.3.13 → metalist-0.3.14}/app/security/http_headers.py +0 -0
  76. {metalist-0.3.13 → metalist-0.3.14}/app/security/note_html.py +0 -0
  77. {metalist-0.3.13 → metalist-0.3.14}/app/security/request_boundary.py +0 -0
  78. {metalist-0.3.13 → metalist-0.3.14}/app/security/sensitive_logging.py +0 -0
  79. {metalist-0.3.13 → metalist-0.3.14}/app/security/shell_execution.py +0 -0
  80. {metalist-0.3.13 → metalist-0.3.14}/app/security/validation_errors.py +0 -0
  81. {metalist-0.3.13 → metalist-0.3.14}/app/server_runtime.py +0 -0
  82. {metalist-0.3.13 → metalist-0.3.14}/app/services/__init__.py +0 -0
  83. {metalist-0.3.13 → metalist-0.3.14}/app/services/auth.py +0 -0
  84. {metalist-0.3.13 → metalist-0.3.14}/app/services/auth_cache_state.py +0 -0
  85. {metalist-0.3.13 → metalist-0.3.14}/app/services/auth_service.py +0 -0
  86. {metalist-0.3.13 → metalist-0.3.14}/app/services/backlinks.py +0 -0
  87. {metalist-0.3.13 → metalist-0.3.14}/app/services/backup_service.py +0 -0
  88. {metalist-0.3.13 → metalist-0.3.14}/app/services/backup_settings_service.py +0 -0
  89. {metalist-0.3.13 → metalist-0.3.14}/app/services/base_service.py +0 -0
  90. {metalist-0.3.13 → metalist-0.3.14}/app/services/client_state_service.py +0 -0
  91. {metalist-0.3.13 → metalist-0.3.14}/app/services/content_cache.py +0 -0
  92. {metalist-0.3.13 → metalist-0.3.14}/app/services/date_filtering.py +0 -0
  93. {metalist-0.3.13 → metalist-0.3.14}/app/services/dependencies.py +0 -0
  94. {metalist-0.3.13 → metalist-0.3.14}/app/services/diagnostics.py +0 -0
  95. {metalist-0.3.13 → metalist-0.3.14}/app/services/encryption.py +0 -0
  96. {metalist-0.3.13 → metalist-0.3.14}/app/services/exception_capture.py +0 -0
  97. {metalist-0.3.13 → metalist-0.3.14}/app/services/file_registry.py +0 -0
  98. {metalist-0.3.13 → metalist-0.3.14}/app/services/file_storage.py +0 -0
  99. {metalist-0.3.13 → metalist-0.3.14}/app/services/html_export.py +0 -0
  100. {metalist-0.3.13 → metalist-0.3.14}/app/services/html_unformatting.py +0 -0
  101. {metalist-0.3.13 → metalist-0.3.14}/app/services/hydration_state.py +0 -0
  102. {metalist-0.3.13 → metalist-0.3.14}/app/services/image_size_formatting.py +0 -0
  103. {metalist-0.3.13 → metalist-0.3.14}/app/services/inline_image_occurrences.py +0 -0
  104. {metalist-0.3.13 → metalist-0.3.14}/app/services/integrity.py +0 -0
  105. {metalist-0.3.13 → metalist-0.3.14}/app/services/latex_rendering.py +0 -0
  106. {metalist-0.3.13 → metalist-0.3.14}/app/services/link_titles.py +0 -0
  107. {metalist-0.3.13 → metalist-0.3.14}/app/services/login_rate_limit.py +0 -0
  108. {metalist-0.3.13 → metalist-0.3.14}/app/services/maintenance_mode.py +0 -0
  109. {metalist-0.3.13 → metalist-0.3.14}/app/services/markdown_rendering.py +0 -0
  110. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_deletion_jobs.py +0 -0
  111. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_deletion_worker.py +0 -0
  112. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_rename_jobs.py +0 -0
  113. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_rename_worker.py +0 -0
  114. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_runtime_guard.py +0 -0
  115. {metalist-0.3.13 → metalist-0.3.14}/app/services/namespace_switcher.py +0 -0
  116. {metalist-0.3.13 → metalist-0.3.14}/app/services/note_fullscreen.py +0 -0
  117. {metalist-0.3.13 → metalist-0.3.14}/app/services/note_image_tags.py +0 -0
  118. {metalist-0.3.13 → metalist-0.3.14}/app/services/note_service.py +0 -0
  119. {metalist-0.3.13 → metalist-0.3.14}/app/services/note_store.py +0 -0
  120. {metalist-0.3.13 → metalist-0.3.14}/app/services/query_service.py +0 -0
  121. {metalist-0.3.13 → metalist-0.3.14}/app/services/reminders.py +0 -0
  122. {metalist-0.3.13 → metalist-0.3.14}/app/services/remote_image_proxy.py +0 -0
  123. {metalist-0.3.13 → metalist-0.3.14}/app/services/root_sorting.py +0 -0
  124. {metalist-0.3.13 → metalist-0.3.14}/app/services/runtime_hardening.py +0 -0
  125. {metalist-0.3.13 → metalist-0.3.14}/app/services/runtime_lock.py +0 -0
  126. {metalist-0.3.13 → metalist-0.3.14}/app/services/search_history.py +0 -0
  127. {metalist-0.3.13 → metalist-0.3.14}/app/services/search_history_storage.py +0 -0
  128. {metalist-0.3.13 → metalist-0.3.14}/app/services/search_index.py +0 -0
  129. {metalist-0.3.13 → metalist-0.3.14}/app/services/search_query.py +0 -0
  130. {metalist-0.3.13 → metalist-0.3.14}/app/services/search_text.py +0 -0
  131. {metalist-0.3.13 → metalist-0.3.14}/app/services/selected_text_tag.py +0 -0
  132. {metalist-0.3.13 → metalist-0.3.14}/app/services/self_update.py +0 -0
  133. {metalist-0.3.13 → metalist-0.3.14}/app/services/session_timeout_service.py +0 -0
  134. {metalist-0.3.13 → metalist-0.3.14}/app/services/shell_session_service.py +0 -0
  135. {metalist-0.3.13 → metalist-0.3.14}/app/services/snapshot.py +0 -0
  136. {metalist-0.3.13 → metalist-0.3.14}/app/services/sound_storage.py +0 -0
  137. {metalist-0.3.13 → metalist-0.3.14}/app/services/store.py +0 -0
  138. {metalist-0.3.13 → metalist-0.3.14}/app/services/sync.py +0 -0
  139. {metalist-0.3.13 → metalist-0.3.14}/app/services/sync_state.py +0 -0
  140. {metalist-0.3.13 → metalist-0.3.14}/app/services/tab_state.py +0 -0
  141. {metalist-0.3.13 → metalist-0.3.14}/app/services/tag_case.py +0 -0
  142. {metalist-0.3.13 → metalist-0.3.14}/app/services/tag_ontology.py +0 -0
  143. {metalist-0.3.13 → metalist-0.3.14}/app/services/tag_suggestions.py +0 -0
  144. {metalist-0.3.13 → metalist-0.3.14}/app/services/tag_term_matching.py +0 -0
  145. {metalist-0.3.13 → metalist-0.3.14}/app/services/test_reset.py +0 -0
  146. {metalist-0.3.13 → metalist-0.3.14}/app/services/tokens.py +0 -0
  147. {metalist-0.3.13 → metalist-0.3.14}/app/services/transaction_manager.py +0 -0
  148. {metalist-0.3.13 → metalist-0.3.14}/app/services/undo_service.py +0 -0
  149. {metalist-0.3.13 → metalist-0.3.14}/app/services/undo_state.py +0 -0
  150. {metalist-0.3.13 → metalist-0.3.14}/app/services/view_cache.py +0 -0
  151. {metalist-0.3.13 → metalist-0.3.14}/app/services/view_diff.py +0 -0
  152. {metalist-0.3.13 → metalist-0.3.14}/app/services/view_state.py +0 -0
  153. {metalist-0.3.13 → metalist-0.3.14}/app/services/windows_process_control.py +0 -0
  154. {metalist-0.3.13 → metalist-0.3.14}/app/startup_environment.py +0 -0
  155. {metalist-0.3.13 → metalist-0.3.14}/app/startup_js_sanity.py +0 -0
  156. {metalist-0.3.13 → metalist-0.3.14}/app/startup_sanity.py +0 -0
  157. {metalist-0.3.13 → metalist-0.3.14}/app/startup_sanity_config.py +0 -0
  158. {metalist-0.3.13 → metalist-0.3.14}/app/static/config/command_palette_tags.json +0 -0
  159. {metalist-0.3.13 → metalist-0.3.14}/app/static/css/forms.css +0 -0
  160. {metalist-0.3.13 → metalist-0.3.14}/app/static/img/favicon.ico +0 -0
  161. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/locked.js +0 -0
  162. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/main.js +0 -0
  163. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/activity-tracker.js +0 -0
  164. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/api-client.js +0 -0
  165. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/api-failure-classification-service.js +0 -0
  166. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/async-result.js +0 -0
  167. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/auth.js +0 -0
  168. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/client-state-api.js +0 -0
  169. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/client-state-migration.js +0 -0
  170. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  171. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  172. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  173. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/command-palette-controller.js +0 -0
  174. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
  175. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  176. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  177. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  178. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/command-palette/usage-store.js +0 -0
  179. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/config.js +0 -0
  180. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/connectivity-monitor.js +0 -0
  181. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  182. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  183. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  184. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  185. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  186. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/dom-utils-fixed.js +0 -0
  187. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/dom-utils.js +0 -0
  188. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/editor-commands.js +0 -0
  189. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/editor-selection.js +0 -0
  190. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/editor-toolbar.js +0 -0
  191. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/elapsed-time.js +0 -0
  192. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/error-handler.js +0 -0
  193. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/error-overlay.js +0 -0
  194. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/location-flags.js +0 -0
  195. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/login-namespace-picker.js +0 -0
  196. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  197. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  198. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  199. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  200. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  201. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/base-modal.js +0 -0
  202. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  203. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  204. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  205. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  206. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/namespace-modals.js +0 -0
  207. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  208. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  209. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  210. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  211. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  212. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  213. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  214. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/modals/version-info-modal.js +0 -0
  215. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  216. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  217. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  218. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  219. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  220. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  221. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  222. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  223. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  224. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  225. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
  226. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  227. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  228. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  229. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  230. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  231. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  232. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  233. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  234. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  235. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  236. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/date-filter-indicator-service.js +0 -0
  237. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/date-filter-service.js +0 -0
  238. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  239. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  240. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  241. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  242. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  243. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  244. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  245. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  246. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  247. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  248. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  249. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  250. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  251. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  252. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  253. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  254. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  255. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  256. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  257. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  258. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  259. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  260. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  261. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  262. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  263. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  264. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  265. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  266. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  267. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  268. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  269. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  270. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  271. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/rhs-panel-service.js +0 -0
  272. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  273. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  274. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  275. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  276. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  277. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  278. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  279. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  280. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  281. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  282. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  283. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  284. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  285. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  286. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  287. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  288. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  289. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  290. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  291. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  292. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  293. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  294. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  295. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  296. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  297. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  298. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  299. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  300. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/note-html-sanitizer.js +0 -0
  301. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/password-generator.js +0 -0
  302. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/password-operation-response.js +0 -0
  303. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/password-policy.js +0 -0
  304. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/password-strength.js +0 -0
  305. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/reminder-store.js +0 -0
  306. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/reminder-surface-service.js +0 -0
  307. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/selection-markers.js +0 -0
  308. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/session-auth.js +0 -0
  309. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/sound-service.js +0 -0
  310. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/tag-token.js +0 -0
  311. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/modules/uuid.js +0 -0
  312. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/namespace-deleted.js +0 -0
  313. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/namespace-renamed.js +0 -0
  314. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/dompurify-3.4.12.LICENSE.txt +0 -0
  315. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/dompurify-3.4.12.min.js +0 -0
  316. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/markdown-it.min.js +0 -0
  317. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/mermaid-11.9.0.LICENSE.txt +0 -0
  318. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/mermaid-11.9.0.min.js +0 -0
  319. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  320. {metalist-0.3.13 → metalist-0.3.14}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  321. {metalist-0.3.13 → metalist-0.3.14}/app/static/note-html-policy.json +0 -0
  322. {metalist-0.3.13 → metalist-0.3.14}/app/static/video/login-startup.mp4 +0 -0
  323. {metalist-0.3.13 → metalist-0.3.14}/app/templates/base.html +0 -0
  324. {metalist-0.3.13 → metalist-0.3.14}/app/templates/index.html +0 -0
  325. {metalist-0.3.13 → metalist-0.3.14}/app/templates/locked.html +0 -0
  326. {metalist-0.3.13 → metalist-0.3.14}/app/templates/maintenance.html +0 -0
  327. {metalist-0.3.13 → metalist-0.3.14}/app/templates/namespace_deleted.html +0 -0
  328. {metalist-0.3.13 → metalist-0.3.14}/app/templates/namespace_renamed.html +0 -0
  329. {metalist-0.3.13 → metalist-0.3.14}/app/templates/notes_list.html +0 -0
  330. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/__init__.py +0 -0
  331. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/add_selected_text_tag.py +0 -0
  332. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/alphabetize_root_notes.py +0 -0
  333. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/base.py +0 -0
  334. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/collapse.py +0 -0
  335. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/copy_note.py +0 -0
  336. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/create_child.py +0 -0
  337. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/create_note.py +0 -0
  338. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/create_sibling.py +0 -0
  339. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/delete_subtree.py +0 -0
  340. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/expand.py +0 -0
  341. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/indent.py +0 -0
  342. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/lock.py +0 -0
  343. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/move.py +0 -0
  344. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/move_to_top.py +0 -0
  345. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/outdent.py +0 -0
  346. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/paste_child.py +0 -0
  347. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/paste_sibling.py +0 -0
  348. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/prioritize.py +0 -0
  349. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/redo.py +0 -0
  350. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/rename_tag.py +0 -0
  351. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/reset_updated_at.py +0 -0
  352. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/resize_image.py +0 -0
  353. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/run_shell.py +0 -0
  354. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/search_comment_autofill.py +0 -0
  355. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/search_context_tags.py +0 -0
  356. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/set_collapse_bulk.py +0 -0
  357. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/set_collapse_in_context.py +0 -0
  358. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/split_note.py +0 -0
  359. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/toggle_reference_mode.py +0 -0
  360. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/toggle_todo_done.py +0 -0
  361. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/undo.py +0 -0
  362. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/unformat_content.py +0 -0
  363. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/update_content.py +0 -0
  364. {metalist-0.3.13 → metalist-0.3.14}/app/usecases/view.py +0 -0
  365. {metalist-0.3.13 → metalist-0.3.14}/app/utils/__init__.py +0 -0
  366. {metalist-0.3.13 → metalist-0.3.14}/app/utils/encryption.py +0 -0
  367. {metalist-0.3.13 → metalist-0.3.14}/app/utils/text_utils.py +0 -0
  368. {metalist-0.3.13 → metalist-0.3.14}/convert-from-legacy.py +0 -0
  369. {metalist-0.3.13 → metalist-0.3.14}/main.py +0 -0
  370. {metalist-0.3.13 → metalist-0.3.14}/metalist.egg-info/dependency_links.txt +0 -0
  371. {metalist-0.3.13 → metalist-0.3.14}/metalist.egg-info/entry_points.txt +0 -0
  372. {metalist-0.3.13 → metalist-0.3.14}/metalist.egg-info/requires.txt +0 -0
  373. {metalist-0.3.13 → metalist-0.3.14}/metalist.egg-info/top_level.txt +0 -0
  374. {metalist-0.3.13 → metalist-0.3.14}/pyproject.toml +0 -0
  375. {metalist-0.3.13 → metalist-0.3.14}/scripts/generate-lan-cert.sh +0 -0
  376. {metalist-0.3.13 → metalist-0.3.14}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.3.13
3
+ Version: 0.3.14
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
@@ -67,6 +67,20 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
67
67
  - The browser client drives interaction via `/api2` JSON endpoints.
68
68
  - Notes are loaded/decrypted into an in-memory store at startup; a post-startup DB read guard prevents accidental runtime SELECTs.
69
69
 
70
+ ## Security Boundary
71
+
72
+ Password protection encrypts namespace data at rest. While a namespace is
73
+ unlocked, the server must hold its data-encryption key and decrypted working
74
+ data in process memory, and the browser holds the decrypted content currently
75
+ rendered in the page. A sufficiently privileged local process, debugger,
76
+ administrator, browser extension, or process-memory dump can therefore expose
77
+ an unlocked namespace.
78
+
79
+ Explicit logout removes the live key and purges decrypted runtime stores, but
80
+ it cannot guarantee forensic overwriting of memory previously allocated by the
81
+ Python or browser runtimes. Protect the host account and operating system, and
82
+ see the detailed [security architecture and threat model](docs/security/README.md).
83
+
70
84
  ## Development
71
85
 
72
86
  ### Setup
@@ -85,7 +99,7 @@ After the first installation, update and restart MetaList with one cross-platfor
85
99
  ```bash
86
100
  metalist update
87
101
  ```
88
- The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.13.`).
102
+ The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.14.`).
89
103
 
90
104
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
91
105
 
@@ -33,6 +33,20 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
33
33
  - The browser client drives interaction via `/api2` JSON endpoints.
34
34
  - Notes are loaded/decrypted into an in-memory store at startup; a post-startup DB read guard prevents accidental runtime SELECTs.
35
35
 
36
+ ## Security Boundary
37
+
38
+ Password protection encrypts namespace data at rest. While a namespace is
39
+ unlocked, the server must hold its data-encryption key and decrypted working
40
+ data in process memory, and the browser holds the decrypted content currently
41
+ rendered in the page. A sufficiently privileged local process, debugger,
42
+ administrator, browser extension, or process-memory dump can therefore expose
43
+ an unlocked namespace.
44
+
45
+ Explicit logout removes the live key and purges decrypted runtime stores, but
46
+ it cannot guarantee forensic overwriting of memory previously allocated by the
47
+ Python or browser runtimes. Protect the host account and operating system, and
48
+ see the detailed [security architecture and threat model](docs/security/README.md).
49
+
36
50
  ## Development
37
51
 
38
52
  ### Setup
@@ -51,7 +65,7 @@ After the first installation, update and restart MetaList with one cross-platfor
51
65
  ```bash
52
66
  metalist update
53
67
  ```
54
- The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.13.`).
68
+ The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.3.14.`).
55
69
 
56
70
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
57
71
 
@@ -20,6 +20,7 @@ from app.services.ontology_rules_store import (
20
20
  update_rule_line,
21
21
  )
22
22
  from app.usecases.rename_tag import apply_rename_tag_everywhere
23
+ from app.usecases.delete_tag import apply_delete_tag_everywhere
23
24
  from app.utils.text_utils import strip_html
24
25
 
25
26
 
@@ -226,6 +227,16 @@ def rename_tag(request: Request, payload: dict) -> dict:
226
227
  return apply_rename_tag_everywhere(old=old, new=new, token=token)
227
228
 
228
229
 
230
+ @router.post("/delete-tag")
231
+ @transactional_route
232
+ def delete_tag(request: Request, payload: dict) -> dict:
233
+ tag = payload["tag"]
234
+ if not isinstance(tag, str) or tag.strip() == "":
235
+ raise HTTPException(status_code=400, detail="tag must be a non-empty string")
236
+ token = _maybe_bearer_token(request)
237
+ return apply_delete_tag_everywhere(tag=tag, token=token)
238
+
239
+
229
240
  @router.get("/focus")
230
241
  def focus_view(tag: str) -> dict:
231
242
  ontology = get_ontology()
@@ -422,8 +433,7 @@ def list_tags(q: str, limit: int) -> dict:
422
433
 
423
434
  if needle == "":
424
435
  ordered = sorted(tags, key=lambda tag: (-tag_counts.get(tag, 0), tag))
425
- if limit > 0:
426
- ordered = ordered[:limit]
436
+ ordered = ordered[:limit]
427
437
  payload = [
428
438
  {"tag": tag, "count": tag_counts.get(tag, 0)}
429
439
  for tag in ordered
@@ -446,8 +456,7 @@ def list_tags(q: str, limit: int) -> dict:
446
456
 
447
457
  matches.sort(key=lambda item: (item[0], item[1], item[2]))
448
458
  results = [item[2] for item in matches]
449
- if limit > 0:
450
- results = results[:limit]
459
+ results = results[:limit]
451
460
 
452
461
  payload = [
453
462
  {"tag": tag, "count": tag_counts.get(tag, 0)}
@@ -500,9 +500,8 @@ def _render_plain_url_anchor(*, text: str, link_text: str, href_value: str) -> s
500
500
  if stripped != link_text:
501
501
  return f'<a href="{href_value}" target="_blank" rel="noopener noreferrer">{link_text}</a>'
502
502
 
503
- title = link_title_store.get_ok_title(link_text)
504
- if title is None:
505
- link_title_store.maybe_enqueue_fetch(link_text)
503
+ title_html = render_standalone_link_title_html(link_text)
504
+ if title_html is None:
506
505
  diagnostic = link_title_store.get_diagnostic(link_text)
507
506
  diagnostic_title_attr = ""
508
507
  if diagnostic is not None:
@@ -513,14 +512,38 @@ def _render_plain_url_anchor(*, text: str, link_text: str, href_value: str) -> s
513
512
  f'target="_blank" rel="noopener noreferrer">{link_text}</a>'
514
513
  )
515
514
 
516
- escaped_title = html.escape(title)
517
- escaped_domain = html.escape(display_domain_for_url(link_text))
518
515
  return (
519
516
  f'<a class="link-title" href="{href_value}" title="{href_value}" '
520
517
  'target="_blank" rel="noopener noreferrer">'
518
+ f"{title_html}"
519
+ "</a>"
520
+ )
521
+
522
+
523
+ def render_standalone_link_title_html(text: str) -> str | None:
524
+ if not isinstance(text, str):
525
+ raise TypeError("text must be a string")
526
+ stripped = text.strip()
527
+ if stripped == "":
528
+ return None
529
+
530
+ match = _PLAIN_URL_RE.fullmatch(stripped)
531
+ if match is None:
532
+ return None
533
+ link_text, trailing_suffix = _split_trailing_url_punctuation(match.group(0))
534
+ if link_text != stripped or trailing_suffix != "":
535
+ return None
536
+
537
+ title = link_title_store.get_ok_title(link_text)
538
+ if title is None:
539
+ link_title_store.maybe_enqueue_fetch(link_text)
540
+ return None
541
+
542
+ escaped_title = html.escape(title)
543
+ escaped_domain = html.escape(display_domain_for_url(link_text))
544
+ return (
521
545
  f'<span class="link-title-text">{escaped_title}</span>'
522
546
  f'<span class="link-title-domain"> · {escaped_domain}</span>'
523
- "</a>"
524
547
  )
525
548
 
526
549
 
@@ -8,6 +8,7 @@ from typing import Callable, FrozenSet, List, Optional, Tuple
8
8
  from app.services.content_formatting import find_consumed_content_wrapper_keys
9
9
  from app.services.content_formatting import find_global_credential_tag
10
10
  from app.services.content_formatting import format_note_content_for_view
11
+ from app.services.content_formatting import render_standalone_link_title_html
11
12
  from app.services.inline_image_occurrences import annotate_inline_image_occurrences
12
13
  from app.services.remote_image_proxy import (
13
14
  remote_image_proxy_registry,
@@ -630,23 +631,27 @@ def _render_link_body(
630
631
  )
631
632
  if is_password_preview:
632
633
  preview = "X" * len(preview)
633
- escaped_preview = html.escape(preview)
634
+ preview_html = None
635
+ if not is_password_preview:
636
+ preview_html = render_standalone_link_title_html(preview)
637
+ if preview_html is None:
638
+ preview_html = html.escape(preview)
634
639
  if static_export:
635
640
  if is_password_preview:
636
641
  return (
637
642
  '<span class="note-reference-link note-reference-link-static meta-credential-password">'
638
- f'<span class="meta-credential-value">{escaped_preview}</span>'
643
+ f'<span class="meta-credential-value">{preview_html}</span>'
639
644
  "</span>"
640
645
  )
641
646
  return (
642
647
  f'<span class="note-reference-link note-reference-link-static">'
643
- f"{escaped_preview}"
648
+ f"{preview_html}"
644
649
  "</span>"
645
650
  )
646
651
  return (
647
652
  f'<a href="#" class="note-reference-link" data-ref-note-id="{escaped_note_id}">'
648
653
  '<span class="note-reference-link-icon" aria-hidden="true" title="Link to reference source">&#8599;</span>'
649
- f'<span class="note-reference-link-title">{escaped_preview}</span>'
654
+ f'<span class="note-reference-link-title">{preview_html}</span>'
650
655
  "</a>"
651
656
  )
652
657
 
@@ -532,6 +532,47 @@ def rename_tag_everywhere(*, old: str, new: str, token: str) -> None:
532
532
  _upsert_state_locked(rules=updated_rows, plaintext_by_id=updated_plaintext)
533
533
 
534
534
 
535
+ def delete_tag_everywhere(*, tag: str) -> int:
536
+ if not isinstance(tag, str) or tag.strip() == "":
537
+ raise TypeError("tag must be a non-empty string")
538
+
539
+ normalized = tag.strip()
540
+ with _LOCK:
541
+ state = _STATE
542
+ if state is None:
543
+ raise RuntimeError("Ontology rules store not bootstrapped")
544
+ if not state.is_decrypted:
545
+ raise RuntimeError("Ontology rules not decrypted yet")
546
+
547
+ deleted_rule_ids: list[int] = []
548
+ for rule_id, line in state.plaintext_by_id.items():
549
+ rules = parse_rules_text(text=f"{line}\n", filename=f"ontology_rules:{rule_id}")
550
+ references_tag = any(
551
+ rule.rhs == normalized
552
+ or any(isinstance(atom, TagAtom) and atom.tag == normalized for atom in rule.lhs)
553
+ for rule in rules
554
+ )
555
+ if references_tag:
556
+ deleted_rule_ids.append(rule_id)
557
+
558
+ if not deleted_rule_ids:
559
+ return 0
560
+
561
+ with begin_writer() as connection:
562
+ for rule_id in deleted_rule_ids:
563
+ db_delete_rule(connection, rule_id)
564
+
565
+ deleted_rule_id_set = set(deleted_rule_ids)
566
+ updated_rows = [row for row in state.rules if row.id not in deleted_rule_id_set]
567
+ updated_plaintext = {
568
+ rule_id: line
569
+ for rule_id, line in state.plaintext_by_id.items()
570
+ if rule_id not in deleted_rule_id_set
571
+ }
572
+ _upsert_state_locked(rules=updated_rows, plaintext_by_id=updated_plaintext)
573
+ return len(deleted_rule_ids)
574
+
575
+
535
576
  def extract_ontology_tags(ontology: TagOntology) -> set[str]:
536
577
  tags: set[str] = set()
537
578
  for src, outs in ontology.implication_out_edges.items():
@@ -5,6 +5,83 @@ import re
5
5
  from app.services.content_formatting import _unwrap_tag_token
6
6
 
7
7
 
8
+ def delete_tag_from_tag_bar(*, tags: str, tag: str) -> tuple[str, bool]:
9
+ if not isinstance(tags, str):
10
+ raise TypeError('tags must be a string')
11
+ if not isinstance(tag, str) or tag == '':
12
+ raise TypeError('tag must be a non-empty string')
13
+
14
+ out = ''
15
+ changed = False
16
+ index = 0
17
+ while index < len(tags):
18
+ if tags.startswith('/*', index):
19
+ end = tags.find('*/', index + 2)
20
+ if end == -1:
21
+ out += tags[index:]
22
+ break
23
+ out += tags[index : end + 2]
24
+ index = end + 2
25
+ continue
26
+
27
+ ch = tags[index]
28
+ if ch.isspace():
29
+ out += ch
30
+ index += 1
31
+ continue
32
+
33
+ start = index
34
+ opener = tags[index]
35
+ token_end = None
36
+
37
+ if opener in {'[', '{', '('}:
38
+ opener_run = 1
39
+ while index + opener_run < len(tags) and tags[index + opener_run] == opener:
40
+ opener_run += 1
41
+ if opener_run <= 3:
42
+ closer = {"[": "]", "{": "}", "(": ")"}[opener]
43
+ needle = closer * opener_run
44
+ close_at = tags.find(needle, index + opener_run)
45
+ if close_at != -1:
46
+ token_end = close_at + opener_run
47
+
48
+ if token_end is None:
49
+ token_end = start
50
+ while token_end < len(tags) and not tags[token_end].isspace():
51
+ token_end += 1
52
+
53
+ token = tags[start:token_end]
54
+ base, wrapper = _unwrap_tag_token(token)
55
+
56
+ if wrapper is None:
57
+ if base == tag:
58
+ changed = True
59
+ else:
60
+ out += token
61
+ else:
62
+ remaining = _delete_inner_token(inner=base, tag=tag)
63
+ if remaining != base:
64
+ changed = True
65
+ if remaining != '':
66
+ opener_char, depth = wrapper
67
+ closer_char = {"[": "]", "{": "}", "(": ")"}[opener_char]
68
+ out += (opener_char * depth) + remaining + (closer_char * depth)
69
+ else:
70
+ out += token
71
+
72
+ index = token_end
73
+
74
+ return out, changed
75
+
76
+
77
+ def _delete_inner_token(*, inner: str, tag: str) -> str:
78
+ parts = re.split(r'\s+', inner.strip())
79
+ remaining = [part for part in parts if part != tag]
80
+ if len(remaining) == len(parts):
81
+ return inner
82
+ return ' '.join(remaining)
83
+
84
+
8
85
  def rename_tag_in_tag_bar(*, tags: str, old: str, new: str) -> tuple[str, bool]:
9
86
  if not isinstance(tags, str):
10
87
  raise TypeError('tags must be a string')