@jsonresume/utils 0.2.0 → 0.2.1

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 (2) hide show
  1. package/README.md +114 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # @jsonresume/utils
2
+
3
+ Framework-free pure utilities for [JSON Resume](https://jsonresume.org): date formatting, derived metrics, URL safety, and resume-shape helpers.
4
+
5
+ No React, no styled-components, no side effects — safe to use anywhere: server, CLI, browser, or inside a theme.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @jsonresume/utils
11
+ ```
12
+
13
+ ## API
14
+
15
+ Everything is re-exported from the root (`.`) for convenience, and also available via focused subpaths.
16
+
17
+ ### Root (`@jsonresume/utils`)
18
+
19
+ Re-exports all of the functions below, plus two resume-shape helpers:
20
+
21
+ | Function | Description |
22
+ | --- | --- |
23
+ | `formatLocation(location)` | Join `city, region, countryCode` into one display line (empty parts dropped). |
24
+ | `normalizeResume(resume)` | Return a copy with all 12 standard sections present (`basics` as `{}`, arrays as `[]`); never mutates the input. |
25
+
26
+ ### Dates (`@jsonresume/utils/dates`)
27
+
28
+ | Function | Description |
29
+ | --- | --- |
30
+ | `formatDateRange({ startDate, endDate, format?, locale?, numberingSystem?, presentLabel? })` | Locale-aware date range via `Intl.DateTimeFormat`. A `null` `endDate` renders `Present`; a missing `endDate` renders a single date. |
31
+ | `getRelativeTime(date, ago?)` | Human relative time, e.g. `6 years ago`. |
32
+ | `getDuration(startDate, endDate?)` | Duration between two dates, e.g. `2 years, 6 months` (`endDate` defaults to now). |
33
+ | `normalizeDates(resume)` | Shallow copy with any `Date`-valued date fields stringified to `YYYY-MM-DD`. |
34
+
35
+ ### Metrics (`@jsonresume/utils/metrics`)
36
+
37
+ | Function | Description |
38
+ | --- | --- |
39
+ | `calculateTotalExperience(work)` | Total years of professional experience (rounded to nearest year). |
40
+ | `calculateCurrentRoleExperience(work)` | Years in the current/most-recent role (1 decimal). |
41
+ | `countCareerPositions(work)` | Number of distinct `position` titles held. |
42
+ | `getCareerProgressionRate(work)` | Average years per position. |
43
+ | `countTotalHighlights(work)` | Total `highlights` across all work entries. |
44
+ | `countCompanies(work)` | Number of unique company names. |
45
+ | `countProjects(projects)` | Number of projects. |
46
+ | `countPublications(publications)` | Number of publications. |
47
+ | `countAwards(awards)` | Number of awards. |
48
+ | `countTotalSkills(skills)` | Total skill `keywords` across all categories. |
49
+ | `countSkillCategories(skills)` | Number of skill categories. |
50
+ | `countLanguages(languages)` | Number of languages. |
51
+ | `calculateEducationYears(education)` | Total years of education (rounded). |
52
+ | `getHighestDegree(education)` | The highest degree by `studyType` ranking (e.g. `PhD`). |
53
+ | `calculateVolunteerYears(volunteer)` | Total volunteer years (rounded). |
54
+ | `getUniqueIndustries(work)` | Array of unique `industry` values. |
55
+ | `getCurrentEmployer(work)` | The current (no `endDate`) or most-recent work entry, or `null`. |
56
+ | `isCurrentlyEmployed(work)` | `true` if any work entry has no `endDate`. |
57
+ | `calculateKeyMetrics(resume)` | Dashboard-ready array of `{ label, value }` summarizing the resume. |
58
+
59
+ ### URL safety (`@jsonresume/utils/url`)
60
+
61
+ | Function | Description |
62
+ | --- | --- |
63
+ | `safeUrl(url)` | Block `javascript:`/`data:`/`vbscript:` schemes; return a safe URL or `null`. |
64
+ | `getLinkRel(url, openInNewTab?)` | Return `noopener noreferrer` for external links opened in a new tab. |
65
+ | `sanitizeHtml(html)` | Escape HTML-significant characters to prevent XSS. |
66
+ | `isExternalUrl(url, currentOrigin?)` | `true` if the URL points to a different origin. |
67
+ | `formatUrlForDisplay(url)` | Strip the protocol and trailing slash, e.g. `example.com/blog`. |
68
+
69
+ ## Usage
70
+
71
+ Compute headline metrics from a resume:
72
+
73
+ ```js
74
+ import {
75
+ calculateTotalExperience,
76
+ getHighestDegree,
77
+ formatDateRange,
78
+ } from '@jsonresume/utils';
79
+
80
+ const years = calculateTotalExperience(resume.work);
81
+ const degree = getHighestDegree(resume.education);
82
+ const range = formatDateRange({ startDate: '2020-01-15', endDate: null });
83
+ // range === 'Jan 2020 - Present'
84
+ ```
85
+
86
+ Import from a focused subpath to keep things tight:
87
+
88
+ ```js
89
+ import { safeUrl, getLinkRel } from '@jsonresume/utils/url';
90
+
91
+ const href = safeUrl(profile.url); // null if dangerous
92
+ const rel = getLinkRel(href, true); // 'noopener noreferrer'
93
+ ```
94
+
95
+ Build a dashboard summary:
96
+
97
+ ```js
98
+ import { calculateKeyMetrics } from '@jsonresume/utils/metrics';
99
+
100
+ for (const { label, value } of calculateKeyMetrics(resume)) {
101
+ console.log(`${label}: ${value}`);
102
+ }
103
+ // Years Experience: 8
104
+ // Companies: 5
105
+ // Projects: 12
106
+ ```
107
+
108
+ ## Ecosystem
109
+
110
+ Part of the [JSON Resume](https://jsonresume.org) ecosystem. The styled date/link components in `@jsonresume/core` are built on top of these functions. See the roadmap and related packages in [jsonresume/jsonresume.org#421](https://github.com/jsonresume/jsonresume.org/issues/421).
111
+
112
+ ## License
113
+
114
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonresume/utils",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "Framework-free pure utilities for JSON Resume: date formatting, metrics, and URL safety",
6
6
  "type": "module",
@@ -18,7 +18,7 @@
18
18
  "devDependencies": {
19
19
  "typescript": "^5.9.3",
20
20
  "vitest": "^2",
21
- "@jsonresume/types": "0.2.0",
21
+ "@jsonresume/types": "0.2.1",
22
22
  "@repo/eslint-config-custom": "^0.0.0",
23
23
  "tsconfig": "0.0.0"
24
24
  },