diff --git a/.gitignore b/.gitignore index 7c4bd7b..ca83437 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*~ output/ .packages/ .DS_Store diff --git a/20260101143401-actual_self_hosted.org b/20260101143401-actual_self_hosted.org new file mode 100644 index 0000000..0b095bd --- /dev/null +++ b/20260101143401-actual_self_hosted.org @@ -0,0 +1,16 @@ +:PROPERTIES: +:ID: effa2bf5-8b04-42d3-b9c1-17160dc4ddc2 +:END: +#+title: Actual +#+filetags: :server:self-hosting:finance: + +In order to update the balance, I have decided for the moment to export as ~csv~ the monthly transactions from Halifax. Place the file into the ~~/master-folder/attachments/bank-statements/~ folder and name it as ~halifax-YYYY-MM.csv~, where ~YYYY~ is the four-digit year and ~MM~ is the two-digit month. + +Then run the following command in the terminal whilst being in the ~~/master-folder/projects/scripts/~ directory: + +#+begin_src python + python3 clean-halifax-actual.py ../../attachments/bank-statements/halifax-YYYY-MM.csv ../../attachments/bank-statements/halifax-YYYY-MM-cleaned.csv + +#+end_src + +Then you can go to the website ~https://actual.zainezq.com/~ and upload the cleaned file to update the balance. diff --git a/20260101194248-gitea.org b/20260101194248-gitea.org new file mode 100644 index 0000000..2e4d7a4 --- /dev/null +++ b/20260101194248-gitea.org @@ -0,0 +1,23 @@ +:PROPERTIES: +:ID: 74ec625c-3559-4570-8f6e-8272f4859ea7 +:END: +#+title: gitea + + +In order to connect to the gitea server and run git commands, you will need to do the following: + +Run ~cat ~/.ssh/id_ed25519.pub~ + +Copy that key and add it to the ssh keys in gitea + +ssh-keygen -t ed25519 -C "windows-gitea" + +ssh -T -p 222 git@192.168.0.241 + +Check the remote url of the git project. + +git remote -v + +change it to: + +git remote set-url origin git@ diff --git a/all-files.json b/all-files.json new file mode 100644 index 0000000..d3a121b --- /dev/null +++ b/all-files.json @@ -0,0 +1,625 @@ +{ + "title": "All Files", + "description": "A complete alphabetical index of all published pages.", + "groups": { + "A": [ + { + "id": "effa2bf5-8b04-42d3-b9c1-17160dc4ddc2", + "title": "Actual", + "url": "/20260101143401-actual_self_hosted.html" + }, + { + "id": "3acffb66-bc1a-4661-904f-c5447b3c3488", + "title": "advanced-networking", + "url": "/20250723184233-advanced_networking.html" + }, + { + "id": "556d10d1-1c74-4d9f-a398-39cb3bd5d935", + "title": "afp", + "url": "/20250120110833-afp.html" + }, + { + "id": "f6c9e1a7-8465-4cef-9481-2b803d0c43d4", + "title": "afp_lab_1", + "url": "/20250120113936-afp_lab_1.html" + }, + { + "id": "3aef24fd-b220-4408-aa1e-c3538d661b62", + "title": "afp_lec_1", + "url": "/20250121110241-afp_lec_1.html" + }, + { + "id": "460f4a49-8ae4-444a-bf82-4e14ca7cad3f", + "title": "afp_lec_2", + "url": "/20250128111008-afp_lec_2.html" + }, + { + "id": "ed4c372b-0314-4b6e-9119-742f69b5e434", + "title": "afp_lec_5", + "url": "/20250218110346-afp_lec_5.html" + }, + { + "id": "6c272430-aff5-468b-90d3-5ff3a96152cf", + "title": "afp_week1", + "url": "/20250120111047-afp_week1.html" + }, + { + "id": "4bc71106-1d2b-4c71-836d-54b738fe5ff5", + "title": "afp_week2", + "url": "/20250128110828-afp_week2.html" + }, + { + "id": "1f395b8c-cf55-43eb-9430-dd9449f6b575", + "title": "afp_week5", + "url": "/20250218110239-afp_week5.html" + }, + { + "id": "c6cf8f7a-778f-4e83-b607-753ef8dbb3f1", + "title": "Airflow", + "url": "/20251229180039-airflow.html" + }, + { + "id": "3b16e19a-62f0-4705-a451-a8790181941f", + "title": "Airflow Dags", + "url": "/20251229180249-airflow_dags.html" + }, + { + "id": "1ea42d73-3cd1-4cac-a6ee-028de21d08d5", + "title": "Airflow Tasks", + "url": "/20251229180156-airflow_tasks.html" + }, + { + "id": "e7f2302b-16eb-476d-a7b9-be12f077819d", + "title": "AOC Notes", + "url": "/20241210001150-aoc_notes.html" + } + ], + "B": [ + { + "id": "580cc3a5-af8e-4cbe-b5ad-5b06680e6c37", + "title": "Backlog", + "url": "/20251101123637-backlog.html" + }, + { + "id": "275988a8-59d8-40c8-a8b4-47118d6eb834", + "title": "big-o-complexity", + "url": "/20250804201706-big_o_complexity.html" + }, + { + "id": "238ff7d8-db22-41e2-8aad-fc3c778e6248", + "title": "book-recs", + "url": "/20250727174903-book_recs.html" + }, + { + "id": "2706598f-e6aa-4e88-8d24-5f699bd22787", + "title": "book_notes", + "url": "/20241231172511-book_notes.html" + }, + { + "id": "63314cff-3a3f-49b4-9e76-4a359c51f55f", + "title": "Books MOC", + "url": "/20250727174809-books_moc.html" + }, + { + "id": "363dbdfa-f23c-4f7e-a6f3-6d34f78984bb", + "title": "books-org-agenda", + "url": "/20250724230557-books_org_agenda.html" + }, + { + "id": "bca8e7a6-0590-4630-ab49-210306ad21a2", + "title": "bowling-kata", + "url": "/20250723185943-bowling_kata.html" + }, + { + "id": "b2fb976a-c23c-4275-8a53-da343c223b97", + "title": "Brain MOC", + "url": "/20241210233721-brain_moc.html" + } + ], + "C": [ + { + "id": "5a207a1c-6f02-40d5-b42e-38daaa0aec10", + "title": "c_notes", + "url": "/20241213005125-c_notes.html" + }, + { + "id": "f9838952-9753-471b-a2cc-d72e01a53ef6", + "title": "career_capital", + "url": "/20250723183655-career_capital.html" + }, + { + "id": "dd04d228-fff5-402a-929d-9d113a2ec965", + "title": "career_moc", + "url": "/20250722221649-career_moc.html" + }, + { + "id": "dd55d635-59de-4ed9-8ff0-423782c2e0ae", + "title": "clean-code", + "url": "/20250727221512-clean_code.html" + }, + { + "id": "22737796-6D31-49D5-84F2-F7BC73E45144", + "title": "Concepts", + "url": "/20260101010049-concepts.html" + } + ], + "D": [ + { + "id": "e448cd99-afee-4702-947f-644bb34dc1aa", + "title": "Database MOC", + "url": "/20250727122406-database_moc.html" + }, + { + "id": "d4f96bfb-b83d-449b-9f74-f602a1a3c2d3", + "title": "deliberate_practice", + "url": "/20250723183755-deliberate_practice.html" + }, + { + "id": "631b2086-4b8f-4fe3-829d-be1dc014e293", + "title": "Design patterns", + "url": "/20251223215636-design_patterns_notes.html" + } + ], + "E": [ + { + "id": "7e79e4c5-383d-450f-882c-33d4f87ba1b5", + "title": "emacs-stuff-elisp", + "url": "/20250326002128-emacs_stuff_elisp.html" + }, + { + "id": "45CC3AF5-5E20-4B03-A36C-8D4BDD5CBB13", + "title": "emacs-stuff-evil", + "url": "/20250420012258-emacs_stuff_evil.html" + }, + { + "id": "8e5e9498-ff3c-48e7-aab5-6e94b2e41ccb", + "title": "emacs-stuff-gtd", + "url": "/20241210004453-gtd.html" + }, + { + "id": "966175d4-3b58-4abc-9b41-08cbf328dd87", + "title": "emacs-stuff-keybindings", + "url": "/20250218174735-emacs_stuff_keybindings.html" + }, + { + "id": "2ab0fa3f-8ac6-4af2-8cd4-1dd490fb19c3", + "title": "emacs-stuff-magit", + "url": "/20250329231658-emacs_stuff_magit.html" + }, + { + "id": "7d2e867e-f091-4362-a583-453f732207fe", + "title": "emacs-stuff-org-publish", + "url": "/20250806155335-emacs_stuff_org_publish.html" + }, + { + "id": "034abe27-ca14-4dc0-9a3f-b8d0e1f26342", + "title": "emacs-stuff-org-roam", + "url": "/20241210004329-org_roam.html" + }, + { + "id": "8fa3f476-6152-45f4-b618-50f1e4bce46c", + "title": "emacs_moc", + "url": "/20241210004247-emacs_stuff.html" + } + ], + "F": [ + { + "id": "7d199fbe-b0e7-48fd-b8a1-793044dbea01", + "title": "fyp", + "url": "/20241210012703-fyp.html" + }, + { + "id": "26b2ed9a-cb81-4c43-bc63-6b3c8ffa3bf1", + "title": "fyp-report-planning", + "url": "/20250403120140-fyp_report_planning.html" + } + ], + "G": [ + { + "id": "74ec625c-3559-4570-8f6e-8272f4859ea7", + "title": "gitea", + "url": "/20260101194248-gitea.html" + }, + { + "id": "710f65e5-0bd4-42be-b5d1-69dbe79b745e", + "title": "github_notes", + "url": "/20241220234456-github_notes.html" + }, + { + "id": "30c28e5e-0b1c-43ae-b3bd-eb31023f8b73", + "title": "gpg-encryption", + "url": "/20250516161728-gpg_encryption.html" + } + ], + "H": [ + { + "id": "347d2663-515b-4d9a-9ee9-7706ee86a845", + "title": "haskell_notes", + "url": "/20241212013207-haskell_notes.html" + }, + { + "id": "dc9ece84-0b14-4afd-b25a-786cf1618996", + "title": "HFDP", + "url": "/Head First Design Patterns.html" + }, + { + "id": "086ca3ca-39ec-4d37-b56d-b6d9f51e6873", + "title": "how-to-solve-leetcode", + "url": "/20250804212215-how_to_solve_leetcode.html" + } + ], + "I": [ + { + "id": "9d5aae0f-4ae1-49a5-a047-9099baad0a06", + "title": "i3-wm", + "url": "/20250213124335-i3_wm.html" + }, + { + "id": "DE792A73-FD00-4048-82D8-AB6E84E869F2", + "title": "Index", + "url": "/index.html" + }, + { + "id": "c69e4c4d-2fb4-4cf1-a835-a235cf6db8e9", + "title": "ise", + "url": "/20250329114733-ise.html" + }, + { + "id": "06b2a012-4e8a-4a8a-9494-de7ed9fbe1d3", + "title": "ise_week_1", + "url": "/20250329114848-ise_week_1.html" + }, + { + "id": "f308642d-fcf3-410b-b154-d60582e112a2", + "title": "ise_week_2", + "url": "/20250329121843-ise_week_2.html" + }, + { + "id": "1d0fa257-579f-49f3-b8fd-a3b68ddccf10", + "title": "ise_week_3", + "url": "/20250329142725-ise_week_3.html" + }, + { + "id": "ebf874d9-0554-47f0-be8b-5c9a948738bf", + "title": "ise_week_4", + "url": "/20250329200158-ise_week_4.html" + }, + { + "id": "0e70c535-b145-42d9-a9ed-fe48cddbb1a5", + "title": "ise_week_5", + "url": "/20250331201944-ise_week_5.html" + }, + { + "id": "9ad3f3f1-55f7-4114-bc8c-17250b6dd25d", + "title": "ise_week_7", + "url": "/20250331202447-ise_week_7.html" + } + ], + "J": [ + { + "id": "7b8de14c-a73e-4c92-a403-a9a1c419c0b3", + "title": "java-junit-testing", + "url": "/20250723190656-java_junit_testing.html" + }, + { + "id": "5cfd7f6f-f5ac-4f18-90f9-be9a31dd238e", + "title": "java-portswrigger-test", + "url": "/20250723190203-java_portswrigger_test.html" + }, + { + "id": "ae343652-96fe-4341-8a36-ec3a1abd0dc6", + "title": "java_moc", + "url": "/20250402185735-technical_java_notes.html" + }, + { + "id": "f9897f8e-2b63-4ad2-a55f-3787c4ac235f", + "title": "job_application_cover_letters", + "url": "/20241211161232- job_application_cover_letters.html" + } + ], + "K": [ + { + "id": "0217f537-442a-4593-8c69-d481f0d1f2a8", + "title": "keyboard", + "url": "/20251122223053-keyboard.html" + } + ], + "L": [ + { + "id": "63456626-b34e-46d9-b85e-0f1f5724aa83", + "title": "lazy_evaluation", + "url": "/20241212013902-lazy_evaluation.html" + }, + { + "id": "93a43a24-6861-40c4-b45b-581977bb55cf", + "title": "leetcode-arrays", + "url": "/20250804212606-leetcode_arrays.html" + }, + { + "id": "9d1cfccc-8da7-41a3-b435-9857f0abe441", + "title": "leetcode_notes", + "url": "/20241210001206-leetcode_notes.html" + }, + { + "id": "569a4a57-1843-4821-8259-17762855985e", + "title": "linux-arch-linux", + "url": "/20250703183239-linux_arch_linux.html" + }, + { + "id": "bdb493df-db92-4c93-9558-0b10fdff3048", + "title": "linux_moc", + "url": "/20250417173809-linux_moc.html" + } + ], + "M": [ + { + "id": "bcd41e87-120c-455c-8898-996ddaa41f75", + "title": "maven-pom-file", + "url": "/20250723171109-maven_pom_file.html" + }, + { + "id": "ABF4A0BE-0309-48A6-92ED-76031B3D2F86", + "title": "Microlise MOC", + "url": "/20251002154125-microlise_moc.html" + }, + { + "id": "f877240e-c2c8-4087-84e5-4b1ca3fcd4ed", + "title": "microlise-assessment", + "url": "/20250430001952-microlise_assessment.html" + }, + { + "id": "08415f5c-986e-45a6-8ea1-f3bedcc996f0", + "title": "misc_moc", + "url": "/20250918120519-misc_moc.html" + } + ], + "N": [ + { + "id": "4426cc9a-1568-4fc8-9242-269654c43a3b", + "title": "naqshe-hayat", + "url": "/20250819174119-naqshe_hayat.html" + }, + { + "id": "0880f089-a5ad-49cd-8ce3-f020a5941313", + "title": "networking-moc", + "url": "/20250727121051-networking_moc.html" + }, + { + "id": "a087da71-bcfb-4ddf-9565-b82113d5d27f", + "title": "neuroplasticity", + "url": "/20250723185056-neuroplasticity.html" + }, + { + "id": "56f39be4-1108-4020-be5a-1f3a0fbf96fa", + "title": "nextcloud", + "url": "/20250727120306-nextcloud.html" + }, + { + "id": "565eaccd-8cf6-4dbb-bc66-a4b37367ce6b", + "title": "non_technical_moc", + "url": "/20250806111925-non_technical_moc.html" + } + ], + "O": [ + { + "id": "2c2d8df4-ad36-40ab-9f30-8a047b372956", + "title": "old_nextcloud_server_code", + "url": "/20251019114758-old_nextcloud_server_code.html" + }, + { + "id": "a9829b5d-690d-4a21-ba94-ac8beac4d439", + "title": "old_nginx_code", + "url": "/20251109205925-old_nginx_code.html" + } + ], + "P": [ + { + "id": "939e301b-6463-46a8-b57e-0af606e7e7ef", + "title": "Postgres", + "url": "/20250723200800-postgres.html" + }, + { + "id": "2BFB84B2-2129-4AE3-8E69-290CA5BF9747", + "title": "pre_work_prep_microlise", + "url": "/20251002154204-pre_work_prep_microlise.html" + }, + { + "id": "125c81dc-c14f-4b4d-93c6-0a2b157735ac", + "title": "python-dictionary", + "url": "/20250805141906-python_dictionary.html" + }, + { + "id": "9d534e89-7f0b-494c-bff6-7b3be05b85d1", + "title": "python-lambda", + "url": "/20250805143741-python_lambda.html" + }, + { + "id": "3a41407c-661e-416a-80d2-4c7a137d153a", + "title": "python-set", + "url": "/20250804214537-python_set.html" + }, + { + "id": "3bbc6099-0187-4bf2-9282-97e5fa443f72", + "title": "python-sorted-function", + "url": "/20250805143427-python_sorted_function.html" + } + ], + "R": [ + { + "id": "EA93341B-20C0-48A2-BD88-F24ED3C540DA", + "title": "recipes-done", + "url": "/20250719175023-recipes_done.html" + }, + { + "id": "F7D68FF4-CAD0-4791-BAE4-AC20B84A8785", + "title": "recipes-ideas", + "url": "/20250719174944-recipes_ideas.html" + }, + { + "id": "65F747B1-3CB2-429A-9E26-ED8BC169E689", + "title": "recipes-main", + "url": "/20250717230336-recipes_moc.html" + } + ], + "S": [ + { + "id": "99533f2d-a4e8-41d0-a605-c7d4cef6f995", + "title": "self_hosting", + "url": "/20250723190927-self_hosting.html" + }, + { + "id": "f09cb4ed-1407-4187-9002-de2c5db13a8f", + "title": "server_moc", + "url": "/20251019114736-server_moc.html" + }, + { + "id": "2d7f1ccc-99d7-4c45-8fe7-4b87080edb01", + "title": "so_good_they_cant_ignore_you", + "url": "/20250723182408-so_good_they_cant_ignore_you.html" + }, + { + "id": "efe0360d-8d81-4372-833d-ad58e67d17c6", + "title": "socket_programming_in_c", + "url": "/20241213005156-socket_programming_in_c.html" + }, + { + "id": "6820973F-613E-441A-BC1D-8FE5CD9BD6F7", + "title": "solid_principles", + "url": "/20260101012549-solid_principles.html" + }, + { + "id": "F3875F0F-5C9E-4BB1-A79C-6000B9558115", + "title": "solid_principles_examples", + "url": "/20260101012731-solid_principles_examples.html" + }, + { + "id": "acba0d25-08db-4784-8cc2-fe5c437ba723", + "title": "stanford_marshmallow_experiment", + "url": "/20250723184430-stanford_marshmallow_experiment.html" + }, + { + "id": "bf277242-4f09-46a2-aa6b-1d75ce0025ac", + "title": "systemd_services", + "url": "/20250428133236-systemd_services.html" + } + ], + "T": [ + { + "id": "37495d5f-2a77-40bc-b45c-8163189bbe6b", + "title": "technical-commonplace", + "url": "/20251223220531-technical_commonplace.html" + }, + { + "id": "2f285f04-fcf4-4ade-a1ac-2c50b43d529a", + "title": "technical_moc", + "url": "/20241210001045-technical_moc.html" + }, + { + "id": "2729599d-ae2b-4f22-b73d-bf22d81e0767", + "title": "Test Driven Development", + "url": "/20250723185829-test_driven_development.html" + }, + { + "id": "EC9D851F-3A2E-4F32-A584-76F6F7A08E30", + "title": "the_clean_coder", + "url": "/20250715223949-the_clean_coder.html" + }, + { + "id": "455ef38f-9a5f-4f62-afe9-25e2261e1282", + "title": "the_science_of_self_discipline", + "url": "/20241231172543-the_science_of_self_discipline.html" + }, + { + "id": "5443ed1c-bb7f-4eb4-9c96-d12648dd2291", + "title": "tpis", + "url": "/20241210152713-tpis.html" + } + ], + "U": [ + { + "id": "4a8edaed-9ebd-402b-9c5f-7a0cb4399102", + "title": "uml_fyp", + "url": "/20241210232054-uml_fyp.html" + }, + { + "id": "797d6e3e-98eb-4bc7-88b6-e096ef7306ad", + "title": "uni_moc", + "url": "/20241210152650-uni_moc.html" + }, + { + "id": "d939e477-d1e9-43ea-960e-8727246d12a3", + "title": "useful-c-imports", + "url": "/20251214210526-useful_c_imports.html" + } + ], + "W": [ + { + "id": "7612a9a6-ae70-4525-93a0-81bac857df39", + "title": "wacom-notes", + "url": "/20250417173821-wacom_notes.html" + }, + { + "id": "348df473-6443-4f4a-b366-95397b574989", + "title": "web-port-notes", + "url": "/20241217234535-web_port_notes.html" + }, + { + "id": "c1de3972-e932-48fd-8065-3d89dad58007", + "title": "wedding_moc", + "url": "/20250918120706-wedding_moc.html" + }, + { + "id": "8CE93986-280B-45BD-9DF2-5D06586DDDE7", + "title": "workflow-moc", + "url": "/20250926151524-workflow_moc.html" + }, + { + "id": "b2db0b0b-c179-43ab-9e2b-22bbaac69bcb", + "title": "wp-emacs-config-blorg", + "url": "/20241217234944-wp_emacs_config_blorg.html" + }, + { + "id": "D02B89DC-84D0-4211-A902-B9399F4179CA", + "title": "wp-emotional-intelligence", + "url": "/20250314230952-wp_emotional_intelligence.html" + }, + { + "id": "CD093B85-BF68-4EAB-AABE-733C7BFC99DE", + "title": "wp-growth-mindset", + "url": "/20250314223811-wp_growth_mindset.html" + }, + { + "id": "1ee754f9-f30f-4976-850b-d18d01a834d2", + "title": "wp-new-emacs-config-blorg", + "url": "/20250214155617-wp_new_emacs_config_blorg.html" + }, + { + "id": "b292f5c6-0c27-439c-8274-2150eb45e20d", + "title": "wp-prefront-cortex-blorg", + "url": "/20250111213016-wp_prefront_cortex_blog.html" + }, + { + "id": "462F091B-9156-48B3-8665-0BE36C95C182", + "title": "wp-sadness", + "url": "/20250412234351-wp_sadness.html" + }, + { + "id": "cfc4ce06-7862-49b7-9a4f-e515d690cd38", + "title": "wp-urge-surfing-blorg", + "url": "/20250226184629-wp_urge_surfing_blorg.html" + }, + { + "id": "8CD2F4C4-22C2-4ECC-8F5F-C4779F8AC0F1", + "title": "wp-week-12-reflection", + "url": "/20250324041724-wp_week_12_reflections.html" + } + ], + "X": [ + { + "id": "F32F8F09-3DEC-4FD1-8CFA-401A316E906B", + "title": "xor", + "url": "/20260101011126-xor.html" + } + ] + } +} \ No newline at end of file diff --git a/search-index.py b/search-index.py new file mode 100644 index 0000000..8d54e89 --- /dev/null +++ b/search-index.py @@ -0,0 +1,112 @@ +import json +import re +from pathlib import Path + +def get_org_id_and_title(file_path): + """Extract ID and TITLE from an Org file.""" + id_pattern = re.compile(r"^:ID:\s*(.+)", re.MULTILINE) + title_pattern = re.compile(r"^#\+title:\s*(.+)", re.IGNORECASE | re.MULTILINE) + + content = file_path.read_text(encoding="utf-8", errors="ignore") + + id_match = id_pattern.search(content) + title_match = title_pattern.search(content) + + org_id = id_match.group(1).strip() if id_match else None + title = title_match.group(1).strip() if title_match else "Untitled" + + return org_id, title + + +def generate_search_index(org_dir, out_file): + """Generate search-index.json with title, url, and id.""" + print("🔍 Generating search-index.json...") + + org_dir = Path(org_dir).expanduser() + out_file = Path(out_file).expanduser() + + # Recursively find all .org files (excluding Emacs lockfiles like .#foo.org) + org_files = [ + f for f in org_dir.rglob("*.org") + if not re.search(r"/\.#[^/]+\.org$", str(f)) + ] + + index = [] + for file_path in org_files: + org_id, title = get_org_id_and_title(file_path) + if org_id: + index.append({ + "title": title, + "url": f"/{file_path.stem}.html", + "id": org_id + }) + + # De-duplicate by ID + seen_ids = set() + unique_index = [] + for entry in index: + if entry["id"] not in seen_ids: + unique_index.append(entry) + seen_ids.add(entry["id"]) + + # Ensure output directory exists + out_file.parent.mkdir(parents=True, exist_ok=True) + + # Write JSON + with open(out_file, "w", encoding="utf-8") as f: + json.dump(unique_index, f, ensure_ascii=False, indent=2) + + print(f"✅ search-index.json generated ({len(unique_index)} entries).") + + +def generate_all_files_json(search_index_file, out_file): + """Generate all-files.json from search-index.json.""" + search_index_file = Path(search_index_file).expanduser() + out_file = Path(out_file).expanduser() + + # Load data + with open(search_index_file, "r", encoding="utf-8") as f: + data = json.load(f) + + print(f"🔎 Loaded {len(data)} entries from {search_index_file}") + + # Sort alphabetically + data.sort(key=lambda x: x.get("title", "").lower()) + + # Group by first letter + grouped = {} + for entry in data: + title = entry.get("title", "") + if not title: + continue + letter = title[0].upper() + grouped.setdefault(letter, []).append({ + "id": entry["id"], + "title": title, + "url": entry["url"] + }) + + # Output structure + output = { + "title": "All Files", + "description": "A complete alphabetical index of all published pages.", + "groups": grouped, + } + + with open(out_file, "w", encoding="utf-8") as f: + json.dump(output, f, ensure_ascii=False, indent=2) + + print(f"✅ all-files.json generated → {out_file}") + + +def main(): + base_dir = Path.home() / "master-folder" / "org_files" / "org_roam" + search_index = base_dir / "output" / "search-index.json" + all_files_json = base_dir / "all-files.json" + + generate_search_index(base_dir, search_index) + generate_all_files_json(search_index, all_files_json) + + +if __name__ == "__main__": + main()