cronli5 0.1.5 → 0.1.6

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/dist/lang/zh.js CHANGED
@@ -223,8 +223,18 @@ function minuteHourClause(ir) {
223
223
  function renderMinutePast(ir) {
224
224
  return minuteHourClause(ir);
225
225
  }
226
+ function hourSegmentWords(segment) {
227
+ if (segment.kind === "range") {
228
+ return [hourWord(+segment.bounds[0]) + "\u81F3" + hourWord(+segment.bounds[1])];
229
+ }
230
+ if (segment.kind === "step") {
231
+ return segment.fires.map(hourWord);
232
+ }
233
+ return [hourWord(+segment.value)];
234
+ }
226
235
  function hourList(ir) {
227
- return joinAnd(hourFires(ir).map(hourWord));
236
+ const words = fieldSegments(ir, "hour").flatMap(hourSegmentWords);
237
+ return joinAnd(words);
228
238
  }
229
239
  function hourFrame(ir) {
230
240
  if (ir.shapes.hour === "range") {
@@ -237,9 +247,11 @@ function renderMinuteFrequency(ir, plan) {
237
247
  const minuteStep = stepSegment(ir, "minute");
238
248
  const base = stepClause(minuteStep, UNITS.minute, "\u5206", "\u6BCF\u5C0F\u65F6");
239
249
  const { hours } = plan;
240
- if (hours.kind === "step") {
241
- const hourStep = stepSegment(ir, "hour");
242
- return hourStep.startToken === "*" ? cadence(hourStep.interval, UNITS.hour) + base : "\u5728" + hourList(ir) + "\uFF0C" + base;
250
+ if (hours.kind === "step" || hours.kind === "during") {
251
+ const hourCad = hourCadencePhrase(ir);
252
+ if (hourCad !== null) {
253
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "" : "\uFF0C") + base;
254
+ }
243
255
  }
244
256
  if (hours.kind === "single" || hours.kind === "window" && hours.from === hours.to) {
245
257
  return "\u5728" + hourWord(hours.from) + "\u81F3" + hours.from + "\u70B9" + hours.last + "\u5206\u4E4B\u95F4\uFF0C" + base;
@@ -261,20 +273,21 @@ function renderMinuteSpanInHour(ir, plan) {
261
273
  }
262
274
  function renderMinutesAcrossHours(ir, plan) {
263
275
  const { form } = plan;
276
+ const hourCad = hourCadencePhrase(ir);
264
277
  if (form === "wildcard") {
265
- return "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F";
278
+ return hourCad === null ? "\u5728" + hourList(ir) + "\uFF0C\u6BCF\u5206\u949F" : hourCad + "\uFF0C\u6BCF\u5206\u949F";
266
279
  }
267
- return hourList(ir) + "\uFF0C" + minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
280
+ return (hourCad ?? hourList(ir)) + "\uFF0C" + minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
268
281
  }
269
282
  function renderMinuteSpanAcrossHourStep(ir, plan) {
270
283
  const hourStep = stepSegment(ir, "hour");
271
284
  const { form } = plan;
272
285
  if (form === "list") {
273
- return renderMinutePast(ir) + "\uFF0C\u5728" + hourList(ir);
286
+ return hourCadencePhrase(ir) + "\uFF0C" + renderMinutePast(ir);
274
287
  }
275
288
  const minuteTail = form === "wildcard" ? "\u6BCF\u5206\u949F" : minuteHourClause(ir) + "\uFF0C\u6BCF\u5206\u949F";
276
289
  if (hourStep.startToken !== "*") {
277
- return form === "wildcard" ? "\u5728" + hourList(ir) + "\uFF0C" + minuteTail : hourList(ir) + "\uFF0C" + minuteTail;
290
+ return hourCadencePhrase(ir) + "\uFF0C" + minuteTail;
278
291
  }
279
292
  if (hourStep.interval === 2 && form === "wildcard") {
280
293
  return "\u5728\u5076\u6570\u5C0F\u65F6\uFF0C" + minuteTail;
@@ -283,26 +296,26 @@ function renderMinuteSpanAcrossHourStep(ir, plan) {
283
296
  return form === "wildcard" ? cad + "\u5185\uFF0C" + minuteTail : cad + "\uFF0C" + minuteTail;
284
297
  }
285
298
  function renderClockTimes(ir, plan, opts) {
286
- if (ir.shapes.minute === "single") {
287
- const cad = hourCadence(ir);
288
- if (cad !== null) {
289
- return cad;
290
- }
299
+ const cad = hourCadenceText(ir);
300
+ if (cad !== null) {
301
+ return cad;
291
302
  }
292
303
  const { times } = plan;
293
304
  return joinAnd(times.map((t) => clockTime(t.hour, t.minute, t.second, opts)));
294
305
  }
295
306
  function renderCompactClockTimes(ir, plan) {
296
- if (ir.shapes.minute === "single") {
297
- const cad = hourCadence(ir);
298
- if (cad !== null) {
299
- return cad;
300
- }
307
+ const cad = hourCadenceText(ir);
308
+ if (cad !== null) {
309
+ return cad;
301
310
  }
302
- const { minute } = plan;
311
+ const compact = plan;
303
312
  const secs = fieldSegments(ir, "second");
304
313
  const tail = secs.length && ir.pattern.second !== "0" ? "\uFF0C\u7B2C" + valueText(secs) + "\u79D2" : "";
305
- if (minute > 0) {
314
+ if (!compact.fold) {
315
+ const hourCad = hourCadencePhrase(ir);
316
+ return hourCad === null ? minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail : hourCad + "\uFF0C" + minuteHourClause(ir) + tail;
317
+ }
318
+ if (compact.minute > 0) {
306
319
  return minuteHourClause(ir) + "\uFF0C\u5728" + hourList(ir) + tail;
307
320
  }
308
321
  return hourList(ir) + tail;
@@ -321,54 +334,62 @@ function renderHourRange(ir, plan) {
321
334
  }
322
335
  function renderHourStep(ir) {
323
336
  const segment = stepSegment(ir, "hour");
324
- if (segment.startToken !== "*") {
325
- return hourList(ir);
326
- }
327
337
  if (segment.fires.length <= 2) {
328
338
  return joinAnd(segment.fires.map(hourWord));
329
339
  }
330
- return cadence(segment.interval, UNITS.hour);
340
+ return hourCadencePhrase(ir);
331
341
  }
332
342
  function hourStride(ir) {
333
343
  const segments = fieldSegments(ir, "hour");
334
344
  if (segments.length === 1 && segments[0].kind === "step") {
335
- const segment = segments[0];
336
- const start = segment.startToken === "*" ? 0 : +segment.startToken;
337
- if (start !== 0 || 24 % segment.interval !== 0) {
338
- return null;
339
- }
340
- return {
341
- interval: segment.interval,
342
- last: segment.fires[segment.fires.length - 1]
343
- };
345
+ const { fires, interval } = segments[0];
346
+ return { interval, start: fires[0], last: fires[fires.length - 1] };
344
347
  }
345
348
  const values = singleValues(segments);
346
- const step = values && arithmeticStep(values);
347
- if (!step || step.start !== 0 || 24 % step.interval !== 0) {
348
- return null;
349
- }
350
- return { interval: step.interval, last: step.last };
349
+ return values && arithmeticStep(values);
350
+ }
351
+ function hourCadencePhrase(ir) {
352
+ const stride = hourStride(ir);
353
+ return stride && renderStride({
354
+ ...stride,
355
+ cycle: 24,
356
+ unit: UNITS.hour,
357
+ mark: "\u70B9",
358
+ anchor: ""
359
+ });
351
360
  }
352
361
  function hourCadence(ir) {
353
362
  const stride = hourStride(ir);
354
363
  if (!stride) {
355
364
  return null;
356
365
  }
357
- const fires = stride.last / stride.interval + 1;
366
+ const fires = (stride.last - stride.start) / stride.interval + 1;
358
367
  if (ir.pattern.second === "0" && fires <= maxClockTimes) {
359
368
  return null;
360
369
  }
361
- const prefix = cadence(stride.interval, UNITS.hour);
370
+ const prefix = hourCadencePhrase(ir);
371
+ if (prefix.indexOf("\u81F3") !== -1) {
372
+ return null;
373
+ }
362
374
  const minute = +ir.pattern.minute;
363
375
  const subMinute = ir.pattern.second === "*" || ir.shapes.second === "step";
364
376
  if (minute === 0 && subMinute) {
365
- return stride.interval === 2 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
377
+ return stride.interval === 2 && stride.start === 0 ? "\u5728\u5076\u6570\u5C0F\u65F60\u5206" + secondTail(ir) : null;
366
378
  }
367
379
  if (minute === 0) {
368
380
  return prefix + "0\u5206" + secondTail(ir);
369
381
  }
370
382
  return ir.pattern.second === "0" ? prefix + minute + "\u5206" : prefix + minute + "\u5206" + secondTail(ir);
371
383
  }
384
+ function hourCadenceText(ir) {
385
+ if (ir.shapes.minute !== "single") {
386
+ return null;
387
+ }
388
+ if (+ir.pattern.minute === 0 && ir.pattern.second === "0") {
389
+ return hourCadencePhrase(ir);
390
+ }
391
+ return hourCadence(ir);
392
+ }
372
393
  function secondTail(ir) {
373
394
  const sec = secondClause(ir);
374
395
  return sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec;
@@ -416,8 +437,8 @@ function minuteClause(ir) {
416
437
  }
417
438
  return valueList(fieldSegments(ir, "minute"), "\u5206");
418
439
  }
419
- function isHourCadence(ir) {
420
- return ir.shapes.hour === "step" && stepSegment(ir, "hour").startToken === "*";
440
+ function clockRestCarriesSecond(rest) {
441
+ return rest.kind === "clockTimes" && rest.times.some((time) => Boolean(time.second));
421
442
  }
422
443
  function composeSecondsOnHour(ir, plan, opts) {
423
444
  const sec = secondClause(ir);
@@ -433,17 +454,19 @@ function composeSecondsOnHour(ir, plan, opts) {
433
454
  return composeMinuteZeroClocks(ir, sec);
434
455
  }
435
456
  const restText = render(ir, rest, opts);
436
- if (rest.kind === "clockTimes" || rest.kind === "compactClockTimes") {
437
- if (isDaily(ir)) {
438
- return "\u6BCF\u5929" + restText + sec;
439
- }
457
+ const secTail = clockRestCarriesSecond(rest) ? "" : sec;
458
+ if (composedClock && isDaily(ir)) {
459
+ return "\u6BCF\u5929" + restText + secTail;
440
460
  }
441
461
  if (rest.kind === "singleMinute") {
442
462
  return restText + "\uFF0C" + sec;
443
463
  }
444
- return restText + sec;
464
+ return restText + secTail;
445
465
  }
446
466
  function composeMinuteZeroClocks(ir, sec) {
467
+ if (hasHourWindow(ir)) {
468
+ return isDaily(ir) ? "\u6BCF\u5929" + hourRangeWindow(ir, sec) : hourRangeWindow(ir, sec);
469
+ }
447
470
  const clocks = hourFires(ir).map(function clock(hour) {
448
471
  return hour === 12 ? "\u6B63\u5348" : hourWord(hour) + "0\u5206";
449
472
  });
@@ -452,11 +475,24 @@ function composeMinuteZeroClocks(ir, sec) {
452
475
  const core = joinAnd(clocks) + tail;
453
476
  return isDaily(ir) ? "\u6BCF\u5929" + core : core;
454
477
  }
478
+ function hasHourWindow(ir) {
479
+ return fieldSegments(ir, "hour").some(function range(segment) {
480
+ return segment.kind === "range";
481
+ });
482
+ }
483
+ function hourRangeWindow(ir, sec) {
484
+ const span = hourList(ir);
485
+ if (ir.pattern.second === "*" || ir.shapes.second === "step") {
486
+ return span + "0\u5206" + (sec === "\u6BCF\u79D2" ? "\u7684\u6BCF\u4E00\u79D2" : "\u7684" + sec);
487
+ }
488
+ return span + "\uFF0C" + sec;
489
+ }
455
490
  function composeSecondsCadence(ir) {
456
491
  const sec = secondClause(ir);
457
492
  const tail = minuteClause(ir) + sec;
458
- if (isHourCadence(ir)) {
459
- return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + "\u7684" + tail;
493
+ const hourCad = hourCadencePhrase(ir);
494
+ if (hourCad !== null) {
495
+ return hourCad + (hourCad.indexOf("\u81F3") === -1 ? "\u7684" : "\uFF0C") + tail;
460
496
  }
461
497
  if (ir.shapes.hour === "single") {
462
498
  return hourWord(hourFires(ir)[0]) + "\u7684" + tail;
@@ -483,8 +519,9 @@ function composeSecondsListed(ir) {
483
519
  if (ir.shapes.hour === "wildcard") {
484
520
  return minutes + "\uFF0C" + sec;
485
521
  }
486
- if (isHourCadence(ir)) {
487
- return cadence(stepSegment(ir, "hour").interval, UNITS.hour) + "\uFF0C" + minutes + "\uFF0C" + sec;
522
+ const hourCad = hourCadencePhrase(ir);
523
+ if (hourCad !== null) {
524
+ return hourCad + "\uFF0C" + minutes + "\uFF0C" + sec;
488
525
  }
489
526
  return hourFrame(ir) + minutes + "\uFF0C" + sec;
490
527
  }
@@ -696,7 +733,7 @@ function composeWindow(ir, core) {
696
733
  return qualifier(ir) + core;
697
734
  }
698
735
  function hourCadenceApplies(ir) {
699
- return ir.shapes.minute === "single" && hourCadence(ir) !== null;
736
+ return hourCadenceText(ir) !== null;
700
737
  }
701
738
  function describe(ir, opts) {
702
739
  const { kind } = ir.plan;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cronli5",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Cron Like I'm Five: A Cron to English Utility",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,7 +70,7 @@
70
70
  "test:types": "npm run types && tsd",
71
71
  "typecheck": "tsc -p tsconfig.json",
72
72
  "coverage": "c8 mocha",
73
- "verify": "npm run lint && npm run typecheck && npm run test:types && npm test && npm run coverage && npm run docs -- --check && npm run build",
73
+ "verify": "npm run lint && npm run typecheck && npm run test:types && npm test && npm run coverage && npm run conciseness && npm run docs -- --check && npm run build",
74
74
  "prepare": "node scripts/install-hooks.mjs",
75
75
  "prepublishOnly": "npm run lint && npm run typecheck && npm run test:types && npm run build && npm test"
76
76
  },