mevebu 0.3.1 → 0.4.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 (178) hide show
  1. package/README.md +24 -8
  2. package/mevebu/app/mevebu.js +2 -2
  3. package/mevebu/libs/css/tools.css +103 -1
  4. package/mevebu/libs/js/core.js +1 -1
  5. package/mevebu/libs/js/icons.js +115 -1
  6. package/mevebu/libs/js/registry.js +3102 -0
  7. package/mevebu/libs/js/tools/abstract-checklist.js +54 -0
  8. package/mevebu/libs/js/tools/add-subtract-days.js +105 -0
  9. package/mevebu/libs/js/tools/age-calculator.js +108 -0
  10. package/mevebu/libs/js/tools/apa-reference.js +98 -0
  11. package/mevebu/libs/js/tools/api-request-builder.js +76 -0
  12. package/mevebu/libs/js/tools/area-converter.js +87 -0
  13. package/mevebu/libs/js/tools/aspect-ratio.js +81 -0
  14. package/mevebu/libs/js/tools/average-calculator.js +83 -0
  15. package/mevebu/libs/js/tools/bibliography-sorter.js +43 -0
  16. package/mevebu/libs/js/tools/bibtex-generator.js +98 -0
  17. package/mevebu/libs/js/tools/binary-calculator.js +58 -0
  18. package/mevebu/libs/js/tools/border-radius.js +88 -0
  19. package/mevebu/libs/js/tools/box-shadow.js +71 -0
  20. package/mevebu/libs/js/tools/branch-name.js +44 -0
  21. package/mevebu/libs/js/tools/break-even.js +68 -0
  22. package/mevebu/libs/js/tools/business-days.js +120 -0
  23. package/mevebu/libs/js/tools/canonical-tag.js +63 -0
  24. package/mevebu/libs/js/tools/caption-counter.js +66 -0
  25. package/mevebu/libs/js/tools/case-inspector.js +114 -0
  26. package/mevebu/libs/js/tools/cash-denomination.js +74 -0
  27. package/mevebu/libs/js/tools/cash-flow.js +124 -0
  28. package/mevebu/libs/js/tools/cert-expiry.js +83 -0
  29. package/mevebu/libs/js/tools/changelog-generator.js +48 -0
  30. package/mevebu/libs/js/tools/character-counter.js +80 -0
  31. package/mevebu/libs/js/tools/checklist.js +86 -0
  32. package/mevebu/libs/js/tools/citation-metadata.js +89 -0
  33. package/mevebu/libs/js/tools/citation-number-check.js +107 -0
  34. package/mevebu/libs/js/tools/color-palette.js +110 -0
  35. package/mevebu/libs/js/tools/color-picker.js +93 -0
  36. package/mevebu/libs/js/tools/commit-message.js +62 -0
  37. package/mevebu/libs/js/tools/content-calendar.js +111 -0
  38. package/mevebu/libs/js/tools/contrast-checker.js +93 -0
  39. package/mevebu/libs/js/tools/countdown-timer.js +174 -0
  40. package/mevebu/libs/js/tools/cron-builder.js +91 -0
  41. package/mevebu/libs/js/tools/css-clamp.js +66 -0
  42. package/mevebu/libs/js/tools/css-formatter.js +84 -0
  43. package/mevebu/libs/js/tools/css-grid.js +75 -0
  44. package/mevebu/libs/js/tools/css-minifier.js +98 -0
  45. package/mevebu/libs/js/tools/csv-to-json.js +114 -0
  46. package/mevebu/libs/js/tools/csv-viewer.js +132 -0
  47. package/mevebu/libs/js/tools/currency-format.js +69 -0
  48. package/mevebu/libs/js/tools/daily-planner.js +124 -0
  49. package/mevebu/libs/js/tools/data-masker.js +71 -0
  50. package/mevebu/libs/js/tools/data-storage.js +89 -0
  51. package/mevebu/libs/js/tools/data-validator.js +111 -0
  52. package/mevebu/libs/js/tools/date-difference.js +100 -0
  53. package/mevebu/libs/js/tools/date-format.js +107 -0
  54. package/mevebu/libs/js/tools/delimiter-converter.js +109 -0
  55. package/mevebu/libs/js/tools/discount-calculator.js +83 -0
  56. package/mevebu/libs/js/tools/doi-resolver.js +67 -0
  57. package/mevebu/libs/js/tools/env-formatter.js +72 -0
  58. package/mevebu/libs/js/tools/equation-formatter.js +71 -0
  59. package/mevebu/libs/js/tools/expense-split.js +90 -0
  60. package/mevebu/libs/js/tools/favicon-markup.js +53 -0
  61. package/mevebu/libs/js/tools/find-replace.js +88 -0
  62. package/mevebu/libs/js/tools/flashcard-creator.js +117 -0
  63. package/mevebu/libs/js/tools/font-pairing.js +88 -0
  64. package/mevebu/libs/js/tools/fraction-calculator.js +130 -0
  65. package/mevebu/libs/js/tools/git-command-builder.js +100 -0
  66. package/mevebu/libs/js/tools/gitignore-generator.js +60 -0
  67. package/mevebu/libs/js/tools/gpa-calculator.js +100 -0
  68. package/mevebu/libs/js/tools/grade-calculator.js +101 -0
  69. package/mevebu/libs/js/tools/gradient-generator.js +99 -0
  70. package/mevebu/libs/js/tools/habit-tracker.js +120 -0
  71. package/mevebu/libs/js/tools/harvard-citation.js +90 -0
  72. package/mevebu/libs/js/tools/hashtag-formatter.js +62 -0
  73. package/mevebu/libs/js/tools/heading-formatter.js +61 -0
  74. package/mevebu/libs/js/tools/hmac-generator.js +63 -0
  75. package/mevebu/libs/js/tools/hpp-calculator.js +70 -0
  76. package/mevebu/libs/js/tools/html-entity.js +49 -0
  77. package/mevebu/libs/js/tools/html-formatter.js +72 -0
  78. package/mevebu/libs/js/tools/html-to-text.js +47 -0
  79. package/mevebu/libs/js/tools/http-status.js +63 -0
  80. package/mevebu/libs/js/tools/ieee-reference.js +102 -0
  81. package/mevebu/libs/js/tools/intext-citation.js +75 -0
  82. package/mevebu/libs/js/tools/inventory-quantity.js +103 -0
  83. package/mevebu/libs/js/tools/invoice-number.js +64 -0
  84. package/mevebu/libs/js/tools/json-escape.js +76 -0
  85. package/mevebu/libs/js/tools/json-formatter.js +51 -0
  86. package/mevebu/libs/js/tools/json-minifier.js +58 -0
  87. package/mevebu/libs/js/tools/json-to-csv.js +72 -0
  88. package/mevebu/libs/js/tools/json-to-typescript.js +102 -0
  89. package/mevebu/libs/js/tools/json-validator.js +49 -0
  90. package/mevebu/libs/js/tools/jwt-decoder.js +74 -0
  91. package/mevebu/libs/js/tools/jwt-expiry.js +97 -0
  92. package/mevebu/libs/js/tools/length-converter.js +86 -0
  93. package/mevebu/libs/js/tools/license-reference.js +58 -0
  94. package/mevebu/libs/js/tools/line-break-formatter.js +48 -0
  95. package/mevebu/libs/js/tools/line-counter.js +55 -0
  96. package/mevebu/libs/js/tools/list-difference.js +86 -0
  97. package/mevebu/libs/js/tools/list-merger.js +67 -0
  98. package/mevebu/libs/js/tools/locale-number.js +79 -0
  99. package/mevebu/libs/js/tools/markdown-preview.js +143 -0
  100. package/mevebu/libs/js/tools/markdown-table.js +111 -0
  101. package/mevebu/libs/js/tools/markdown-to-text.js +48 -0
  102. package/mevebu/libs/js/tools/markup-calculator.js +69 -0
  103. package/mevebu/libs/js/tools/meeting-agenda.js +137 -0
  104. package/mevebu/libs/js/tools/meta-preview.js +51 -0
  105. package/mevebu/libs/js/tools/meta-tags.js +62 -0
  106. package/mevebu/libs/js/tools/mime-types.js +54 -0
  107. package/mevebu/libs/js/tools/mla-citation.js +91 -0
  108. package/mevebu/libs/js/tools/number-base-converter.js +97 -0
  109. package/mevebu/libs/js/tools/open-graph.js +62 -0
  110. package/mevebu/libs/js/tools/password-strength.js +118 -0
  111. package/mevebu/libs/js/tools/percent-to-fraction.js +96 -0
  112. package/mevebu/libs/js/tools/percentage-calculator.js +86 -0
  113. package/mevebu/libs/js/tools/percentage-change.js +70 -0
  114. package/mevebu/libs/js/tools/permutation-combination.js +106 -0
  115. package/mevebu/libs/js/tools/prefix-suffix.js +46 -0
  116. package/mevebu/libs/js/tools/priority-matrix.js +100 -0
  117. package/mevebu/libs/js/tools/profit-margin.js +69 -0
  118. package/mevebu/libs/js/tools/quadratic-solver.js +93 -0
  119. package/mevebu/libs/js/tools/query-builder.js +71 -0
  120. package/mevebu/libs/js/tools/quiz-formatter.js +70 -0
  121. package/mevebu/libs/js/tools/quotation-formatter.js +77 -0
  122. package/mevebu/libs/js/tools/ratio-calculator.js +103 -0
  123. package/mevebu/libs/js/tools/readability.js +112 -0
  124. package/mevebu/libs/js/tools/reading-time.js +76 -0
  125. package/mevebu/libs/js/tools/readme-generator.js +50 -0
  126. package/mevebu/libs/js/tools/reference-completeness.js +62 -0
  127. package/mevebu/libs/js/tools/regex-tester.js +86 -0
  128. package/mevebu/libs/js/tools/remove-duplicate-lines.js +46 -0
  129. package/mevebu/libs/js/tools/remove-extra-spaces.js +41 -0
  130. package/mevebu/libs/js/tools/robots-txt.js +60 -0
  131. package/mevebu/libs/js/tools/roman-numeral-converter.js +106 -0
  132. package/mevebu/libs/js/tools/sales-commission.js +96 -0
  133. package/mevebu/libs/js/tools/scientific-calculator.js +247 -0
  134. package/mevebu/libs/js/tools/scientific-notation.js +83 -0
  135. package/mevebu/libs/js/tools/script-planner.js +72 -0
  136. package/mevebu/libs/js/tools/secure-token.js +60 -0
  137. package/mevebu/libs/js/tools/selling-price.js +74 -0
  138. package/mevebu/libs/js/tools/semver-helper.js +54 -0
  139. package/mevebu/libs/js/tools/sentence-length.js +80 -0
  140. package/mevebu/libs/js/tools/sequence-analyzer.js +90 -0
  141. package/mevebu/libs/js/tools/sitemap-xml.js +82 -0
  142. package/mevebu/libs/js/tools/slug-converter.js +48 -0
  143. package/mevebu/libs/js/tools/slug-preview.js +83 -0
  144. package/mevebu/libs/js/tools/sort-lines.js +54 -0
  145. package/mevebu/libs/js/tools/speed-converter.js +83 -0
  146. package/mevebu/libs/js/tools/sql-formatter.js +78 -0
  147. package/mevebu/libs/js/tools/sql-minifier.js +102 -0
  148. package/mevebu/libs/js/tools/standard-deviation.js +96 -0
  149. package/mevebu/libs/js/tools/stopwatch.js +133 -0
  150. package/mevebu/libs/js/tools/study-schedule.js +88 -0
  151. package/mevebu/libs/js/tools/subtitle-formatter.js +74 -0
  152. package/mevebu/libs/js/tools/table-to-markdown.js +137 -0
  153. package/mevebu/libs/js/tools/tax-calculator.js +84 -0
  154. package/mevebu/libs/js/tools/temperature-converter.js +94 -0
  155. package/mevebu/libs/js/tools/text-diff.js +104 -0
  156. package/mevebu/libs/js/tools/text-direction.js +55 -0
  157. package/mevebu/libs/js/tools/text-reverser.js +51 -0
  158. package/mevebu/libs/js/tools/time-duration.js +83 -0
  159. package/mevebu/libs/js/tools/time-format-converter.js +86 -0
  160. package/mevebu/libs/js/tools/timestamp-converter.js +85 -0
  161. package/mevebu/libs/js/tools/timezone-converter.js +163 -0
  162. package/mevebu/libs/js/tools/title-length.js +67 -0
  163. package/mevebu/libs/js/tools/unicode-escape.js +80 -0
  164. package/mevebu/libs/js/tools/unicode-inspector.js +58 -0
  165. package/mevebu/libs/js/tools/url-inspector.js +98 -0
  166. package/mevebu/libs/js/tools/url-parser.js +83 -0
  167. package/mevebu/libs/js/tools/utf8-bytes.js +67 -0
  168. package/mevebu/libs/js/tools/version-compare.js +70 -0
  169. package/mevebu/libs/js/tools/video-duration.js +72 -0
  170. package/mevebu/libs/js/tools/volume-converter.js +88 -0
  171. package/mevebu/libs/js/tools/weekly-planner.js +101 -0
  172. package/mevebu/libs/js/tools/weight-converter.js +85 -0
  173. package/mevebu/libs/js/tools/weighted-average.js +86 -0
  174. package/mevebu/libs/js/tools/word-counter.js +90 -0
  175. package/mevebu/libs/js/tools/word-limit.js +60 -0
  176. package/mevebu/libs/js/tools/xml-formatter.js +85 -0
  177. package/mevebu/libs/js/tools/yaml-formatter.js +71 -0
  178. package/package.json +1 -1
@@ -9,6 +9,20 @@ export const CATEGORIES = [
9
9
  { id: "developer", name: "Developer", icon: "terminal" },
10
10
  { id: "convert", name: "Convert", icon: "repeat" },
11
11
  { id: "text", name: "Text and data", icon: "file-text" },
12
+ { id: "daily", name: "Daily use", icon: "calendar-days" },
13
+ { id: "math", name: "Math", icon: "calculator" },
14
+ { id: "datetime", name: "Date and time", icon: "clock" },
15
+ { id: "data", name: "Data and lists", icon: "table" },
16
+ { id: "design", name: "Design", icon: "swatch-book" },
17
+ { id: "seo", name: "Web and SEO", icon: "globe" },
18
+ { id: "academic", name: "Academic", icon: "graduation-cap" },
19
+ { id: "education", name: "Study", icon: "book-open" },
20
+ { id: "business", name: "Business", icon: "briefcase" },
21
+ { id: "encoding", name: "Encoding", icon: "code" },
22
+ { id: "locale", name: "Locale", icon: "languages" },
23
+ { id: "content", name: "Content", icon: "megaphone" },
24
+ { id: "git", name: "GitHub", icon: "git-branch" },
25
+ { id: "measure", name: "Units", icon: "ruler" },
12
26
  { id: "qr", name: "QR codes", icon: "qr-code" },
13
27
  ];
14
28
 
@@ -125,6 +139,132 @@ export const TOOLS = [
125
139
  keywords: "digest checksum sha sha256 sha512 fingerprint",
126
140
  load: () => import("./tools/hash-generator.js"),
127
141
  },
142
+ {
143
+ id: "password-strength",
144
+ category: "security",
145
+ name: "Password Strength",
146
+ icon: "gauge",
147
+ note: "Estimate how strong a password is.",
148
+ about: "Scores length and patterns and suggests what to change.",
149
+ tutorial: {
150
+ intro: "Estimate how strong a password is.",
151
+ steps: [
152
+ "Type or paste a password.",
153
+ "The score and the reasons appear.",
154
+ "The check runs in this tab. Nothing is sent or saved.",
155
+ ],
156
+ },
157
+ keywords: "password strength score entropy weak strong",
158
+ load: () => import("./tools/password-strength.js"),
159
+ },
160
+ {
161
+ id: "hmac-generator",
162
+ category: "security",
163
+ name: "HMAC Generator",
164
+ icon: "file-key",
165
+ note: "Sign a message with a key.",
166
+ about: "HMAC-SHA-256 and the other SHA sizes, computed in this tab.",
167
+ tutorial: {
168
+ intro: "Sign a message with a secret key.",
169
+ steps: [
170
+ "Type the message and the secret key.",
171
+ "Pick a hash.",
172
+ "Copy the signature. Do not paste a production secret into any site you do not trust.",
173
+ ],
174
+ },
175
+ keywords: "hmac signature mac key sha256 webhook",
176
+ load: () => import("./tools/hmac-generator.js"),
177
+ },
178
+ {
179
+ id: "secure-token",
180
+ category: "security",
181
+ name: "Secure Token",
182
+ icon: "key-round",
183
+ note: "Generate a random token.",
184
+ about: "Hex or URL-safe Base64, from the browser random source.",
185
+ tutorial: {
186
+ intro: "Generate a random token for testing.",
187
+ steps: [
188
+ "Set the byte length.",
189
+ "Pick hex or Base64 URL-safe.",
190
+ "Press Generate, then Copy. Store real tokens safely.",
191
+ ],
192
+ },
193
+ keywords: "token random secret hex base64 url-safe api",
194
+ load: () => import("./tools/secure-token.js"),
195
+ },
196
+ {
197
+ id: "jwt-expiry",
198
+ category: "security",
199
+ name: "JWT Expiry Checker",
200
+ icon: "clock-alert",
201
+ note: "Read a JWT's time claims.",
202
+ about: "Shows iat, nbf and exp as dates and says if it looks expired.",
203
+ tutorial: {
204
+ intro: "Read the time claims of a JSON Web Token.",
205
+ steps: [
206
+ "Paste a token.",
207
+ "The iat, nbf and exp claims appear as dates.",
208
+ "A note says whether it looks expired. The signature is not checked.",
209
+ ],
210
+ },
211
+ keywords: "jwt exp iat nbf expiry token expired",
212
+ load: () => import("./tools/jwt-expiry.js"),
213
+ },
214
+ {
215
+ id: "cert-expiry",
216
+ category: "security",
217
+ name: "Certificate Expiry",
218
+ icon: "shield-check",
219
+ note: "Count the days until a certificate expires.",
220
+ about: "Enter an expiry date and see the days left.",
221
+ tutorial: {
222
+ intro: "Count the days until a certificate expires.",
223
+ steps: [
224
+ "Enter the expiry date.",
225
+ "The days left and the status appear.",
226
+ "Set a reminder threshold to flag a soon date.",
227
+ ],
228
+ },
229
+ keywords: "certificate expiry tls ssl days renew",
230
+ load: () => import("./tools/cert-expiry.js"),
231
+ },
232
+ {
233
+ id: "data-masker",
234
+ category: "security",
235
+ name: "Data Masker",
236
+ icon: "eye-off",
237
+ note: "Hide part of a value before sharing.",
238
+ about: "Masks emails, phone numbers and identifiers.",
239
+ tutorial: {
240
+ intro: "Mask part of a value before sharing it.",
241
+ steps: [
242
+ "Paste the values, one per line.",
243
+ "Pick what to mask.",
244
+ "Copy the masked result.",
245
+ ],
246
+ },
247
+ keywords: "mask redact email phone anonymize hide",
248
+ load: () => import("./tools/data-masker.js"),
249
+ },
250
+ {
251
+ id: "url-inspector",
252
+ category: "security",
253
+ name: "URL Inspector",
254
+ icon: "scan-eye",
255
+ note: "Look closely at a link before opening it.",
256
+ about: "Shows the real host and flags look-alike characters.",
257
+ tutorial: {
258
+ intro: "Look closely at a link before you open it.",
259
+ steps: [
260
+ "Paste a URL.",
261
+ "The real host and path appear.",
262
+ "Look-alike characters in the host are flagged.",
263
+ ],
264
+ },
265
+ keywords: "url inspect phishing host homograph link safe",
266
+ load: () => import("./tools/url-inspector.js"),
267
+ },
128
268
 
129
269
  {
130
270
  id: "uuid-generator",
@@ -291,6 +431,2968 @@ export const TOOLS = [
291
431
  keywords: "read decode camera image photo scan",
292
432
  load: () => import("./tools/qr-scanner.js"),
293
433
  },
434
+
435
+ // ---------- text and writing ----------
436
+ {
437
+ id: "word-counter",
438
+ category: "text",
439
+ name: "Word Counter",
440
+ icon: "text-cursor-input",
441
+ note: "Count words, characters, sentences and lines.",
442
+ about: "Live counts as you type, plus a reading time estimate.",
443
+ tutorial: {
444
+ intro: "Type or paste text and read the counts as they change.",
445
+ steps: [
446
+ "Type or paste your text on the left.",
447
+ "The counts and the reading time update as you type.",
448
+ "Set a word limit to track how close you are, then Copy summary.",
449
+ ],
450
+ },
451
+ keywords: "words characters sentences paragraphs reading time essay limit",
452
+ load: () => import("./tools/word-counter.js"),
453
+ },
454
+ {
455
+ id: "character-counter",
456
+ category: "text",
457
+ name: "Character Counter",
458
+ icon: "ruler",
459
+ note: "Count characters with and without spaces.",
460
+ about: "Tracks a limit and shows what is left.",
461
+ tutorial: {
462
+ intro: "Count characters and watch a limit you set.",
463
+ steps: [
464
+ "Type or paste your text.",
465
+ "Set a character limit if you have one.",
466
+ "The counts and the characters left update as you type.",
467
+ ],
468
+ },
469
+ keywords: "characters unicode emoji limit remaining caption",
470
+ load: () => import("./tools/character-counter.js"),
471
+ },
472
+ {
473
+ id: "line-counter",
474
+ category: "text",
475
+ name: "Line Counter",
476
+ icon: "list",
477
+ note: "Count total, filled and blank lines.",
478
+ about: "Useful for lists, logs and pasted data.",
479
+ tutorial: {
480
+ intro: "Count the lines in a block of text.",
481
+ steps: [
482
+ "Paste your text.",
483
+ "Total, filled and blank lines appear on the right.",
484
+ ],
485
+ },
486
+ keywords: "lines blank empty rows count",
487
+ load: () => import("./tools/line-counter.js"),
488
+ },
489
+ {
490
+ id: "remove-duplicate-lines",
491
+ category: "text",
492
+ name: "Remove Duplicate Lines",
493
+ icon: "list-minus",
494
+ note: "Drop repeated lines, keep the first.",
495
+ about: "Keeps the first time each line appears and reports how many it removed.",
496
+ tutorial: {
497
+ intro: "Remove repeated lines while keeping the original order.",
498
+ steps: [
499
+ "Paste your list, one entry per line.",
500
+ "Toggle Ignore case to treat Andi and andi as the same.",
501
+ "Copy the cleaned list.",
502
+ ],
503
+ },
504
+ keywords: "dedupe unique duplicate lines list",
505
+ load: () => import("./tools/remove-duplicate-lines.js"),
506
+ },
507
+ {
508
+ id: "sort-lines",
509
+ category: "text",
510
+ name: "Sort Lines",
511
+ icon: "arrow-down-a-z",
512
+ note: "Sort lines A to Z or Z to A.",
513
+ about: "Alphabetical or numeric, with an option to ignore case.",
514
+ tutorial: {
515
+ intro: "Sort a list of lines.",
516
+ steps: [
517
+ "Paste your list, one entry per line.",
518
+ "Pick a direction and toggle Ignore case or Numeric.",
519
+ "Copy the sorted list.",
520
+ ],
521
+ },
522
+ keywords: "sort order alphabetical numeric lines list",
523
+ load: () => import("./tools/sort-lines.js"),
524
+ },
525
+ {
526
+ id: "find-replace",
527
+ category: "text",
528
+ name: "Find and Replace",
529
+ icon: "replace",
530
+ note: "Replace every match or just one.",
531
+ about: "Plain text or a regular expression, with a live match count.",
532
+ tutorial: {
533
+ intro: "Find a value in text and replace it.",
534
+ steps: [
535
+ "Paste your text, then set the find and replace values.",
536
+ "Toggle Regex to match a pattern, or Ignore case to match either case.",
537
+ "Press Replace all. The count of replacements is shown.",
538
+ ],
539
+ },
540
+ keywords: "search replace regex substitute text",
541
+ load: () => import("./tools/find-replace.js"),
542
+ },
543
+ {
544
+ id: "remove-extra-spaces",
545
+ category: "text",
546
+ name: "Remove Extra Spaces",
547
+ icon: "eraser",
548
+ note: "Tidy double spaces and blank lines.",
549
+ about: "Trim each line and collapse runs of spaces.",
550
+ tutorial: {
551
+ intro: "Clean up spacing in pasted text.",
552
+ steps: [
553
+ "Paste your text.",
554
+ "Toggle the cleanups you want.",
555
+ "Copy the tidied text.",
556
+ ],
557
+ },
558
+ keywords: "trim whitespace spaces blank lines tidy",
559
+ load: () => import("./tools/remove-extra-spaces.js"),
560
+ },
561
+ {
562
+ id: "text-reverser",
563
+ category: "text",
564
+ name: "Text Reverser",
565
+ icon: "arrow-left-right",
566
+ note: "Reverse by character, word or line.",
567
+ about: "Handles emoji and accented characters as whole units.",
568
+ tutorial: {
569
+ intro: "Reverse text by character, word, or line.",
570
+ steps: [
571
+ "Type or paste your text.",
572
+ "Pick Characters, Words, or Lines.",
573
+ "Copy the reversed text.",
574
+ ],
575
+ },
576
+ keywords: "reverse flip backwards characters words lines",
577
+ load: () => import("./tools/text-reverser.js"),
578
+ },
579
+ {
580
+ id: "slug-converter",
581
+ category: "text",
582
+ name: "Slug Converter",
583
+ icon: "link-2",
584
+ note: "Turn a title into a URL slug.",
585
+ about: "Lowercase, hyphenated, punctuation removed.",
586
+ tutorial: {
587
+ intro: "Turn a title into a URL slug.",
588
+ steps: [
589
+ "Type a title.",
590
+ "Pick the separator.",
591
+ "Copy the slug.",
592
+ ],
593
+ },
594
+ keywords: "slug url seo permalink kebab",
595
+ load: () => import("./tools/slug-converter.js"),
596
+ },
597
+ {
598
+ id: "prefix-suffix",
599
+ category: "text",
600
+ name: "Prefix and Suffix",
601
+ icon: "list-plus",
602
+ note: "Add text to the start or end of lines.",
603
+ about: "Adds a prefix, a suffix, or automatic numbering to each line.",
604
+ tutorial: {
605
+ intro: "Add a prefix, suffix, or numbering to every line.",
606
+ steps: [
607
+ "Paste your list, one entry per line.",
608
+ "Set a prefix and suffix, or turn on Numbering.",
609
+ "Copy the result.",
610
+ ],
611
+ },
612
+ keywords: "prefix suffix affix numbering lines",
613
+ load: () => import("./tools/prefix-suffix.js"),
614
+ },
615
+ {
616
+ id: "text-diff",
617
+ category: "text",
618
+ name: "Text Diff",
619
+ icon: "file-diff",
620
+ note: "Compare two texts line by line.",
621
+ about: "Marks added and removed lines, with a count of each.",
622
+ tutorial: {
623
+ intro: "Compare two versions of a text.",
624
+ steps: [
625
+ "Paste the first text on the left and the second on the right.",
626
+ "Added and removed lines are marked in the result.",
627
+ "Toggle Ignore case or Ignore spaces to soften the comparison.",
628
+ ],
629
+ },
630
+ keywords: "diff compare changes revisions text",
631
+ load: () => import("./tools/text-diff.js"),
632
+ },
633
+ {
634
+ id: "case-inspector",
635
+ category: "text",
636
+ name: "Case Inspector",
637
+ icon: "text-search",
638
+ note: "Detect the letter case of text.",
639
+ about: "Names the case it finds and shows the alternatives.",
640
+ tutorial: {
641
+ intro: "Detect which letter case a piece of text uses.",
642
+ steps: [
643
+ "Type or paste the text.",
644
+ "The detected case is named, with every other case listed.",
645
+ "Click a case to copy it.",
646
+ ],
647
+ },
648
+ keywords: "case detect camel snake title inspect",
649
+ load: () => import("./tools/case-inspector.js"),
650
+ },
651
+
652
+ // ---------- developer ----------
653
+ {
654
+ id: "jwt-decoder",
655
+ category: "developer",
656
+ name: "JWT Decoder",
657
+ icon: "signature",
658
+ note: "Read a JWT header and payload.",
659
+ about: "Decodes in this tab. Decoding is not signature validation.",
660
+ tutorial: {
661
+ intro: "Read the header and payload of a JSON Web Token.",
662
+ steps: [
663
+ "Paste a token.",
664
+ "The header and payload appear as JSON.",
665
+ "The iat, nbf and exp claims are shown as readable times when present.",
666
+ ],
667
+ },
668
+ keywords: "jwt token decode header payload claims bearer",
669
+ load: () => import("./tools/jwt-decoder.js"),
670
+ },
671
+ {
672
+ id: "json-formatter",
673
+ category: "developer",
674
+ name: "JSON Formatter",
675
+ icon: "braces",
676
+ note: "Pretty-print JSON with 2 or 4 spaces.",
677
+ about: "Formats or compacts JSON and points at the error when it is invalid.",
678
+ tutorial: {
679
+ intro: "Format or compact a JSON document.",
680
+ steps: [
681
+ "Paste JSON on the left.",
682
+ "Pick 2 or 4 spaces, or Compact.",
683
+ "Copy the result. An invalid document shows where parsing stopped.",
684
+ ],
685
+ },
686
+ keywords: "json format pretty print indent minify",
687
+ load: () => import("./tools/json-formatter.js"),
688
+ },
689
+ {
690
+ id: "json-validator",
691
+ category: "developer",
692
+ name: "JSON Validator",
693
+ icon: "circle-check",
694
+ note: "Check whether JSON parses.",
695
+ about: "Reports the first syntax error and where it is.",
696
+ tutorial: {
697
+ intro: "Check whether a JSON document is valid.",
698
+ steps: [
699
+ "Paste JSON.",
700
+ "The result says valid or names the first error.",
701
+ ],
702
+ },
703
+ keywords: "json validate syntax error parse check",
704
+ load: () => import("./tools/json-validator.js"),
705
+ },
706
+ {
707
+ id: "json-minifier",
708
+ category: "developer",
709
+ name: "JSON Minifier",
710
+ icon: "minimize-2",
711
+ note: "Strip whitespace from JSON.",
712
+ about: "Compacts valid JSON and shows the size saved.",
713
+ tutorial: {
714
+ intro: "Compact JSON by removing needless whitespace.",
715
+ steps: [
716
+ "Paste JSON.",
717
+ "The compacted document and the size saved appear on the right.",
718
+ "Copy the result.",
719
+ ],
720
+ },
721
+ keywords: "json minify compact whitespace size",
722
+ load: () => import("./tools/json-minifier.js"),
723
+ },
724
+ {
725
+ id: "json-to-typescript",
726
+ category: "developer",
727
+ name: "JSON to TypeScript",
728
+ icon: "file-code",
729
+ note: "Turn a JSON sample into types.",
730
+ about: "Generates interfaces from a JSON object, including nested ones.",
731
+ tutorial: {
732
+ intro: "Generate TypeScript types from a JSON sample.",
733
+ steps: [
734
+ "Paste a JSON object or array.",
735
+ "Set the name of the root type.",
736
+ "Copy the generated types.",
737
+ ],
738
+ },
739
+ keywords: "json typescript interface type generate schema",
740
+ load: () => import("./tools/json-to-typescript.js"),
741
+ },
742
+ {
743
+ id: "regex-tester",
744
+ category: "developer",
745
+ name: "Regex Tester",
746
+ icon: "regex",
747
+ note: "Test a pattern against text.",
748
+ about: "Highlights matches and lists the capture groups.",
749
+ tutorial: {
750
+ intro: "Test a regular expression against sample text.",
751
+ steps: [
752
+ "Enter a pattern and any flags.",
753
+ "Paste the text to test against.",
754
+ "Matches are highlighted and listed with their capture groups.",
755
+ ],
756
+ },
757
+ keywords: "regex regular expression pattern match test groups",
758
+ load: () => import("./tools/regex-tester.js"),
759
+ },
760
+ {
761
+ id: "timestamp-converter",
762
+ category: "developer",
763
+ name: "Timestamp Converter",
764
+ icon: "clock",
765
+ note: "Convert between Unix time and dates.",
766
+ about: "Reads seconds or milliseconds and writes ISO 8601.",
767
+ tutorial: {
768
+ intro: "Convert a Unix timestamp to a date, or a date to a timestamp.",
769
+ steps: [
770
+ "Paste a timestamp, or pick a date.",
771
+ "Seconds and milliseconds are both handled.",
772
+ "Copy the ISO 8601 value or the timestamp.",
773
+ ],
774
+ },
775
+ keywords: "unix timestamp epoch date time iso utc",
776
+ load: () => import("./tools/timestamp-converter.js"),
777
+ },
778
+ {
779
+ id: "html-entity",
780
+ category: "developer",
781
+ name: "HTML Entities",
782
+ icon: "code-xml",
783
+ note: "Encode or decode HTML entities.",
784
+ about: "Turns <, >, & and quotes into entities and back.",
785
+ tutorial: {
786
+ intro: "Encode special characters as HTML entities, or decode them.",
787
+ steps: [
788
+ "Pick Encode or Decode.",
789
+ "Type or paste your text.",
790
+ "Copy the result.",
791
+ ],
792
+ },
793
+ keywords: "html entity encode decode escape amp lt gt",
794
+ load: () => import("./tools/html-entity.js"),
795
+ },
796
+ {
797
+ id: "sql-formatter",
798
+ category: "developer",
799
+ name: "SQL Formatter",
800
+ icon: "database",
801
+ note: "Format a SQL query.",
802
+ about: "Indents the clauses and can upper-case the keywords.",
803
+ tutorial: {
804
+ intro: "Format a SQL query so it reads clause by clause.",
805
+ steps: [
806
+ "Paste a query.",
807
+ "Toggle keyword casing.",
808
+ "Copy the formatted query.",
809
+ ],
810
+ },
811
+ keywords: "sql format beautify indent keywords query",
812
+ load: () => import("./tools/sql-formatter.js"),
813
+ },
814
+ {
815
+ id: "sql-minifier",
816
+ category: "developer",
817
+ name: "SQL Minifier",
818
+ icon: "shrink",
819
+ note: "Compact a SQL query.",
820
+ about: "Removes needless whitespace while keeping string literals intact.",
821
+ tutorial: {
822
+ intro: "Compact a SQL query onto fewer lines.",
823
+ steps: [
824
+ "Paste a query.",
825
+ "The compacted query appears on the right.",
826
+ "Copy the result.",
827
+ ],
828
+ },
829
+ keywords: "sql minify compact whitespace query",
830
+ load: () => import("./tools/sql-minifier.js"),
831
+ },
832
+ {
833
+ id: "cron-builder",
834
+ category: "developer",
835
+ name: "Cron Builder",
836
+ icon: "calendar-clock",
837
+ note: "Build a cron expression.",
838
+ about: "Sets each field and explains the schedule in plain words.",
839
+ tutorial: {
840
+ intro: "Build a cron expression and read it back in plain words.",
841
+ steps: [
842
+ "Set the minute, hour, day, month and weekday fields.",
843
+ "The expression and a plain description appear.",
844
+ "Copy the expression. Cron implementations can differ, so check yours.",
845
+ ],
846
+ },
847
+ keywords: "cron schedule expression crontab job",
848
+ load: () => import("./tools/cron-builder.js"),
849
+ },
850
+ {
851
+ id: "html-formatter",
852
+ category: "developer",
853
+ name: "HTML Formatter",
854
+ icon: "code",
855
+ note: "Indent HTML by nesting.",
856
+ about: "Reindents tags and flags tags that never close.",
857
+ tutorial: {
858
+ intro: "Reindent an HTML fragment by nesting depth.",
859
+ steps: [
860
+ "Paste HTML.",
861
+ "Pick the indent size.",
862
+ "Copy the formatted markup.",
863
+ ],
864
+ },
865
+ keywords: "html format indent beautify markup",
866
+ load: () => import("./tools/html-formatter.js"),
867
+ },
868
+ {
869
+ id: "css-formatter",
870
+ category: "developer",
871
+ name: "CSS Formatter",
872
+ icon: "paintbrush",
873
+ note: "Format CSS into readable blocks.",
874
+ about: "One property per line, selectors on their own line.",
875
+ tutorial: {
876
+ intro: "Format a CSS stylesheet.",
877
+ steps: [
878
+ "Paste CSS.",
879
+ "The formatted stylesheet appears on the right.",
880
+ "Copy the result.",
881
+ ],
882
+ },
883
+ keywords: "css format beautify indent stylesheet",
884
+ load: () => import("./tools/css-formatter.js"),
885
+ },
886
+ {
887
+ id: "css-minifier",
888
+ category: "developer",
889
+ name: "CSS Minifier",
890
+ icon: "shrink",
891
+ note: "Compact CSS.",
892
+ about: "Removes comments and needless whitespace, and shows the size saved.",
893
+ tutorial: {
894
+ intro: "Compact a CSS stylesheet.",
895
+ steps: [
896
+ "Paste CSS.",
897
+ "Toggle comment removal if you want it.",
898
+ "Copy the compacted CSS.",
899
+ ],
900
+ },
901
+ keywords: "css minify compact whitespace comments",
902
+ load: () => import("./tools/css-minifier.js"),
903
+ },
904
+ {
905
+ id: "markdown-preview",
906
+ category: "developer",
907
+ name: "Markdown Preview",
908
+ icon: "file-text",
909
+ note: "Render Markdown as you write.",
910
+ about: "Shows headings, lists, links, code and tables next to the source.",
911
+ tutorial: {
912
+ intro: "Write Markdown and see it rendered next to the source.",
913
+ steps: [
914
+ "Type or paste Markdown on the left.",
915
+ "The rendered result appears on the right.",
916
+ "Copy the Markdown source with the Copy button.",
917
+ ],
918
+ },
919
+ keywords: "markdown preview render md github readme",
920
+ load: () => import("./tools/markdown-preview.js"),
921
+ },
922
+ {
923
+ id: "markdown-table",
924
+ category: "developer",
925
+ name: "Markdown Table",
926
+ icon: "table",
927
+ note: "Build a Markdown table.",
928
+ about: "Add rows and columns and pick the column alignment.",
929
+ tutorial: {
930
+ intro: "Build a Markdown table cell by cell.",
931
+ steps: [
932
+ "Add rows and columns as needed.",
933
+ "Set the alignment for each column.",
934
+ "Copy the Markdown table.",
935
+ ],
936
+ },
937
+ keywords: "markdown table generator readme columns",
938
+ load: () => import("./tools/markdown-table.js"),
939
+ },
940
+ {
941
+ id: "env-formatter",
942
+ category: "developer",
943
+ name: "Env Formatter",
944
+ icon: "file-key",
945
+ note: "Tidy a .env list.",
946
+ about: "Sorts KEY=value lines and flags duplicate names.",
947
+ tutorial: {
948
+ intro: "Tidy a list of environment variables.",
949
+ steps: [
950
+ "Paste KEY=value lines.",
951
+ "The names are sorted and duplicates are flagged.",
952
+ "Copy the tidied list.",
953
+ ],
954
+ },
955
+ keywords: "env dotenv environment variables key value sort",
956
+ load: () => import("./tools/env-formatter.js"),
957
+ },
958
+ {
959
+ id: "api-request-builder",
960
+ category: "developer",
961
+ name: "API Request Builder",
962
+ icon: "send",
963
+ note: "Build an HTTP request as fetch code.",
964
+ about: "Pick a method, fill the URL, headers and body, and copy the fetch snippet.",
965
+ tutorial: {
966
+ intro: "Build an HTTP request and copy it as fetch code.",
967
+ steps: [
968
+ "Pick a method and enter the URL.",
969
+ "Add headers and a body if the method takes one.",
970
+ "Copy the generated fetch snippet.",
971
+ ],
972
+ },
973
+ keywords: "api http request fetch curl method headers",
974
+ load: () => import("./tools/api-request-builder.js"),
975
+ },
976
+ {
977
+ id: "git-command-builder",
978
+ category: "developer",
979
+ name: "Git Command Builder",
980
+ icon: "git-branch",
981
+ note: "Build common git commands.",
982
+ about: "Fills in clone, switch, pull and commit, and flags the destructive ones.",
983
+ tutorial: {
984
+ intro: "Build a common git command from a few fields.",
985
+ steps: [
986
+ "Pick an operation.",
987
+ "Fill the fields it asks for.",
988
+ "Copy the command. Operations that can lose work are marked.",
989
+ ],
990
+ },
991
+ keywords: "git command clone branch commit pull checkout",
992
+ load: () => import("./tools/git-command-builder.js"),
993
+ },
994
+
995
+ // ---------- daily use ----------
996
+ {
997
+ id: "countdown-timer",
998
+ category: "daily",
999
+ name: "Countdown Timer",
1000
+ icon: "timer",
1001
+ note: "Count down from a set duration.",
1002
+ about: "Set a time, start it, and get a nudge when it ends.",
1003
+ tutorial: {
1004
+ intro: "Count down from a duration you set.",
1005
+ steps: [
1006
+ "Set the hours, minutes and seconds, or pick a preset.",
1007
+ "Press Start. Pause and resume any time.",
1008
+ "A short beep plays and the tab title changes when it reaches zero.",
1009
+ ],
1010
+ },
1011
+ keywords: "countdown timer minutes alarm focus pomodoro",
1012
+ load: () => import("./tools/countdown-timer.js"),
1013
+ },
1014
+ {
1015
+ id: "stopwatch",
1016
+ category: "daily",
1017
+ name: "Stopwatch",
1018
+ icon: "clock",
1019
+ note: "Time an activity and record laps.",
1020
+ about: "Start, pause, and record laps with millisecond precision.",
1021
+ tutorial: {
1022
+ intro: "Time an activity and record laps.",
1023
+ steps: [
1024
+ "Press Start to begin.",
1025
+ "Press Lap to record a split, or Pause to hold.",
1026
+ "Copy the list of laps when you are done.",
1027
+ ],
1028
+ },
1029
+ keywords: "stopwatch lap split timer duration",
1030
+ load: () => import("./tools/stopwatch.js"),
1031
+ },
1032
+ {
1033
+ id: "checklist",
1034
+ category: "daily",
1035
+ name: "Checklist",
1036
+ icon: "list-checks",
1037
+ note: "Make a list you can tick off.",
1038
+ about: "Add items, tick them off, and see how many are left.",
1039
+ tutorial: {
1040
+ intro: "Make a list you can tick off.",
1041
+ steps: [
1042
+ "Type an item and press Add.",
1043
+ "Tick items as you finish them.",
1044
+ "Copy the list, or clear the finished items.",
1045
+ ],
1046
+ },
1047
+ keywords: "checklist todo tasks tick list",
1048
+ load: () => import("./tools/checklist.js"),
1049
+ },
1050
+ {
1051
+ id: "daily-planner",
1052
+ category: "daily",
1053
+ name: "Daily Planner",
1054
+ icon: "calendar-check",
1055
+ note: "Plan a day by the clock.",
1056
+ about: "Add activities with start and end times and spot overlaps.",
1057
+ tutorial: {
1058
+ intro: "Plan a day by the clock.",
1059
+ steps: [
1060
+ "Add an activity with its start and end time.",
1061
+ "The list sorts by time and shows each duration.",
1062
+ "Overlapping activities are flagged.",
1063
+ ],
1064
+ },
1065
+ keywords: "planner schedule agenda day time blocks",
1066
+ load: () => import("./tools/daily-planner.js"),
1067
+ },
1068
+ {
1069
+ id: "weekly-planner",
1070
+ category: "daily",
1071
+ name: "Weekly Planner",
1072
+ icon: "calendar-range",
1073
+ note: "Plan seven days at once.",
1074
+ about: "Add targets to each weekday and tick them off.",
1075
+ tutorial: {
1076
+ intro: "Plan seven days at once.",
1077
+ steps: [
1078
+ "Pick a day.",
1079
+ "Add an activity or target.",
1080
+ "Tick items off as you go, and copy the week.",
1081
+ ],
1082
+ },
1083
+ keywords: "weekly planner schedule week days",
1084
+ load: () => import("./tools/weekly-planner.js"),
1085
+ },
1086
+ {
1087
+ id: "priority-matrix",
1088
+ category: "daily",
1089
+ name: "Priority Matrix",
1090
+ icon: "grid-2x2",
1091
+ note: "Sort tasks by urgency and importance.",
1092
+ about: "Four boxes: do now, schedule, delegate, drop.",
1093
+ tutorial: {
1094
+ intro: "Sort tasks into four boxes by urgency and importance.",
1095
+ steps: [
1096
+ "Add a task and pick a quadrant.",
1097
+ "Move tasks between quadrants as they change.",
1098
+ "Copy the matrix when you are done.",
1099
+ ],
1100
+ },
1101
+ keywords: "eisenhower matrix urgent important priority tasks",
1102
+ load: () => import("./tools/priority-matrix.js"),
1103
+ },
1104
+ {
1105
+ id: "meeting-agenda",
1106
+ category: "daily",
1107
+ name: "Meeting Agenda",
1108
+ icon: "clipboard-list",
1109
+ note: "Lay out a meeting with timings.",
1110
+ about: "Topics with owners and time budgets, totalled for you.",
1111
+ tutorial: {
1112
+ intro: "Lay out a meeting with timings.",
1113
+ steps: [
1114
+ "Add topics with an owner and a time budget.",
1115
+ "The total time and each start time are shown.",
1116
+ "Copy the agenda.",
1117
+ ],
1118
+ },
1119
+ keywords: "meeting agenda topics minutes timebox",
1120
+ load: () => import("./tools/meeting-agenda.js"),
1121
+ },
1122
+ {
1123
+ id: "habit-tracker",
1124
+ category: "daily",
1125
+ name: "Habit Tracker",
1126
+ icon: "flame",
1127
+ note: "Mark habits done each day.",
1128
+ about: "Track a week of habits and see your streaks.",
1129
+ tutorial: {
1130
+ intro: "Track a week of habits.",
1131
+ steps: [
1132
+ "Add a habit.",
1133
+ "Tick the days you keep it.",
1134
+ "The week count and the streak update.",
1135
+ ],
1136
+ },
1137
+ keywords: "habit tracker streak daily week routine",
1138
+ load: () => import("./tools/habit-tracker.js"),
1139
+ },
1140
+
1141
+ // ---------- math ----------
1142
+ {
1143
+ id: "percentage-calculator",
1144
+ category: "math",
1145
+ name: "Percentage Calculator",
1146
+ icon: "percent",
1147
+ note: "Work out a percentage of a number.",
1148
+ about: "Find a percent of a value, or what percent one value is of another.",
1149
+ tutorial: {
1150
+ intro: "Work out percentages.",
1151
+ steps: [
1152
+ "Enter the values.",
1153
+ "Read the result, updated as you type.",
1154
+ ],
1155
+ },
1156
+ keywords: "percent percentage of number calculate",
1157
+ load: () => import("./tools/percentage-calculator.js"),
1158
+ },
1159
+ {
1160
+ id: "percentage-change",
1161
+ category: "math",
1162
+ name: "Percentage Change",
1163
+ icon: "trending-up",
1164
+ note: "Measure the change between two values.",
1165
+ about: "Shows the change as a percent and names a rise or fall.",
1166
+ tutorial: {
1167
+ intro: "Measure the change between two values.",
1168
+ steps: [
1169
+ "Enter the starting and ending values.",
1170
+ "The change, the direction and the difference appear.",
1171
+ ],
1172
+ },
1173
+ keywords: "percent change increase decrease difference",
1174
+ load: () => import("./tools/percentage-change.js"),
1175
+ },
1176
+ {
1177
+ id: "discount-calculator",
1178
+ category: "math",
1179
+ name: "Discount Calculator",
1180
+ icon: "badge-percent",
1181
+ note: "Work out a sale price.",
1182
+ about: "Applies one or more discounts, with optional tax after.",
1183
+ tutorial: {
1184
+ intro: "Work out a sale price.",
1185
+ steps: [
1186
+ "Enter the price and the discount.",
1187
+ "Add a second discount or a tax rate if you need to.",
1188
+ "The final price and the amount saved are shown.",
1189
+ ],
1190
+ },
1191
+ keywords: "discount sale price percent off tax",
1192
+ load: () => import("./tools/discount-calculator.js"),
1193
+ },
1194
+ {
1195
+ id: "profit-margin",
1196
+ category: "math",
1197
+ name: "Profit and Margin",
1198
+ icon: "trending-up",
1199
+ note: "Work out profit and margin.",
1200
+ about: "Shows the profit, the margin and the markup for a sale.",
1201
+ tutorial: {
1202
+ intro: "Work out profit, margin and markup.",
1203
+ steps: [
1204
+ "Enter the cost and the selling price.",
1205
+ "Profit, margin and markup appear.",
1206
+ ],
1207
+ },
1208
+ keywords: "profit margin markup cost price business",
1209
+ load: () => import("./tools/profit-margin.js"),
1210
+ },
1211
+ {
1212
+ id: "markup-calculator",
1213
+ category: "math",
1214
+ name: "Markup Calculator",
1215
+ icon: "tag",
1216
+ note: "Set a price from cost and markup.",
1217
+ about: "Turns a cost and a target markup into a selling price.",
1218
+ tutorial: {
1219
+ intro: "Set a selling price from a cost and a markup.",
1220
+ steps: [
1221
+ "Enter the cost and the markup percent.",
1222
+ "The selling price and the profit appear.",
1223
+ ],
1224
+ },
1225
+ keywords: "markup price cost percent selling",
1226
+ load: () => import("./tools/markup-calculator.js"),
1227
+ },
1228
+ {
1229
+ id: "ratio-calculator",
1230
+ category: "math",
1231
+ name: "Ratio Calculator",
1232
+ icon: "divide",
1233
+ note: "Simplify and scale ratios.",
1234
+ about: "Reduces a ratio and solves for a missing term.",
1235
+ tutorial: {
1236
+ intro: "Simplify a ratio or solve for a missing term.",
1237
+ steps: [
1238
+ "Enter two or more numbers.",
1239
+ "The simplified ratio appears.",
1240
+ "Fill three of four terms to solve the missing one.",
1241
+ ],
1242
+ },
1243
+ keywords: "ratio simplify proportion scale divide",
1244
+ load: () => import("./tools/ratio-calculator.js"),
1245
+ },
1246
+ {
1247
+ id: "average-calculator",
1248
+ category: "math",
1249
+ name: "Average Calculator",
1250
+ icon: "sigma",
1251
+ note: "Find mean, median and mode.",
1252
+ about: "Paste numbers and read the summary statistics.",
1253
+ tutorial: {
1254
+ intro: "Find the mean, median and mode of a list of numbers.",
1255
+ steps: [
1256
+ "Paste numbers separated by spaces, commas or new lines.",
1257
+ "Mean, median, mode, count and sum appear.",
1258
+ ],
1259
+ },
1260
+ keywords: "average mean median mode statistics",
1261
+ load: () => import("./tools/average-calculator.js"),
1262
+ },
1263
+ {
1264
+ id: "weighted-average",
1265
+ category: "math",
1266
+ name: "Weighted Average",
1267
+ icon: "scale",
1268
+ note: "Average values with weights.",
1269
+ about: "Give each value a weight and read the weighted mean.",
1270
+ tutorial: {
1271
+ intro: "Average values that carry different weights.",
1272
+ steps: [
1273
+ "Add values with their weights.",
1274
+ "The weighted average and the total weight appear.",
1275
+ ],
1276
+ },
1277
+ keywords: "weighted average grades weights",
1278
+ load: () => import("./tools/weighted-average.js"),
1279
+ },
1280
+ {
1281
+ id: "standard-deviation",
1282
+ category: "math",
1283
+ name: "Standard Deviation",
1284
+ icon: "chart-line",
1285
+ note: "Variance and standard deviation.",
1286
+ about: "For a population or a sample, from pasted numbers.",
1287
+ tutorial: {
1288
+ intro: "Find the variance and standard deviation of a list of numbers.",
1289
+ steps: [
1290
+ "Paste your numbers.",
1291
+ "Pick Population or Sample.",
1292
+ "Mean, variance and standard deviation appear.",
1293
+ ],
1294
+ },
1295
+ keywords: "standard deviation variance statistics sample population",
1296
+ load: () => import("./tools/standard-deviation.js"),
1297
+ },
1298
+ {
1299
+ id: "fraction-calculator",
1300
+ category: "math",
1301
+ name: "Fraction Calculator",
1302
+ icon: "divide",
1303
+ note: "Add, subtract, multiply and divide fractions.",
1304
+ about: "Keeps the result as a simplified fraction and a decimal.",
1305
+ tutorial: {
1306
+ intro: "Do arithmetic with fractions.",
1307
+ steps: [
1308
+ "Enter two fractions and pick an operation.",
1309
+ "The simplified result and its decimal appear.",
1310
+ ],
1311
+ },
1312
+ keywords: "fraction add subtract multiply divide simplify",
1313
+ load: () => import("./tools/fraction-calculator.js"),
1314
+ },
1315
+ {
1316
+ id: "scientific-calculator",
1317
+ category: "math",
1318
+ name: "Scientific Calculator",
1319
+ icon: "calculator",
1320
+ note: "Do scientific math with a keypad.",
1321
+ about: "Trigonometry, logs, powers and roots, in degrees or radians.",
1322
+ tutorial: {
1323
+ intro: "Do scientific math with a keypad.",
1324
+ steps: [
1325
+ "Type an expression or use the keys.",
1326
+ "Pick degrees or radians for the trig functions.",
1327
+ "Press = to evaluate. The history keeps recent results.",
1328
+ ],
1329
+ },
1330
+ keywords: "scientific calculator trigonometry log sin cos tan",
1331
+ load: () => import("./tools/scientific-calculator.js"),
1332
+ },
1333
+ {
1334
+ id: "quadratic-solver",
1335
+ category: "math",
1336
+ name: "Quadratic Solver",
1337
+ icon: "radical",
1338
+ note: "Solve a quadratic equation.",
1339
+ about: "Shows the discriminant and the real or complex roots.",
1340
+ tutorial: {
1341
+ intro: "Solve a quadratic equation of the form ax squared plus bx plus c equals zero.",
1342
+ steps: [
1343
+ "Enter a, b and c.",
1344
+ "The discriminant and the roots appear.",
1345
+ "Real or complex roots are labelled.",
1346
+ ],
1347
+ },
1348
+ keywords: "quadratic equation roots discriminant solve",
1349
+ load: () => import("./tools/quadratic-solver.js"),
1350
+ },
1351
+ {
1352
+ id: "permutation-combination",
1353
+ category: "math",
1354
+ name: "Permutation and Combination",
1355
+ icon: "shuffle",
1356
+ note: "Count arrangements and selections.",
1357
+ about: "nPr and nCr with the working shown.",
1358
+ tutorial: {
1359
+ intro: "Count arrangements and selections.",
1360
+ steps: [
1361
+ "Enter n and r.",
1362
+ "Pick Permutation or Combination.",
1363
+ "The count and the formula appear.",
1364
+ ],
1365
+ },
1366
+ keywords: "permutation combination npr ncr combinatorics",
1367
+ load: () => import("./tools/permutation-combination.js"),
1368
+ },
1369
+ {
1370
+ id: "number-base-converter",
1371
+ category: "math",
1372
+ name: "Number Base Converter",
1373
+ icon: "binary",
1374
+ note: "Convert between number bases.",
1375
+ about: "Binary, octal, decimal and hexadecimal, all at once.",
1376
+ tutorial: {
1377
+ intro: "Convert a number between bases.",
1378
+ steps: [
1379
+ "Type a number and pick its base.",
1380
+ "The value in every base appears.",
1381
+ ],
1382
+ },
1383
+ keywords: "binary octal decimal hex base converter",
1384
+ load: () => import("./tools/number-base-converter.js"),
1385
+ },
1386
+ {
1387
+ id: "scientific-notation",
1388
+ category: "math",
1389
+ name: "Scientific Notation",
1390
+ icon: "superscript",
1391
+ note: "Convert to and from scientific notation.",
1392
+ about: "Handles very large and very small numbers.",
1393
+ tutorial: {
1394
+ intro: "Convert a number to and from scientific notation.",
1395
+ steps: [
1396
+ "Type a number, or a value in scientific notation.",
1397
+ "The other forms appear.",
1398
+ ],
1399
+ },
1400
+ keywords: "scientific notation exponent mantissa",
1401
+ load: () => import("./tools/scientific-notation.js"),
1402
+ },
1403
+ {
1404
+ id: "roman-numeral-converter",
1405
+ category: "math",
1406
+ name: "Roman Numeral Converter",
1407
+ icon: "list-ordered",
1408
+ note: "Convert to and from Roman numerals.",
1409
+ about: "Validates the input and covers 1 to 3999.",
1410
+ tutorial: {
1411
+ intro: "Convert a number to a Roman numeral, or the other way round.",
1412
+ steps: [
1413
+ "Type a number or a Roman numeral.",
1414
+ "The conversion appears, or a message if it is out of range.",
1415
+ ],
1416
+ },
1417
+ keywords: "roman numeral converter number",
1418
+ load: () => import("./tools/roman-numeral-converter.js"),
1419
+ },
1420
+ {
1421
+ id: "percent-to-fraction",
1422
+ category: "math",
1423
+ name: "Percent to Fraction",
1424
+ icon: "percent",
1425
+ note: "Turn a percent into a fraction.",
1426
+ about: "Simplifies the fraction and shows the decimal.",
1427
+ tutorial: {
1428
+ intro: "Turn a percent into a simplified fraction.",
1429
+ steps: [
1430
+ "Type a percent.",
1431
+ "The simplified fraction and the decimal appear.",
1432
+ ],
1433
+ },
1434
+ keywords: "percent fraction decimal convert simplify",
1435
+ load: () => import("./tools/percent-to-fraction.js"),
1436
+ },
1437
+
1438
+ // ---------- date and time ----------
1439
+ {
1440
+ id: "date-difference",
1441
+ category: "datetime",
1442
+ name: "Date Difference",
1443
+ icon: "calendar-minus",
1444
+ note: "Count the days between two dates.",
1445
+ about: "Shows the gap in days, weeks, months and years.",
1446
+ tutorial: {
1447
+ intro: "Count the time between two dates.",
1448
+ steps: [
1449
+ "Pick the start and end dates.",
1450
+ "The difference appears in several units.",
1451
+ "Toggle Include the end date if you count it.",
1452
+ ],
1453
+ },
1454
+ keywords: "date difference days between duration project",
1455
+ load: () => import("./tools/date-difference.js"),
1456
+ },
1457
+ {
1458
+ id: "add-subtract-days",
1459
+ category: "datetime",
1460
+ name: "Add or Subtract Days",
1461
+ icon: "calendar-plus",
1462
+ note: "Move a date by a number of days.",
1463
+ about: "Adds or subtracts days, weeks, months or years.",
1464
+ tutorial: {
1465
+ intro: "Move a date forward or back.",
1466
+ steps: [
1467
+ "Pick a date and a number.",
1468
+ "Pick the unit and add or subtract.",
1469
+ "The resulting date appears.",
1470
+ ],
1471
+ },
1472
+ keywords: "add days date subtract weeks months",
1473
+ load: () => import("./tools/add-subtract-days.js"),
1474
+ },
1475
+ {
1476
+ id: "business-days",
1477
+ category: "datetime",
1478
+ name: "Business Days",
1479
+ icon: "briefcase",
1480
+ note: "Count working days between dates.",
1481
+ about: "Skips weekends and any holidays you add.",
1482
+ tutorial: {
1483
+ intro: "Count working days between two dates.",
1484
+ steps: [
1485
+ "Pick the start and end dates.",
1486
+ "Choose which weekdays are working days.",
1487
+ "Add holidays to skip, and read the working day count.",
1488
+ ],
1489
+ },
1490
+ keywords: "business days working days weekend holiday",
1491
+ load: () => import("./tools/business-days.js"),
1492
+ },
1493
+ {
1494
+ id: "time-duration",
1495
+ category: "datetime",
1496
+ name: "Time Duration",
1497
+ icon: "hourglass",
1498
+ note: "Measure the time between two clock times.",
1499
+ about: "Handles crossing midnight and subtracts breaks.",
1500
+ tutorial: {
1501
+ intro: "Measure the time between two clock times.",
1502
+ steps: [
1503
+ "Enter the start and end times.",
1504
+ "Add a break in minutes if you need to.",
1505
+ "The duration appears in hours and minutes.",
1506
+ ],
1507
+ },
1508
+ keywords: "time duration hours minutes between start end",
1509
+ load: () => import("./tools/time-duration.js"),
1510
+ },
1511
+ {
1512
+ id: "timezone-converter",
1513
+ category: "datetime",
1514
+ name: "Time Zone Converter",
1515
+ icon: "globe",
1516
+ note: "Convert a time between zones.",
1517
+ about: "Uses the time zone rules built into your browser.",
1518
+ tutorial: {
1519
+ intro: "Convert a time from one zone to another.",
1520
+ steps: [
1521
+ "Pick a date and time.",
1522
+ "Pick the source and target zones.",
1523
+ "The converted time appears.",
1524
+ ],
1525
+ },
1526
+ keywords: "timezone time zone convert utc meeting world",
1527
+ load: () => import("./tools/timezone-converter.js"),
1528
+ },
1529
+ {
1530
+ id: "age-calculator",
1531
+ category: "datetime",
1532
+ name: "Age Calculator",
1533
+ icon: "cake",
1534
+ note: "Work out an age in years, months and days.",
1535
+ about: "Ages on any date, plus the next birthday.",
1536
+ tutorial: {
1537
+ intro: "Work out an age from a birth date.",
1538
+ steps: [
1539
+ "Enter the birth date.",
1540
+ "Optionally set the date to measure at.",
1541
+ "The age and the next birthday appear.",
1542
+ ],
1543
+ },
1544
+ keywords: "age birthday date of birth years old",
1545
+ load: () => import("./tools/age-calculator.js"),
1546
+ },
1547
+ {
1548
+ id: "time-format-converter",
1549
+ category: "datetime",
1550
+ name: "Time Format Converter",
1551
+ icon: "clock",
1552
+ note: "Switch between 12 and 24 hour time.",
1553
+ about: "Converts one time or a whole list.",
1554
+ tutorial: {
1555
+ intro: "Switch times between 12 and 24 hour format.",
1556
+ steps: [
1557
+ "Pick 12 or 24 hour input.",
1558
+ "Type one time per line.",
1559
+ "The converted times appear.",
1560
+ ],
1561
+ },
1562
+ keywords: "12 hour 24 hour am pm time format convert",
1563
+ load: () => import("./tools/time-format-converter.js"),
1564
+ },
1565
+
1566
+ // ---------- data and lists ----------
1567
+ {
1568
+ id: "csv-viewer",
1569
+ category: "data",
1570
+ name: "CSV Viewer",
1571
+ icon: "table",
1572
+ note: "Read CSV as a table.",
1573
+ about: "Detects the delimiter and shows rows and columns.",
1574
+ tutorial: {
1575
+ intro: "Read CSV or delimited text as a table.",
1576
+ steps: [
1577
+ "Paste CSV, or choose a .csv file.",
1578
+ "Pick the delimiter if the guess is wrong.",
1579
+ "The table and the row and column counts appear.",
1580
+ ],
1581
+ },
1582
+ keywords: "csv table view rows columns delimiter",
1583
+ load: () => import("./tools/csv-viewer.js"),
1584
+ },
1585
+ {
1586
+ id: "csv-to-json",
1587
+ category: "data",
1588
+ name: "CSV to JSON",
1589
+ icon: "braces",
1590
+ note: "Turn CSV rows into JSON.",
1591
+ about: "The first row becomes the property names.",
1592
+ tutorial: {
1593
+ intro: "Turn CSV rows into JSON records.",
1594
+ steps: [
1595
+ "Paste CSV.",
1596
+ "Toggle typed values if numbers and booleans should convert.",
1597
+ "Copy the JSON.",
1598
+ ],
1599
+ },
1600
+ keywords: "csv json convert rows header",
1601
+ load: () => import("./tools/csv-to-json.js"),
1602
+ },
1603
+ {
1604
+ id: "json-to-csv",
1605
+ category: "data",
1606
+ name: "JSON to CSV",
1607
+ icon: "file-spreadsheet",
1608
+ note: "Turn JSON records into CSV.",
1609
+ about: "Uses the object keys as the column names.",
1610
+ tutorial: {
1611
+ intro: "Turn JSON records into CSV.",
1612
+ steps: [
1613
+ "Paste an array of objects.",
1614
+ "The CSV appears with a header row.",
1615
+ "Copy or download the CSV.",
1616
+ ],
1617
+ },
1618
+ keywords: "json csv convert export records columns",
1619
+ load: () => import("./tools/json-to-csv.js"),
1620
+ },
1621
+ {
1622
+ id: "delimiter-converter",
1623
+ category: "data",
1624
+ name: "Delimiter Converter",
1625
+ icon: "arrow-right-left",
1626
+ note: "Swap one delimiter for another.",
1627
+ about: "Comma, semicolon, tab, pipe or your own.",
1628
+ tutorial: {
1629
+ intro: "Swap one delimiter for another.",
1630
+ steps: [
1631
+ "Paste your data.",
1632
+ "Set the current and the new delimiter.",
1633
+ "Copy the result.",
1634
+ ],
1635
+ },
1636
+ keywords: "delimiter comma tab semicolon pipe convert tsv",
1637
+ load: () => import("./tools/delimiter-converter.js"),
1638
+ },
1639
+ {
1640
+ id: "list-merger",
1641
+ category: "data",
1642
+ name: "List Merger",
1643
+ icon: "combine",
1644
+ note: "Join lists into one.",
1645
+ about: "Combines two or more lists, with an option to drop duplicates.",
1646
+ tutorial: {
1647
+ intro: "Join two or more lists into one.",
1648
+ steps: [
1649
+ "Paste each list in its own box.",
1650
+ "Toggle Remove duplicates if you need to.",
1651
+ "Copy the merged list.",
1652
+ ],
1653
+ },
1654
+ keywords: "merge combine lists join append unique",
1655
+ load: () => import("./tools/list-merger.js"),
1656
+ },
1657
+ {
1658
+ id: "list-difference",
1659
+ category: "data",
1660
+ name: "List Difference",
1661
+ icon: "git-compare",
1662
+ note: "Compare two lists.",
1663
+ about: "Shows what is only in each list and what they share.",
1664
+ tutorial: {
1665
+ intro: "Compare two lists.",
1666
+ steps: [
1667
+ "Paste list A and list B.",
1668
+ "Only in A, only in B and shared items appear.",
1669
+ "Toggle Ignore case if you need to.",
1670
+ ],
1671
+ },
1672
+ keywords: "list difference compare sets common unique",
1673
+ load: () => import("./tools/list-difference.js"),
1674
+ },
1675
+ {
1676
+ id: "table-to-markdown",
1677
+ category: "data",
1678
+ name: "Table to Markdown",
1679
+ icon: "table-2",
1680
+ note: "Turn pasted table data into Markdown.",
1681
+ about: "Paste tab or comma separated data and set the alignment.",
1682
+ tutorial: {
1683
+ intro: "Turn pasted table data into a Markdown table.",
1684
+ steps: [
1685
+ "Paste rows copied from a spreadsheet.",
1686
+ "The Markdown table appears.",
1687
+ "Copy the Markdown.",
1688
+ ],
1689
+ },
1690
+ keywords: "table markdown tsv spreadsheet convert",
1691
+ load: () => import("./tools/table-to-markdown.js"),
1692
+ },
1693
+ {
1694
+ id: "data-validator",
1695
+ category: "data",
1696
+ name: "Data Validator",
1697
+ icon: "badge-check",
1698
+ note: "Check a list against simple rules.",
1699
+ about: "Flags rows that fail a length, pattern or range rule.",
1700
+ tutorial: {
1701
+ intro: "Check a list of values against a rule.",
1702
+ steps: [
1703
+ "Paste one value per line.",
1704
+ "Pick a rule and its setting.",
1705
+ "Rows that fail are listed.",
1706
+ ],
1707
+ },
1708
+ keywords: "validate data rule email length pattern check",
1709
+ load: () => import("./tools/data-validator.js"),
1710
+ },
1711
+
1712
+ // ---------- design ----------
1713
+ {
1714
+ id: "color-picker",
1715
+ category: "design",
1716
+ name: "Color Picker",
1717
+ icon: "pipette",
1718
+ note: "Pick a color and read its codes.",
1719
+ about: "Shows hex, rgb and hsl for any color you choose.",
1720
+ tutorial: {
1721
+ intro: "Pick a color and read its codes.",
1722
+ steps: [
1723
+ "Pick a color, or type a hex value.",
1724
+ "The hex, rgb and hsl values appear.",
1725
+ "Click any value to copy it.",
1726
+ ],
1727
+ },
1728
+ keywords: "color picker hex rgb hsl palette",
1729
+ load: () => import("./tools/color-picker.js"),
1730
+ },
1731
+ {
1732
+ id: "color-palette",
1733
+ category: "design",
1734
+ name: "Color Palette",
1735
+ icon: "palette",
1736
+ note: "Build a matching set of colors.",
1737
+ about: "Analogous, complementary and monochrome schemes from one base color.",
1738
+ tutorial: {
1739
+ intro: "Build a palette from a base color.",
1740
+ steps: [
1741
+ "Pick a base color and a scheme.",
1742
+ "The palette appears with each color's hex.",
1743
+ "Copy one color or the whole set as CSS variables.",
1744
+ ],
1745
+ },
1746
+ keywords: "palette scheme analogous complementary monochrome",
1747
+ load: () => import("./tools/color-palette.js"),
1748
+ },
1749
+ {
1750
+ id: "gradient-generator",
1751
+ category: "design",
1752
+ name: "Gradient Generator",
1753
+ icon: "blend",
1754
+ note: "Make a CSS gradient.",
1755
+ about: "Linear or radial, with color stops you control.",
1756
+ tutorial: {
1757
+ intro: "Make a CSS gradient.",
1758
+ steps: [
1759
+ "Pick linear or radial and set the angle.",
1760
+ "Add color stops and set each one's color and position.",
1761
+ "Copy the CSS gradient value.",
1762
+ ],
1763
+ },
1764
+ keywords: "gradient css linear radial color stop",
1765
+ load: () => import("./tools/gradient-generator.js"),
1766
+ },
1767
+ {
1768
+ id: "box-shadow",
1769
+ category: "design",
1770
+ name: "Box Shadow",
1771
+ icon: "square-dashed-bottom",
1772
+ note: "Build a CSS box-shadow.",
1773
+ about: "Set the offset, blur, spread and color with a live preview.",
1774
+ tutorial: {
1775
+ intro: "Build a CSS box-shadow.",
1776
+ steps: [
1777
+ "Move the sliders for offset, blur and spread.",
1778
+ "Pick the color and toggle an inset shadow.",
1779
+ "Copy the CSS value.",
1780
+ ],
1781
+ },
1782
+ keywords: "box shadow css offset blur spread elevation",
1783
+ load: () => import("./tools/box-shadow.js"),
1784
+ },
1785
+ {
1786
+ id: "border-radius",
1787
+ category: "design",
1788
+ name: "Border Radius",
1789
+ icon: "rectangle-horizontal",
1790
+ note: "Round the corners of a box.",
1791
+ about: "Set each corner on its own with a live preview.",
1792
+ tutorial: {
1793
+ intro: "Round the corners of a box.",
1794
+ steps: [
1795
+ "Move each corner slider, or link them.",
1796
+ "The preview updates as you change a value.",
1797
+ "Copy the CSS border-radius value.",
1798
+ ],
1799
+ },
1800
+ keywords: "border radius corner css rounded",
1801
+ load: () => import("./tools/border-radius.js"),
1802
+ },
1803
+ {
1804
+ id: "contrast-checker",
1805
+ category: "design",
1806
+ name: "Contrast Checker",
1807
+ icon: "contrast",
1808
+ note: "Check text contrast against WCAG.",
1809
+ about: "Reads the ratio and the AA and AAA pass or fail for text and large text.",
1810
+ tutorial: {
1811
+ intro: "Check the contrast between text and background colors.",
1812
+ steps: [
1813
+ "Pick the text and background colors.",
1814
+ "The contrast ratio and the WCAG results appear.",
1815
+ "Swap the colors with one press.",
1816
+ ],
1817
+ },
1818
+ keywords: "contrast wcag accessibility ratio text background aa aaa",
1819
+ load: () => import("./tools/contrast-checker.js"),
1820
+ },
1821
+ {
1822
+ id: "aspect-ratio",
1823
+ category: "design",
1824
+ name: "Aspect Ratio",
1825
+ icon: "ratio",
1826
+ note: "Work out sizes from a ratio.",
1827
+ about: "Simplifies a ratio and finds a missing width or height.",
1828
+ tutorial: {
1829
+ intro: "Work out a size from an aspect ratio.",
1830
+ steps: [
1831
+ "Enter a width and height, or a ratio.",
1832
+ "Set one new side to find the other.",
1833
+ "The simplified ratio and the missing side appear.",
1834
+ ],
1835
+ },
1836
+ keywords: "aspect ratio width height resize thumbnail",
1837
+ load: () => import("./tools/aspect-ratio.js"),
1838
+ },
1839
+ {
1840
+ id: "css-clamp",
1841
+ category: "design",
1842
+ name: "CSS Clamp",
1843
+ icon: "scaling",
1844
+ note: "Build a fluid size with clamp().",
1845
+ about: "Sets a minimum, a preferred viewport width and a maximum.",
1846
+ tutorial: {
1847
+ intro: "Build a fluid size with the CSS clamp function.",
1848
+ steps: [
1849
+ "Set the minimum, the preferred width and the maximum.",
1850
+ "The clamp value and a sample appear.",
1851
+ "Copy the CSS declaration.",
1852
+ ],
1853
+ },
1854
+ keywords: "clamp fluid responsive font size css",
1855
+ load: () => import("./tools/css-clamp.js"),
1856
+ },
1857
+ {
1858
+ id: "css-grid",
1859
+ category: "design",
1860
+ name: "CSS Grid",
1861
+ icon: "layout-grid",
1862
+ note: "Lay out a CSS grid.",
1863
+ about: "Sets the columns, rows and gaps with a live preview.",
1864
+ tutorial: {
1865
+ intro: "Lay out a CSS grid.",
1866
+ steps: [
1867
+ "Set the column and row counts and the gaps.",
1868
+ "The preview updates as you change a value.",
1869
+ "Copy the CSS grid declarations.",
1870
+ ],
1871
+ },
1872
+ keywords: "css grid columns rows gap layout",
1873
+ load: () => import("./tools/css-grid.js"),
1874
+ },
1875
+ {
1876
+ id: "font-pairing",
1877
+ category: "design",
1878
+ name: "Font Pairing",
1879
+ icon: "type-outline",
1880
+ note: "Preview a heading and body font pair.",
1881
+ about: "Uses the fonts already on your system to show a pairing.",
1882
+ tutorial: {
1883
+ intro: "Preview a heading and body font pair.",
1884
+ steps: [
1885
+ "Pick a heading font and a body font.",
1886
+ "Set the sizes, weight and line height.",
1887
+ "Read the sample, then copy the CSS font stacks.",
1888
+ ],
1889
+ },
1890
+ keywords: "font pairing typography heading body preview",
1891
+ load: () => import("./tools/font-pairing.js"),
1892
+ },
1893
+
1894
+ // ---------- web and seo ----------
1895
+ {
1896
+ id: "meta-tags",
1897
+ category: "seo",
1898
+ name: "Meta Tags",
1899
+ icon: "globe",
1900
+ note: "Build the basic SEO tags.",
1901
+ about: "Title, description, canonical and robots, with a length reading.",
1902
+ tutorial: {
1903
+ intro: "Build the basic meta tags for a page.",
1904
+ steps: [
1905
+ "Enter the title and description.",
1906
+ "Add a canonical URL and a robots value if you need them.",
1907
+ "Copy the HTML tags.",
1908
+ ],
1909
+ },
1910
+ keywords: "meta tags seo title description canonical robots",
1911
+ load: () => import("./tools/meta-tags.js"),
1912
+ },
1913
+ {
1914
+ id: "open-graph",
1915
+ category: "seo",
1916
+ name: "Open Graph Tags",
1917
+ icon: "external-link",
1918
+ note: "Build link preview tags.",
1919
+ about: "Open Graph tags for the title, description, URL and image.",
1920
+ tutorial: {
1921
+ intro: "Build Open Graph tags for a link preview.",
1922
+ steps: [
1923
+ "Fill in the title, description, URL and image.",
1924
+ "Pick a content type.",
1925
+ "Copy the tags. How they appear depends on each platform.",
1926
+ ],
1927
+ },
1928
+ keywords: "open graph og social preview twitter card metadata",
1929
+ load: () => import("./tools/open-graph.js"),
1930
+ },
1931
+ {
1932
+ id: "robots-txt",
1933
+ category: "seo",
1934
+ name: "Robots.txt",
1935
+ icon: "file-text",
1936
+ note: "Write a robots.txt file.",
1937
+ about: "Sets user-agent, allow, disallow and sitemap rules.",
1938
+ tutorial: {
1939
+ intro: "Write a robots.txt file.",
1940
+ steps: [
1941
+ "Add allow and disallow rules for a user agent.",
1942
+ "Add a sitemap URL if you have one.",
1943
+ "Copy the file.",
1944
+ ],
1945
+ },
1946
+ keywords: "robots txt crawler allow disallow sitemap",
1947
+ load: () => import("./tools/robots-txt.js"),
1948
+ },
1949
+ {
1950
+ id: "sitemap-xml",
1951
+ category: "seo",
1952
+ name: "Sitemap XML",
1953
+ icon: "code-xml",
1954
+ note: "Build a sitemap from URLs.",
1955
+ about: "Turns a list of URLs into sitemap XML.",
1956
+ tutorial: {
1957
+ intro: "Build a sitemap XML file from a list of URLs.",
1958
+ steps: [
1959
+ "Paste one URL per line.",
1960
+ "Add a last modified date if you have one.",
1961
+ "Copy or download the XML.",
1962
+ ],
1963
+ },
1964
+ keywords: "sitemap xml urls seo crawl",
1965
+ load: () => import("./tools/sitemap-xml.js"),
1966
+ },
1967
+ {
1968
+ id: "url-parser",
1969
+ category: "seo",
1970
+ name: "URL Parser",
1971
+ icon: "link-2",
1972
+ note: "Break a URL into its parts.",
1973
+ about: "Shows the protocol, host, path, query and fragment.",
1974
+ tutorial: {
1975
+ intro: "Break a URL into its parts.",
1976
+ steps: [
1977
+ "Paste a URL.",
1978
+ "Each part appears, with the query split into pairs.",
1979
+ ],
1980
+ },
1981
+ keywords: "url parse components query params host path",
1982
+ load: () => import("./tools/url-parser.js"),
1983
+ },
1984
+ {
1985
+ id: "query-builder",
1986
+ category: "seo",
1987
+ name: "Query Builder",
1988
+ icon: "list",
1989
+ note: "Build a query string.",
1990
+ about: "Add key and value pairs and read the full URL.",
1991
+ tutorial: {
1992
+ intro: "Build a query string from key and value pairs.",
1993
+ steps: [
1994
+ "Enter a base URL.",
1995
+ "Add key and value pairs.",
1996
+ "Copy the full URL.",
1997
+ ],
1998
+ },
1999
+ keywords: "query string params url builder key value",
2000
+ load: () => import("./tools/query-builder.js"),
2001
+ },
2002
+ {
2003
+ id: "canonical-tag",
2004
+ category: "seo",
2005
+ name: "Canonical Tag",
2006
+ icon: "link-2",
2007
+ note: "Build a canonical link tag.",
2008
+ about: "Validates the URL and writes the link element.",
2009
+ tutorial: {
2010
+ intro: "Build a canonical link tag.",
2011
+ steps: [
2012
+ "Enter the canonical URL.",
2013
+ "Copy the link element.",
2014
+ ],
2015
+ },
2016
+ keywords: "canonical url link rel seo duplicate",
2017
+ load: () => import("./tools/canonical-tag.js"),
2018
+ },
2019
+ {
2020
+ id: "favicon-markup",
2021
+ category: "seo",
2022
+ name: "Favicon Markup",
2023
+ icon: "image-up",
2024
+ note: "Write the favicon link tags.",
2025
+ about: "Points at icon files you already have.",
2026
+ tutorial: {
2027
+ intro: "Write the favicon link tags for a site.",
2028
+ steps: [
2029
+ "Enter the path to each icon file you have.",
2030
+ "Copy the link tags for the head.",
2031
+ ],
2032
+ },
2033
+ keywords: "favicon icon link apple touch manifest head",
2034
+ load: () => import("./tools/favicon-markup.js"),
2035
+ },
2036
+ {
2037
+ id: "http-status",
2038
+ category: "seo",
2039
+ name: "HTTP Status Codes",
2040
+ icon: "search",
2041
+ note: "Look up an HTTP status code.",
2042
+ about: "The common 2xx, 3xx, 4xx and 5xx codes with a short meaning.",
2043
+ tutorial: {
2044
+ intro: "Look up what an HTTP status code means.",
2045
+ steps: [
2046
+ "Filter by number or by class.",
2047
+ "Read the meaning and a typical case.",
2048
+ ],
2049
+ },
2050
+ keywords: "http status code 404 500 reference",
2051
+ load: () => import("./tools/http-status.js"),
2052
+ },
2053
+ {
2054
+ id: "mime-types",
2055
+ category: "seo",
2056
+ name: "MIME Types",
2057
+ icon: "file-code",
2058
+ note: "Find a MIME type by extension.",
2059
+ about: "Common file extensions and their content types.",
2060
+ tutorial: {
2061
+ intro: "Find the MIME type for a file extension.",
2062
+ steps: [
2063
+ "Type an extension or a type.",
2064
+ "Read the matching content type.",
2065
+ ],
2066
+ },
2067
+ keywords: "mime type content-type extension reference",
2068
+ load: () => import("./tools/mime-types.js"),
2069
+ },
2070
+ {
2071
+ id: "meta-preview",
2072
+ category: "seo",
2073
+ name: "Search Preview",
2074
+ icon: "search",
2075
+ note: "Preview a search result.",
2076
+ about: "Shows how a title and description might look in search.",
2077
+ tutorial: {
2078
+ intro: "Preview how a title and description might look in search results.",
2079
+ steps: [
2080
+ "Enter a title, a URL and a description.",
2081
+ "The preview and the lengths appear.",
2082
+ ],
2083
+ },
2084
+ keywords: "search preview serp title description snippet",
2085
+ load: () => import("./tools/meta-preview.js"),
2086
+ },
2087
+ {
2088
+ id: "slug-preview",
2089
+ category: "seo",
2090
+ name: "Slug Preview",
2091
+ icon: "link-2",
2092
+ note: "Build and check a page slug.",
2093
+ about: "Turns a title into a slug and shows the full path.",
2094
+ tutorial: {
2095
+ intro: "Build and check a page slug.",
2096
+ steps: [
2097
+ "Enter a title and a site address.",
2098
+ "Pick the separator.",
2099
+ "The slug and the full URL appear.",
2100
+ ],
2101
+ },
2102
+ keywords: "slug url path seo permalink preview",
2103
+ load: () => import("./tools/slug-preview.js"),
2104
+ },
2105
+
2106
+ // ---------- encoding ----------
2107
+ {
2108
+ id: "unicode-inspector",
2109
+ category: "encoding",
2110
+ name: "Unicode Inspector",
2111
+ icon: "scan-text",
2112
+ note: "See the code point behind each character.",
2113
+ about: "Lists each character with its code point and UTF-8 bytes.",
2114
+ tutorial: {
2115
+ intro: "See the code point behind each character.",
2116
+ steps: [
2117
+ "Type or paste text.",
2118
+ "Each character is listed with its code point and bytes.",
2119
+ "Useful for spotting characters that look the same but are not.",
2120
+ ],
2121
+ },
2122
+ keywords: "unicode code point character utf-8 inspect homoglyph",
2123
+ load: () => import("./tools/unicode-inspector.js"),
2124
+ },
2125
+ {
2126
+ id: "utf8-bytes",
2127
+ category: "encoding",
2128
+ name: "UTF-8 Byte Counter",
2129
+ icon: "binary",
2130
+ note: "Measure the byte size of text.",
2131
+ about: "Counts characters and UTF-8 bytes side by side.",
2132
+ tutorial: {
2133
+ intro: "Measure the byte size of text.",
2134
+ steps: [
2135
+ "Type or paste text.",
2136
+ "The character and byte counts appear.",
2137
+ "Emoji and accents take more than one byte.",
2138
+ ],
2139
+ },
2140
+ keywords: "utf-8 bytes size characters payload emoji",
2141
+ load: () => import("./tools/utf8-bytes.js"),
2142
+ },
2143
+ {
2144
+ id: "html-to-text",
2145
+ category: "encoding",
2146
+ name: "HTML to Text",
2147
+ icon: "file-text",
2148
+ note: "Strip tags and keep the text.",
2149
+ about: "Removes HTML tags and keeps readable text.",
2150
+ tutorial: {
2151
+ intro: "Strip HTML tags and keep the text.",
2152
+ steps: [
2153
+ "Paste HTML.",
2154
+ "The plain text appears.",
2155
+ "Copy the text.",
2156
+ ],
2157
+ },
2158
+ keywords: "html strip tags plain text extract",
2159
+ load: () => import("./tools/html-to-text.js"),
2160
+ },
2161
+ {
2162
+ id: "markdown-to-text",
2163
+ category: "encoding",
2164
+ name: "Markdown to Text",
2165
+ icon: "pilcrow",
2166
+ note: "Strip Markdown and keep the text.",
2167
+ about: "Removes Markdown syntax and keeps the words.",
2168
+ tutorial: {
2169
+ intro: "Strip Markdown syntax and keep the text.",
2170
+ steps: [
2171
+ "Paste Markdown.",
2172
+ "The plain text appears.",
2173
+ "Copy the text.",
2174
+ ],
2175
+ },
2176
+ keywords: "markdown strip plain text remove syntax",
2177
+ load: () => import("./tools/markdown-to-text.js"),
2178
+ },
2179
+ {
2180
+ id: "unicode-escape",
2181
+ category: "encoding",
2182
+ name: "Unicode Escape",
2183
+ icon: "code",
2184
+ note: "Escape text to code points and back.",
2185
+ about: "Turns characters into escape sequences and back.",
2186
+ tutorial: {
2187
+ intro: "Turn characters into Unicode escape sequences, or decode them.",
2188
+ steps: [
2189
+ "Pick Encode or Decode.",
2190
+ "Type or paste your text.",
2191
+ "Copy the result.",
2192
+ ],
2193
+ },
2194
+ keywords: "unicode escape decode \\u code point",
2195
+ load: () => import("./tools/unicode-escape.js"),
2196
+ },
2197
+ {
2198
+ id: "json-escape",
2199
+ category: "encoding",
2200
+ name: "JSON String Escape",
2201
+ icon: "braces",
2202
+ note: "Escape text for a JSON string.",
2203
+ about: "Escapes quotes, backslashes and control characters, or unescapes them.",
2204
+ tutorial: {
2205
+ intro: "Escape text so it is safe inside a JSON string.",
2206
+ steps: [
2207
+ "Pick Escape or Unescape.",
2208
+ "Type or paste your text.",
2209
+ "Copy the result.",
2210
+ ],
2211
+ },
2212
+ keywords: "json escape string quotes backslash unescape",
2213
+ load: () => import("./tools/json-escape.js"),
2214
+ },
2215
+ {
2216
+ id: "xml-formatter",
2217
+ category: "encoding",
2218
+ name: "XML Formatter",
2219
+ icon: "code-xml",
2220
+ note: "Indent an XML document.",
2221
+ about: "Reindents elements and checks that tags close.",
2222
+ tutorial: {
2223
+ intro: "Indent an XML document by nesting.",
2224
+ steps: [
2225
+ "Paste XML.",
2226
+ "Pick the indent size.",
2227
+ "Copy the formatted XML.",
2228
+ ],
2229
+ },
2230
+ keywords: "xml format indent beautify markup",
2231
+ load: () => import("./tools/xml-formatter.js"),
2232
+ },
2233
+ {
2234
+ id: "yaml-formatter",
2235
+ category: "encoding",
2236
+ name: "YAML Checker",
2237
+ icon: "file-code",
2238
+ note: "Check YAML indentation and structure.",
2239
+ about: "Flags indentation and syntax problems in a small YAML subset.",
2240
+ tutorial: {
2241
+ intro: "Check a YAML document for indentation and structure problems.",
2242
+ steps: [
2243
+ "Paste YAML.",
2244
+ "Problems are listed with their line numbers.",
2245
+ "A clean document reports no problems.",
2246
+ ],
2247
+ },
2248
+ keywords: "yaml check indent syntax validate config",
2249
+ load: () => import("./tools/yaml-formatter.js"),
2250
+ },
2251
+
2252
+ // ---------- academic ----------
2253
+ {
2254
+ id: "apa-reference",
2255
+ category: "academic",
2256
+ name: "APA 7 Reference",
2257
+ icon: "graduation-cap",
2258
+ note: "Build an APA 7 reference.",
2259
+ about: "Books, journal articles, chapters and web pages in APA 7.",
2260
+ tutorial: {
2261
+ intro: "Build an APA 7 reference from source details.",
2262
+ steps: [
2263
+ "Pick the source type and fill the fields.",
2264
+ "The reference and the in-text citation appear.",
2265
+ "Check the details against the source before you submit.",
2266
+ ],
2267
+ },
2268
+ keywords: "apa 7 reference citation bibliography",
2269
+ load: () => import("./tools/apa-reference.js"),
2270
+ },
2271
+ {
2272
+ id: "mla-citation",
2273
+ category: "academic",
2274
+ name: "MLA Citation",
2275
+ icon: "text-quote",
2276
+ note: "Build an MLA works cited entry.",
2277
+ about: "Books, articles, web pages and video in MLA style.",
2278
+ tutorial: {
2279
+ intro: "Build an MLA works cited entry.",
2280
+ steps: [
2281
+ "Pick the source type and fill the fields.",
2282
+ "The entry appears in MLA order.",
2283
+ "Check the details against the source before you submit.",
2284
+ ],
2285
+ },
2286
+ keywords: "mla citation works cited bibliography",
2287
+ load: () => import("./tools/mla-citation.js"),
2288
+ },
2289
+ {
2290
+ id: "ieee-reference",
2291
+ category: "academic",
2292
+ name: "IEEE Reference",
2293
+ icon: "list-ordered",
2294
+ note: "Build an IEEE reference and its number.",
2295
+ about: "Numbered references for books, journals and conferences.",
2296
+ tutorial: {
2297
+ intro: "Build an IEEE reference with its number.",
2298
+ steps: [
2299
+ "Pick the source type and set the number.",
2300
+ "Fill the fields.",
2301
+ "Copy the reference and the bracketed citation.",
2302
+ ],
2303
+ },
2304
+ keywords: "ieee reference citation numbered bibliography",
2305
+ load: () => import("./tools/ieee-reference.js"),
2306
+ },
2307
+ {
2308
+ id: "harvard-citation",
2309
+ category: "academic",
2310
+ name: "Harvard Citation",
2311
+ icon: "text-quote",
2312
+ note: "Build a Harvard style reference.",
2313
+ about: "Author and year references, with a note that styles vary by institution.",
2314
+ tutorial: {
2315
+ intro: "Build a Harvard style reference.",
2316
+ steps: [
2317
+ "Pick the source type and fill the fields.",
2318
+ "The reference and the in-text citation appear.",
2319
+ "Harvard rules differ between institutions, so check yours.",
2320
+ ],
2321
+ },
2322
+ keywords: "harvard citation author year reference bibliography",
2323
+ load: () => import("./tools/harvard-citation.js"),
2324
+ },
2325
+ {
2326
+ id: "bibtex-generator",
2327
+ category: "academic",
2328
+ name: "BibTeX Generator",
2329
+ icon: "library",
2330
+ note: "Build a BibTeX entry.",
2331
+ about: "Article, book and inproceedings entries with a citation key.",
2332
+ tutorial: {
2333
+ intro: "Build a BibTeX entry for a reference.",
2334
+ steps: [
2335
+ "Pick the entry type and fill the fields.",
2336
+ "The entry and its citation key appear.",
2337
+ "Copy or download the .bib entry.",
2338
+ ],
2339
+ },
2340
+ keywords: "bibtex latex reference citation key article book",
2341
+ load: () => import("./tools/bibtex-generator.js"),
2342
+ },
2343
+ {
2344
+ id: "doi-resolver",
2345
+ category: "academic",
2346
+ name: "DOI Resolver",
2347
+ icon: "link-2",
2348
+ note: "Tidy a DOI and build its link.",
2349
+ about: "Cleans a DOI and writes the resolver URL.",
2350
+ tutorial: {
2351
+ intro: "Tidy a DOI and build its resolver link.",
2352
+ steps: [
2353
+ "Paste a DOI, with or without the resolver prefix.",
2354
+ "The cleaned DOI and the link appear.",
2355
+ "A matching pattern does not prove the DOI is registered.",
2356
+ ],
2357
+ },
2358
+ keywords: "doi resolver link clean reference",
2359
+ load: () => import("./tools/doi-resolver.js"),
2360
+ },
2361
+ {
2362
+ id: "intext-citation",
2363
+ category: "academic",
2364
+ name: "In-Text Citation",
2365
+ icon: "text-quote",
2366
+ note: "Format an in-text citation.",
2367
+ about: "Author and year, or numeric, in narrative or parenthetical form.",
2368
+ tutorial: {
2369
+ intro: "Format a citation for inside the text.",
2370
+ steps: [
2371
+ "Enter the author, year and page.",
2372
+ "Pick the style and the form.",
2373
+ "Copy the citation.",
2374
+ ],
2375
+ },
2376
+ keywords: "in-text citation parenthetical narrative author year",
2377
+ load: () => import("./tools/intext-citation.js"),
2378
+ },
2379
+ {
2380
+ id: "bibliography-sorter",
2381
+ category: "academic",
2382
+ name: "Bibliography Sorter",
2383
+ icon: "arrow-down-a-z",
2384
+ note: "Sort a reference list.",
2385
+ about: "Orders references by the first author name.",
2386
+ tutorial: {
2387
+ intro: "Sort a reference list alphabetically.",
2388
+ steps: [
2389
+ "Paste one reference per line or per block.",
2390
+ "Pick the direction.",
2391
+ "Copy the sorted list.",
2392
+ ],
2393
+ },
2394
+ keywords: "bibliography sort references alphabetical order",
2395
+ load: () => import("./tools/bibliography-sorter.js"),
2396
+ },
2397
+ {
2398
+ id: "citation-number-check",
2399
+ category: "academic",
2400
+ name: "Citation Number Check",
2401
+ icon: "hash",
2402
+ note: "Find gaps in numbered citations.",
2403
+ about: "Flags citation numbers with no matching reference and the reverse.",
2404
+ tutorial: {
2405
+ intro: "Check numbered citations against a reference list.",
2406
+ steps: [
2407
+ "Paste the text with citations like [1].",
2408
+ "Paste the reference list, one per line.",
2409
+ "Missing and unused numbers are listed.",
2410
+ ],
2411
+ },
2412
+ keywords: "citation number reference check missing unused",
2413
+ load: () => import("./tools/citation-number-check.js"),
2414
+ },
2415
+ {
2416
+ id: "word-limit",
2417
+ category: "academic",
2418
+ name: "Word Limit Checker",
2419
+ icon: "text-cursor-input",
2420
+ note: "Check text against a word range.",
2421
+ about: "Counts words and shows the room left between a minimum and a maximum.",
2422
+ tutorial: {
2423
+ intro: "Check text against a word limit.",
2424
+ steps: [
2425
+ "Paste the text.",
2426
+ "Set the minimum and maximum.",
2427
+ "The count and the room left appear.",
2428
+ ],
2429
+ },
2430
+ keywords: "word limit abstract minimum maximum count essay",
2431
+ load: () => import("./tools/word-limit.js"),
2432
+ },
2433
+ {
2434
+ id: "abstract-checklist",
2435
+ category: "academic",
2436
+ name: "Abstract Checklist",
2437
+ icon: "clipboard-check",
2438
+ note: "Check an abstract's structure.",
2439
+ about: "Ticks the usual parts: background, aim, method, results, conclusion.",
2440
+ tutorial: {
2441
+ intro: "Check the structure of a research abstract.",
2442
+ steps: [
2443
+ "Paste the abstract.",
2444
+ "Tick each part you can find.",
2445
+ "The word count is shown. This does not judge quality.",
2446
+ ],
2447
+ },
2448
+ keywords: "abstract checklist structure research background method",
2449
+ load: () => import("./tools/abstract-checklist.js"),
2450
+ },
2451
+ {
2452
+ id: "heading-formatter",
2453
+ category: "academic",
2454
+ name: "Heading Formatter",
2455
+ icon: "list-ordered",
2456
+ note: "Number chapter and section headings.",
2457
+ about: "Adds numbers like 1.1 and 1.1.1 to a list of headings.",
2458
+ tutorial: {
2459
+ intro: "Number a list of chapter and section headings.",
2460
+ steps: [
2461
+ "Paste one heading per line.",
2462
+ "Pick the starting number.",
2463
+ "Copy the numbered headings.",
2464
+ ],
2465
+ },
2466
+ keywords: "heading number chapter section outline format",
2467
+ load: () => import("./tools/heading-formatter.js"),
2468
+ },
2469
+ {
2470
+ id: "reference-completeness",
2471
+ category: "academic",
2472
+ name: "Reference Completeness",
2473
+ icon: "clipboard-check",
2474
+ note: "Check a reference for missing parts.",
2475
+ about: "Flags a reference that is missing author, year, title or source.",
2476
+ tutorial: {
2477
+ intro: "Check whether a reference has the usual parts.",
2478
+ steps: [
2479
+ "Paste one reference.",
2480
+ "The parts found and the parts missing are listed.",
2481
+ "A complete reference is not proof the source is real.",
2482
+ ],
2483
+ },
2484
+ keywords: "reference completeness author year title check",
2485
+ load: () => import("./tools/reference-completeness.js"),
2486
+ },
2487
+ {
2488
+ id: "quotation-formatter",
2489
+ category: "academic",
2490
+ name: "Quotation Formatter",
2491
+ icon: "text-quote",
2492
+ note: "Format a direct or indirect quote.",
2493
+ about: "Builds a block or inline quote with its citation.",
2494
+ tutorial: {
2495
+ intro: "Format a direct or indirect quotation.",
2496
+ steps: [
2497
+ "Paste the quoted text and set the author, year and page.",
2498
+ "Pick direct or paraphrase.",
2499
+ "Copy the formatted quote. Check your institution's rules.",
2500
+ ],
2501
+ },
2502
+ keywords: "quotation quote block direct paraphrase citation",
2503
+ load: () => import("./tools/quotation-formatter.js"),
2504
+ },
2505
+ {
2506
+ id: "citation-metadata",
2507
+ category: "academic",
2508
+ name: "Citation Metadata",
2509
+ icon: "notebook-pen",
2510
+ note: "Collect source details in one form.",
2511
+ about: "One form per source type, ready to feed a citation tool.",
2512
+ tutorial: {
2513
+ intro: "Collect the details of a source in one form.",
2514
+ steps: [
2515
+ "Pick the source type.",
2516
+ "Fill the fields you have.",
2517
+ "Copy the details, or the JSON, for a citation tool.",
2518
+ ],
2519
+ },
2520
+ keywords: "citation metadata form source fields author doi",
2521
+ load: () => import("./tools/citation-metadata.js"),
2522
+ },
2523
+
2524
+ // ---------- study ----------
2525
+ {
2526
+ id: "flashcard-creator",
2527
+ category: "education",
2528
+ name: "Flashcard Creator",
2529
+ icon: "layers",
2530
+ note: "Make question and answer cards.",
2531
+ about: "Flip through cards and export them as text or JSON.",
2532
+ tutorial: {
2533
+ intro: "Make a set of question and answer cards.",
2534
+ steps: [
2535
+ "Add a question and its answer.",
2536
+ "Flip through the cards to study.",
2537
+ "Export the set as text or JSON.",
2538
+ ],
2539
+ },
2540
+ keywords: "flashcard study question answer revise cards",
2541
+ load: () => import("./tools/flashcard-creator.js"),
2542
+ },
2543
+ {
2544
+ id: "quiz-formatter",
2545
+ category: "education",
2546
+ name: "Quiz Formatter",
2547
+ icon: "list-checks",
2548
+ note: "Tidy multiple choice questions.",
2549
+ about: "Lays out questions and options, and can separate the answer key.",
2550
+ tutorial: {
2551
+ intro: "Tidy a set of multiple choice questions.",
2552
+ steps: [
2553
+ "Paste questions and options.",
2554
+ "The output is laid out as A, B, C.",
2555
+ "Copy the quiz or the answer key.",
2556
+ ],
2557
+ },
2558
+ keywords: "quiz multiple choice questions options answer key",
2559
+ load: () => import("./tools/quiz-formatter.js"),
2560
+ },
2561
+ {
2562
+ id: "grade-calculator",
2563
+ category: "education",
2564
+ name: "Grade Calculator",
2565
+ icon: "graduation-cap",
2566
+ note: "Work out a final grade.",
2567
+ about: "Weighted components with a check that the weights add up.",
2568
+ tutorial: {
2569
+ intro: "Work out a final grade from weighted components.",
2570
+ steps: [
2571
+ "Add each component with its score and weight.",
2572
+ "The weighted result appears.",
2573
+ "The total weight is checked against 100.",
2574
+ ],
2575
+ },
2576
+ keywords: "grade calculator weighted components final score",
2577
+ load: () => import("./tools/grade-calculator.js"),
2578
+ },
2579
+ {
2580
+ id: "gpa-calculator",
2581
+ category: "education",
2582
+ name: "GPA Calculator",
2583
+ icon: "graduation-cap",
2584
+ note: "Work out a GPA from courses.",
2585
+ about: "Credit weighted grade points, with a scale you can set.",
2586
+ tutorial: {
2587
+ intro: "Work out a GPA from courses.",
2588
+ steps: [
2589
+ "Add each course with its credits and grade.",
2590
+ "Pick the grade scale.",
2591
+ "The GPA and the total credits appear.",
2592
+ ],
2593
+ },
2594
+ keywords: "gpa grade point average credits semester",
2595
+ load: () => import("./tools/gpa-calculator.js"),
2596
+ },
2597
+ {
2598
+ id: "study-schedule",
2599
+ category: "education",
2600
+ name: "Study Schedule",
2601
+ icon: "calendar-days",
2602
+ note: "Spread topics across study sessions.",
2603
+ about: "Assigns topics to dates you set and tracks progress.",
2604
+ tutorial: {
2605
+ intro: "Spread topics across study sessions.",
2606
+ steps: [
2607
+ "Add topics and a target date.",
2608
+ "Assign each topic to a session.",
2609
+ "Tick topics off as you finish them.",
2610
+ ],
2611
+ },
2612
+ keywords: "study schedule plan topics sessions exam",
2613
+ load: () => import("./tools/study-schedule.js"),
2614
+ },
2615
+ {
2616
+ id: "equation-formatter",
2617
+ category: "education",
2618
+ name: "Equation Formatter",
2619
+ icon: "square-function",
2620
+ note: "Preview a LaTeX equation.",
2621
+ about: "Shows a plain preview of common LaTeX math, with the source.",
2622
+ tutorial: {
2623
+ intro: "Preview a LaTeX equation.",
2624
+ steps: [
2625
+ "Type LaTeX like \\frac{a}{b}.",
2626
+ "A plain preview appears next to the source.",
2627
+ "Copy the LaTeX.",
2628
+ ],
2629
+ },
2630
+ keywords: "latex equation math formula preview fraction",
2631
+ load: () => import("./tools/equation-formatter.js"),
2632
+ },
2633
+ {
2634
+ id: "sequence-analyzer",
2635
+ category: "education",
2636
+ name: "Number Sequence Analyzer",
2637
+ icon: "chart-line",
2638
+ note: "Look for a pattern in a number series.",
2639
+ about: "Checks the differences and common simple patterns.",
2640
+ tutorial: {
2641
+ intro: "Look for a pattern in a series of numbers.",
2642
+ steps: [
2643
+ "Paste numbers separated by spaces or commas.",
2644
+ "The differences and any simple pattern are shown.",
2645
+ "One series can fit more than one pattern.",
2646
+ ],
2647
+ },
2648
+ keywords: "sequence series pattern arithmetic geometric difference",
2649
+ load: () => import("./tools/sequence-analyzer.js"),
2650
+ },
2651
+
2652
+ // ---------- business ----------
2653
+ {
2654
+ id: "hpp-calculator",
2655
+ category: "business",
2656
+ name: "Cost per Unit",
2657
+ icon: "receipt",
2658
+ note: "Work out the cost to make one unit.",
2659
+ about: "Adds materials, labour and overhead, then divides by the units made.",
2660
+ tutorial: {
2661
+ intro: "Work out the cost to make one unit.",
2662
+ steps: [
2663
+ "Enter the material, labour and overhead costs.",
2664
+ "Enter the number of units.",
2665
+ "The total cost and the cost per unit appear.",
2666
+ ],
2667
+ },
2668
+ keywords: "hpp cost per unit production overhead material",
2669
+ load: () => import("./tools/hpp-calculator.js"),
2670
+ },
2671
+ {
2672
+ id: "selling-price",
2673
+ category: "business",
2674
+ name: "Selling Price",
2675
+ icon: "tag",
2676
+ note: "Set a price from cost and target margin.",
2677
+ about: "Works from a target margin or a markup.",
2678
+ tutorial: {
2679
+ intro: "Set a selling price from a cost and a target.",
2680
+ steps: [
2681
+ "Enter the cost per unit.",
2682
+ "Pick a target margin or markup and set the value.",
2683
+ "The selling price and the profit appear.",
2684
+ ],
2685
+ },
2686
+ keywords: "selling price cost margin markup business",
2687
+ load: () => import("./tools/selling-price.js"),
2688
+ },
2689
+ {
2690
+ id: "break-even",
2691
+ category: "business",
2692
+ name: "Break-Even Point",
2693
+ icon: "scale",
2694
+ note: "Find the point where a business breaks even.",
2695
+ about: "Units and revenue needed to cover fixed costs.",
2696
+ tutorial: {
2697
+ intro: "Find the break-even point of a product.",
2698
+ steps: [
2699
+ "Enter the fixed costs.",
2700
+ "Enter the price and the variable cost per unit.",
2701
+ "The break-even units and revenue appear.",
2702
+ ],
2703
+ },
2704
+ keywords: "break even point fixed variable cost units revenue",
2705
+ load: () => import("./tools/break-even.js"),
2706
+ },
2707
+ {
2708
+ id: "cash-flow",
2709
+ category: "business",
2710
+ name: "Cash Flow",
2711
+ icon: "banknote",
2712
+ note: "Track money in and out.",
2713
+ about: "Running balance from an opening amount, with a CSV export.",
2714
+ tutorial: {
2715
+ intro: "Track cash in and out from an opening balance.",
2716
+ steps: [
2717
+ "Enter the opening balance.",
2718
+ "Add each income and expense.",
2719
+ "The running balance and the closing total appear.",
2720
+ ],
2721
+ },
2722
+ keywords: "cash flow income expense balance ledger",
2723
+ load: () => import("./tools/cash-flow.js"),
2724
+ },
2725
+ {
2726
+ id: "expense-split",
2727
+ category: "business",
2728
+ name: "Expense Split",
2729
+ icon: "users",
2730
+ note: "Split a bill between people.",
2731
+ about: "Equal or custom shares, with clear rounding.",
2732
+ tutorial: {
2733
+ intro: "Split a bill between people.",
2734
+ steps: [
2735
+ "Enter the total and the people.",
2736
+ "Split equally or set a custom share each.",
2737
+ "Each person's amount appears.",
2738
+ ],
2739
+ },
2740
+ keywords: "expense split bill share divide payment",
2741
+ load: () => import("./tools/expense-split.js"),
2742
+ },
2743
+ {
2744
+ id: "tax-calculator",
2745
+ category: "business",
2746
+ name: "Tax Calculator",
2747
+ icon: "receipt",
2748
+ note: "Work out tax from a rate you enter.",
2749
+ about: "Adds tax to a value or takes it out of a tax-inclusive price.",
2750
+ tutorial: {
2751
+ intro: "Work out tax from a rate you enter.",
2752
+ steps: [
2753
+ "Enter the amount and the rate.",
2754
+ "Pick whether the amount includes tax.",
2755
+ "The tax and the total appear. Use the rate that applies to you.",
2756
+ ],
2757
+ },
2758
+ keywords: "tax vat rate amount inclusive exclusive",
2759
+ load: () => import("./tools/tax-calculator.js"),
2760
+ },
2761
+ {
2762
+ id: "invoice-number",
2763
+ category: "business",
2764
+ name: "Invoice Number",
2765
+ icon: "hash",
2766
+ note: "Build invoice numbers from a pattern.",
2767
+ about: "Prefix, date and a padded counter.",
2768
+ tutorial: {
2769
+ intro: "Build invoice numbers from a pattern.",
2770
+ steps: [
2771
+ "Set the prefix and the pattern.",
2772
+ "Set the starting number and how many to make.",
2773
+ "Copy the numbers. Local numbering is not unique across devices.",
2774
+ ],
2775
+ },
2776
+ keywords: "invoice number pattern prefix sequence",
2777
+ load: () => import("./tools/invoice-number.js"),
2778
+ },
2779
+ {
2780
+ id: "cash-denomination",
2781
+ category: "business",
2782
+ name: "Cash Denomination",
2783
+ icon: "banknote",
2784
+ note: "Count cash by note and coin.",
2785
+ about: "Adds up notes and coins per denomination.",
2786
+ tutorial: {
2787
+ intro: "Count cash by note and coin.",
2788
+ steps: [
2789
+ "Enter how many of each denomination you have.",
2790
+ "The subtotal for each and the total appear.",
2791
+ ],
2792
+ },
2793
+ keywords: "cash denomination notes coins total count money",
2794
+ load: () => import("./tools/cash-denomination.js"),
2795
+ },
2796
+ {
2797
+ id: "sales-commission",
2798
+ category: "business",
2799
+ name: "Sales Commission",
2800
+ icon: "hand-coins",
2801
+ note: "Work out a commission.",
2802
+ about: "Percentage or fixed, with tiers and per-sale detail.",
2803
+ tutorial: {
2804
+ intro: "Work out a sales commission.",
2805
+ steps: [
2806
+ "Enter the sale amounts.",
2807
+ "Set the rate or the tiers.",
2808
+ "The commission per sale and the total appear.",
2809
+ ],
2810
+ },
2811
+ keywords: "commission sales percentage tier incentive",
2812
+ load: () => import("./tools/sales-commission.js"),
2813
+ },
2814
+ {
2815
+ id: "inventory-quantity",
2816
+ category: "business",
2817
+ name: "Inventory Quantity",
2818
+ icon: "package",
2819
+ note: "Work out closing stock.",
2820
+ about: "Opening stock plus in minus out, with a warning for negatives.",
2821
+ tutorial: {
2822
+ intro: "Work out closing stock for items.",
2823
+ steps: [
2824
+ "Enter the opening stock, stock in and stock out.",
2825
+ "The closing stock appears.",
2826
+ "A negative result is flagged.",
2827
+ ],
2828
+ },
2829
+ keywords: "inventory stock quantity opening closing in out",
2830
+ load: () => import("./tools/inventory-quantity.js"),
2831
+ },
2832
+
2833
+ // ---------- locale ----------
2834
+ {
2835
+ id: "reading-time",
2836
+ category: "locale",
2837
+ name: "Reading Time",
2838
+ icon: "book-open",
2839
+ note: "Estimate how long a text takes to read.",
2840
+ about: "Sets a reading speed and shows the time.",
2841
+ tutorial: {
2842
+ intro: "Estimate how long a text takes to read.",
2843
+ steps: [
2844
+ "Paste the text.",
2845
+ "Set the reading speed.",
2846
+ "The time appears. Actual reading speed varies.",
2847
+ ],
2848
+ },
2849
+ keywords: "reading time words per minute estimate article",
2850
+ load: () => import("./tools/reading-time.js"),
2851
+ },
2852
+ {
2853
+ id: "readability",
2854
+ category: "locale",
2855
+ name: "Readability",
2856
+ icon: "scan-text",
2857
+ note: "Score how easy a text is to read.",
2858
+ about: "Uses common readability formulas, with their limits noted.",
2859
+ tutorial: {
2860
+ intro: "Score how easy a text is to read.",
2861
+ steps: [
2862
+ "Paste the text.",
2863
+ "The scores and the counts behind them appear.",
2864
+ "The formulas suit English best, so read the result with care.",
2865
+ ],
2866
+ },
2867
+ keywords: "readability flesch score reading ease grade",
2868
+ load: () => import("./tools/readability.js"),
2869
+ },
2870
+ {
2871
+ id: "sentence-length",
2872
+ category: "locale",
2873
+ name: "Sentence Length",
2874
+ icon: "text-align-start",
2875
+ note: "Find sentences that run long.",
2876
+ about: "Counts words per sentence and flags the longest ones.",
2877
+ tutorial: {
2878
+ intro: "Find sentences that run long.",
2879
+ steps: [
2880
+ "Paste the text.",
2881
+ "Set a length threshold.",
2882
+ "Long sentences and the shortest and longest are listed.",
2883
+ ],
2884
+ },
2885
+ keywords: "sentence length words long editing clarity",
2886
+ load: () => import("./tools/sentence-length.js"),
2887
+ },
2888
+ {
2889
+ id: "locale-number",
2890
+ category: "locale",
2891
+ name: "Number Format",
2892
+ icon: "hash",
2893
+ note: "Format a number for a locale.",
2894
+ about: "Shows the same number in several locales side by side.",
2895
+ tutorial: {
2896
+ intro: "Format a number for a locale.",
2897
+ steps: [
2898
+ "Type a number.",
2899
+ "Pick the decimal and group options.",
2900
+ "The same number appears in several locales.",
2901
+ ],
2902
+ },
2903
+ keywords: "number format locale decimal thousands separator",
2904
+ load: () => import("./tools/locale-number.js"),
2905
+ },
2906
+ {
2907
+ id: "currency-format",
2908
+ category: "locale",
2909
+ name: "Currency Format",
2910
+ icon: "banknote",
2911
+ note: "Show a number as a currency.",
2912
+ about: "Formats a number for a currency and locale, with no rate conversion.",
2913
+ tutorial: {
2914
+ intro: "Show a number as a currency.",
2915
+ steps: [
2916
+ "Type a number.",
2917
+ "Pick the currency and the locale.",
2918
+ "The formatted amount appears. No exchange rate is applied.",
2919
+ ],
2920
+ },
2921
+ keywords: "currency format idr usd locale money display",
2922
+ load: () => import("./tools/currency-format.js"),
2923
+ },
2924
+ {
2925
+ id: "date-format",
2926
+ category: "locale",
2927
+ name: "Date Format",
2928
+ icon: "calendar-days",
2929
+ note: "Convert a date between formats.",
2930
+ about: "Reads ISO or a chosen input format and writes the others.",
2931
+ tutorial: {
2932
+ intro: "Convert a date between formats.",
2933
+ steps: [
2934
+ "Pick the input format and type a date.",
2935
+ "The date in each other format appears.",
2936
+ "Picking the input format avoids a wrong reading of the date.",
2937
+ ],
2938
+ },
2939
+ keywords: "date format iso locale convert parse",
2940
+ load: () => import("./tools/date-format.js"),
2941
+ },
2942
+ {
2943
+ id: "text-direction",
2944
+ category: "locale",
2945
+ name: "Text Direction",
2946
+ icon: "languages",
2947
+ note: "Preview left to right and right to left text.",
2948
+ about: "Shows text under each direction with the HTML to use.",
2949
+ tutorial: {
2950
+ intro: "Preview text in left to right and right to left directions.",
2951
+ steps: [
2952
+ "Type or paste text.",
2953
+ "Pick a direction or use auto.",
2954
+ "The preview and the HTML attribute appear.",
2955
+ ],
2956
+ },
2957
+ keywords: "text direction rtl ltr arabic bidi locale",
2958
+ load: () => import("./tools/text-direction.js"),
2959
+ },
2960
+
2961
+ // ---------- content ----------
2962
+ {
2963
+ id: "caption-counter",
2964
+ category: "content",
2965
+ name: "Caption Counter",
2966
+ icon: "text-cursor",
2967
+ note: "Check a caption against a limit.",
2968
+ about: "Counts characters and lines and shows what is left.",
2969
+ tutorial: {
2970
+ intro: "Check a caption against a character limit.",
2971
+ steps: [
2972
+ "Type or paste the caption.",
2973
+ "Set the limit if you have one.",
2974
+ "The counts and the room left appear.",
2975
+ ],
2976
+ },
2977
+ keywords: "caption character limit social media post",
2978
+ load: () => import("./tools/caption-counter.js"),
2979
+ },
2980
+ {
2981
+ id: "hashtag-formatter",
2982
+ category: "content",
2983
+ name: "Hashtag Formatter",
2984
+ icon: "hash",
2985
+ note: "Tidy a list of hashtags.",
2986
+ about: "Adds the hash sign, drops duplicates and lays them out.",
2987
+ tutorial: {
2988
+ intro: "Tidy a list of hashtags.",
2989
+ steps: [
2990
+ "Paste tags, one per line or space separated.",
2991
+ "The tags are cleaned and de-duplicated.",
2992
+ "Copy the tags on one line or one per line.",
2993
+ ],
2994
+ },
2995
+ keywords: "hashtag format dedupe tags social media",
2996
+ load: () => import("./tools/hashtag-formatter.js"),
2997
+ },
2998
+ {
2999
+ id: "line-break-formatter",
3000
+ category: "content",
3001
+ name: "Line Break Formatter",
3002
+ icon: "pilcrow",
3003
+ note: "Tidy the spacing in a caption.",
3004
+ about: "Removes extra blank lines and sets even paragraph gaps.",
3005
+ tutorial: {
3006
+ intro: "Tidy the spacing in a caption or post.",
3007
+ steps: [
3008
+ "Paste the text.",
3009
+ "Pick how many blank lines between paragraphs.",
3010
+ "Copy the tidied text.",
3011
+ ],
3012
+ },
3013
+ keywords: "caption line break spacing paragraph blank lines",
3014
+ load: () => import("./tools/line-break-formatter.js"),
3015
+ },
3016
+ {
3017
+ id: "video-duration",
3018
+ category: "content",
3019
+ name: "Video Duration",
3020
+ icon: "video",
3021
+ note: "Estimate a video's length from its script.",
3022
+ about: "Words at a speaking rate, plus pauses.",
3023
+ tutorial: {
3024
+ intro: "Estimate a video's length from its script.",
3025
+ steps: [
3026
+ "Paste the script or enter the word count.",
3027
+ "Set the speaking rate and the pause allowance.",
3028
+ "The estimated duration appears.",
3029
+ ],
3030
+ },
3031
+ keywords: "video duration script words speaking rate estimate",
3032
+ load: () => import("./tools/video-duration.js"),
3033
+ },
3034
+ {
3035
+ id: "content-calendar",
3036
+ category: "content",
3037
+ name: "Content Calendar",
3038
+ icon: "calendar-days",
3039
+ note: "Plan posts on a calendar.",
3040
+ about: "Dates, topics, platforms and status, with a CSV export.",
3041
+ tutorial: {
3042
+ intro: "Plan posts on a calendar.",
3043
+ steps: [
3044
+ "Add a date, a topic, a platform and a status.",
3045
+ "Entries are grouped by date.",
3046
+ "Export the calendar as CSV or Markdown.",
3047
+ ],
3048
+ },
3049
+ keywords: "content calendar plan posts schedule platform",
3050
+ load: () => import("./tools/content-calendar.js"),
3051
+ },
3052
+ {
3053
+ id: "script-planner",
3054
+ category: "content",
3055
+ name: "Script Planner",
3056
+ icon: "film",
3057
+ note: "Lay out a video script.",
3058
+ about: "Hook, intro, body and outro, with word and time estimates.",
3059
+ tutorial: {
3060
+ intro: "Lay out a video script in sections.",
3061
+ steps: [
3062
+ "Write each section: hook, intro, body and outro.",
3063
+ "The word count and the time estimate appear per section.",
3064
+ "Copy the full script.",
3065
+ ],
3066
+ },
3067
+ keywords: "script video hook intro body outro plan",
3068
+ load: () => import("./tools/script-planner.js"),
3069
+ },
3070
+ {
3071
+ id: "title-length",
3072
+ category: "content",
3073
+ name: "Title Length",
3074
+ icon: "type",
3075
+ note: "Compare several titles by length.",
3076
+ about: "Counts words and characters and sorts the list.",
3077
+ tutorial: {
3078
+ intro: "Compare several titles by length.",
3079
+ steps: [
3080
+ "Type one title per line.",
3081
+ "Set a length limit if you have one.",
3082
+ "The titles are listed with their counts, longest first.",
3083
+ ],
3084
+ },
3085
+ keywords: "title length characters words compare headline",
3086
+ load: () => import("./tools/title-length.js"),
3087
+ },
3088
+ {
3089
+ id: "subtitle-formatter",
3090
+ category: "content",
3091
+ name: "Subtitle Formatter",
3092
+ icon: "film",
3093
+ note: "Check subtitle line lengths.",
3094
+ about: "Flags lines that run too long and tidies blank lines.",
3095
+ tutorial: {
3096
+ intro: "Check subtitle or caption line lengths.",
3097
+ steps: [
3098
+ "Paste the subtitle text.",
3099
+ "Set a maximum line length.",
3100
+ "Long lines are flagged. SRT timings are left as they are.",
3101
+ ],
3102
+ },
3103
+ keywords: "subtitle caption srt line length format",
3104
+ load: () => import("./tools/subtitle-formatter.js"),
3105
+ },
3106
+
3107
+ // ---------- github ----------
3108
+ {
3109
+ id: "readme-generator",
3110
+ category: "git",
3111
+ name: "README Generator",
3112
+ icon: "file-text",
3113
+ note: "Draft a README for a project.",
3114
+ about: "Fills the usual sections and lets you pick which to include.",
3115
+ tutorial: {
3116
+ intro: "Draft a README for a project.",
3117
+ steps: [
3118
+ "Enter the project name and description.",
3119
+ "Toggle the sections you want.",
3120
+ "Copy the Markdown.",
3121
+ ],
3122
+ },
3123
+ keywords: "readme generator markdown project github",
3124
+ load: () => import("./tools/readme-generator.js"),
3125
+ },
3126
+ {
3127
+ id: "gitignore-generator",
3128
+ category: "git",
3129
+ name: "Gitignore Generator",
3130
+ icon: "file-code",
3131
+ note: "Build a .gitignore file.",
3132
+ about: "Merges templates for common stacks.",
3133
+ tutorial: {
3134
+ intro: "Build a .gitignore file for a project.",
3135
+ steps: [
3136
+ "Pick one or more stacks.",
3137
+ "The patterns are merged.",
3138
+ "Copy or download the file.",
3139
+ ],
3140
+ },
3141
+ keywords: "gitignore template node python laravel ignore",
3142
+ load: () => import("./tools/gitignore-generator.js"),
3143
+ },
3144
+ {
3145
+ id: "semver-helper",
3146
+ category: "git",
3147
+ name: "Semantic Version",
3148
+ icon: "tag",
3149
+ note: "Bump a semantic version.",
3150
+ about: "Major, minor or patch, with the new version and a prerelease tag.",
3151
+ tutorial: {
3152
+ intro: "Bump a semantic version.",
3153
+ steps: [
3154
+ "Enter the current version.",
3155
+ "Pick major, minor or patch.",
3156
+ "Add a prerelease tag if you need one. Copy the new version.",
3157
+ ],
3158
+ },
3159
+ keywords: "semver version bump major minor patch release",
3160
+ load: () => import("./tools/semver-helper.js"),
3161
+ },
3162
+ {
3163
+ id: "changelog-generator",
3164
+ category: "git",
3165
+ name: "Changelog Generator",
3166
+ icon: "list",
3167
+ note: "Draft a changelog entry.",
3168
+ about: "Groups changes under added, changed, fixed and removed.",
3169
+ tutorial: {
3170
+ intro: "Draft a changelog entry.",
3171
+ steps: [
3172
+ "Set the version and the date.",
3173
+ "Add changes under each group.",
3174
+ "Copy the Markdown.",
3175
+ ],
3176
+ },
3177
+ keywords: "changelog release notes keep a changelog markdown",
3178
+ load: () => import("./tools/changelog-generator.js"),
3179
+ },
3180
+ {
3181
+ id: "license-reference",
3182
+ category: "git",
3183
+ name: "License Reference",
3184
+ icon: "scale",
3185
+ note: "Compare common open source licenses.",
3186
+ about: "Short summaries of MIT, Apache-2.0, GPL-3.0 and BSD.",
3187
+ tutorial: {
3188
+ intro: "Compare common open source licenses.",
3189
+ steps: [
3190
+ "Pick a license.",
3191
+ "Read a short summary of what it requires.",
3192
+ "This is a summary, not legal advice.",
3193
+ ],
3194
+ },
3195
+ keywords: "license mit apache gpl bsd open source reference",
3196
+ load: () => import("./tools/license-reference.js"),
3197
+ },
3198
+ {
3199
+ id: "branch-name",
3200
+ category: "git",
3201
+ name: "Branch Name",
3202
+ icon: "git-branch",
3203
+ note: "Turn a task into a branch name.",
3204
+ about: "Adds a type prefix and slugifies the description.",
3205
+ tutorial: {
3206
+ intro: "Turn a task into a branch name.",
3207
+ steps: [
3208
+ "Pick a type like feat or fix.",
3209
+ "Describe the task.",
3210
+ "Copy the branch name.",
3211
+ ],
3212
+ },
3213
+ keywords: "branch name git prefix feat fix slug",
3214
+ load: () => import("./tools/branch-name.js"),
3215
+ },
3216
+ {
3217
+ id: "commit-message",
3218
+ category: "git",
3219
+ name: "Commit Message",
3220
+ icon: "signature",
3221
+ note: "Build a Conventional Commit message.",
3222
+ about: "Type, scope and description, with a quick check.",
3223
+ tutorial: {
3224
+ intro: "Build a commit message in the Conventional Commits style.",
3225
+ steps: [
3226
+ "Pick a type and set a scope.",
3227
+ "Write a short description.",
3228
+ "Copy the message.",
3229
+ ],
3230
+ },
3231
+ keywords: "commit message conventional feat fix scope",
3232
+ load: () => import("./tools/commit-message.js"),
3233
+ },
3234
+ {
3235
+ id: "version-compare",
3236
+ category: "git",
3237
+ name: "Version Compare",
3238
+ icon: "git-compare",
3239
+ note: "Compare two version numbers.",
3240
+ about: "Says which version is newer and where they differ.",
3241
+ tutorial: {
3242
+ intro: "Compare two version numbers.",
3243
+ steps: [
3244
+ "Enter two versions.",
3245
+ "The newer one and the differences appear.",
3246
+ ],
3247
+ },
3248
+ keywords: "version compare newer semver package",
3249
+ load: () => import("./tools/version-compare.js"),
3250
+ },
3251
+
3252
+ // ---------- units ----------
3253
+ {
3254
+ id: "length-converter",
3255
+ category: "measure",
3256
+ name: "Length Converter",
3257
+ icon: "ruler",
3258
+ note: "Convert units of length.",
3259
+ about: "Meters, kilometers, miles, feet, inches and more.",
3260
+ tutorial: {
3261
+ intro: "Convert between units of length.",
3262
+ steps: [
3263
+ "Enter a value and pick its unit.",
3264
+ "Pick the unit to convert to.",
3265
+ "The result appears.",
3266
+ ],
3267
+ },
3268
+ keywords: "length converter meter kilometer mile feet inch",
3269
+ load: () => import("./tools/length-converter.js"),
3270
+ },
3271
+ {
3272
+ id: "weight-converter",
3273
+ category: "measure",
3274
+ name: "Weight Converter",
3275
+ icon: "weight",
3276
+ note: "Convert units of mass.",
3277
+ about: "Milligrams, grams, kilograms, pounds and ounces.",
3278
+ tutorial: {
3279
+ intro: "Convert between units of mass.",
3280
+ steps: [
3281
+ "Enter a value and pick its unit.",
3282
+ "Pick the unit to convert to.",
3283
+ "The result appears.",
3284
+ ],
3285
+ },
3286
+ keywords: "weight mass converter kilogram pound ounce gram",
3287
+ load: () => import("./tools/weight-converter.js"),
3288
+ },
3289
+ {
3290
+ id: "temperature-converter",
3291
+ category: "measure",
3292
+ name: "Temperature Converter",
3293
+ icon: "thermometer",
3294
+ note: "Convert Celsius, Fahrenheit and Kelvin.",
3295
+ about: "Both directions, with the formula shown.",
3296
+ tutorial: {
3297
+ intro: "Convert between Celsius, Fahrenheit and Kelvin.",
3298
+ steps: [
3299
+ "Enter a value and pick its scale.",
3300
+ "The other scales appear with the formula.",
3301
+ ],
3302
+ },
3303
+ keywords: "temperature celsius fahrenheit kelvin convert",
3304
+ load: () => import("./tools/temperature-converter.js"),
3305
+ },
3306
+ {
3307
+ id: "data-storage",
3308
+ category: "measure",
3309
+ name: "Data Storage Converter",
3310
+ icon: "hard-drive",
3311
+ note: "Convert digital storage units.",
3312
+ about: "Decimal and binary units, with the difference explained.",
3313
+ tutorial: {
3314
+ intro: "Convert between digital storage units.",
3315
+ steps: [
3316
+ "Enter a value and pick its unit.",
3317
+ "Pick the unit to convert to.",
3318
+ "Decimal MB and binary MiB differ, and the tool notes it.",
3319
+ ],
3320
+ },
3321
+ keywords: "data storage byte kilobyte megabyte gibibyte converter",
3322
+ load: () => import("./tools/data-storage.js"),
3323
+ },
3324
+ {
3325
+ id: "speed-converter",
3326
+ category: "measure",
3327
+ name: "Speed Converter",
3328
+ icon: "gauge",
3329
+ note: "Convert units of speed.",
3330
+ about: "Kilometers per hour, meters per second, miles per hour and knots.",
3331
+ tutorial: {
3332
+ intro: "Convert between units of speed.",
3333
+ steps: [
3334
+ "Enter a value and pick its unit.",
3335
+ "Pick the unit to convert to.",
3336
+ "The result appears.",
3337
+ ],
3338
+ },
3339
+ keywords: "speed converter kmh mph knots meter per second",
3340
+ load: () => import("./tools/speed-converter.js"),
3341
+ },
3342
+ {
3343
+ id: "area-converter",
3344
+ category: "measure",
3345
+ name: "Area Converter",
3346
+ icon: "square",
3347
+ note: "Convert units of area.",
3348
+ about: "Square meters, hectares, acres and more.",
3349
+ tutorial: {
3350
+ intro: "Convert between units of area.",
3351
+ steps: [
3352
+ "Enter a value and pick its unit.",
3353
+ "Pick the unit to convert to.",
3354
+ "The result appears.",
3355
+ ],
3356
+ },
3357
+ keywords: "area converter square meter hectare acre",
3358
+ load: () => import("./tools/area-converter.js"),
3359
+ },
3360
+ {
3361
+ id: "volume-converter",
3362
+ category: "measure",
3363
+ name: "Volume Converter",
3364
+ icon: "shapes",
3365
+ note: "Convert units of volume.",
3366
+ about: "Liters, milliliters, cubic meters and gallons.",
3367
+ tutorial: {
3368
+ intro: "Convert between units of volume.",
3369
+ steps: [
3370
+ "Enter a value and pick its unit.",
3371
+ "Pick the unit to convert to.",
3372
+ "The result appears.",
3373
+ ],
3374
+ },
3375
+ keywords: "volume converter liter milliliter gallon cubic meter",
3376
+ load: () => import("./tools/volume-converter.js"),
3377
+ },
3378
+ {
3379
+ id: "binary-calculator",
3380
+ category: "measure",
3381
+ name: "Binary Calculator",
3382
+ icon: "binary",
3383
+ note: "Add and subtract binary numbers.",
3384
+ about: "Shows the result in binary and decimal.",
3385
+ tutorial: {
3386
+ intro: "Add or subtract two binary numbers.",
3387
+ steps: [
3388
+ "Enter two binary numbers.",
3389
+ "Pick add or subtract.",
3390
+ "The result appears in binary and decimal.",
3391
+ ],
3392
+ },
3393
+ keywords: "binary add subtract calculator base two",
3394
+ load: () => import("./tools/binary-calculator.js"),
3395
+ },
294
3396
  ];
295
3397
 
296
3398
  export function getTool(id) {