@whiteslove/parsing-lexicon 0.5.9 → 0.5.11

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whiteslove/parsing-lexicon",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "Shared deterministic multilingual parsing lexicon for WhitesLove housing and hiring services",
5
5
  "repository": {
6
6
  "type": "git",
@@ -207,8 +207,15 @@ const SECTION_PATTERNS = Object.freeze(Object.fromEntries(
207
207
  Object.entries(HIRING_SECTION_MARKERS).map(([key, entry]) => [key, sectionPattern(entry)]),
208
208
  ));
209
209
 
210
+ const INLINE_SECTION_LABELS = Object.values(HIRING_SECTION_MARKERS)
211
+ .flatMap((entry) => aliasesOf(entry))
212
+ .sort((a, b) => b.length - a.length)
213
+ .map((value) => escapeRegex(value).replace(/\s+/g, '\\s+'))
214
+ .join('|');
215
+ const INLINE_SECTION_MARKER_RE = new RegExp(`([^\\p{L}\\p{N}\\s])(?=(?:${INLINE_SECTION_LABELS})\\s*[::—-])`, 'giu');
216
+
210
217
  export function splitHiringSections(value) {
211
- const text = String(value || '').replace(/\r/g, '');
218
+ const text = String(value || '').replace(/\r/g, '').replace(INLINE_SECTION_MARKER_RE, '\n$1');
212
219
  const out = {};
213
220
  let current = null;
214
221
  for (const rawLine of text.split('\n')) {
@@ -21,7 +21,7 @@ const FIELD_EXTRA_ALIASES = Object.freeze({
21
21
  }),
22
22
  });
23
23
 
24
- const APPLICATION_MODAL_RE = /(?:отправить\s+резюме\s+)?пол\s+мужской\s+женский\s+образование[\s\S]{0,500}?выберите\s+вакансию[\s\S]*/iu;
24
+ const APPLICATION_MODAL_RE = /(?:отправить\s*резюме\s*)+(?:\[telegram\]\s*)?пол\s*мужской\s*женский\s*образование[\s\S]{0,500}?выберите\s*вакансию[\s\S]*/iu;
25
25
  const LEAKED_STYLESHEET_START_RE = /:root\s*\{\s*--[\w-]+\s*:/iu;
26
26
  const LEAKED_CSS_RULE_RE = /\s*(?:[.#][\w\\-]+|:root)(?:[^{}\n]{0,300})\{\s*(?:(?:--)?[\w-]+\s*:\s*[^;{}]+;?\s*)+\}\s*/giu;
27
27
 
@@ -26,9 +26,11 @@ export type HiringWorkSchedule =
26
26
 
27
27
  export type HiringProbationKind = 'probation' | 'noProbation' | 'paidProbation' | 'unpaidProbation';
28
28
  export type HiringExperienceRequirement = 'noExperience' | 'experienceRequired';
29
+ export type HiringWorkTimeRange = Readonly<{ start: string; end: string }>;
29
30
 
30
31
  export function detectEmploymentTypes(value: unknown): readonly HiringEmploymentType[];
31
32
  export function detectWorkModes(value: unknown): readonly HiringWorkMode[];
32
33
  export function detectWorkSchedules(value: unknown): readonly HiringWorkSchedule[];
34
+ export function extractWorkTimeRanges(value: unknown): readonly HiringWorkTimeRange[];
33
35
  export function detectProbation(value: unknown): HiringProbationKind | null;
34
36
  export function detectExperienceRequirement(value: unknown): HiringExperienceRequirement | null;
@@ -66,6 +66,24 @@ export function detectWorkSchedules(value) {
66
66
  return Object.freeze(collectCanonical(String(value || ''), [...SCHEDULE_TERMS, ...WORK_SCHEDULE_EXTENSIONS]));
67
67
  }
68
68
 
69
+ const WORK_TIME_RANGE_RE = /(?:^|[^\p{L}\p{N}])(?:с|from|de\s+la)?\s*([01]?\d|2[0-3])[:.]([0-5]\d)\s*(?:[-–—]|до|to|până\s+la|pana\s+la|gacha)\s*([01]?\d|2[0-3])[:.]([0-5]\d)(?!\d)/giu;
70
+
71
+ /** Extract explicit working-time intervals without confusing them with contact hours. */
72
+ export function extractWorkTimeRanges(value) {
73
+ const text = String(value || '');
74
+ const ranges = [];
75
+ const seen = new Set();
76
+ for (const match of text.matchAll(WORK_TIME_RANGE_RE)) {
77
+ const start = `${match[1].padStart(2, '0')}:${match[2]}`;
78
+ const end = `${match[3].padStart(2, '0')}:${match[4]}`;
79
+ const key = `${start}-${end}`;
80
+ if (seen.has(key)) continue;
81
+ seen.add(key);
82
+ ranges.push(Object.freeze({ start, end }));
83
+ }
84
+ return Object.freeze(ranges);
85
+ }
86
+
69
87
  export function detectProbation(value) {
70
88
  const text = String(value || '');
71
89
  for (const entry of PROBATION_MATCH_ORDER) {