diff --git a/__tests__/parseText/suites/smoke.txt b/__tests__/parseText/suites/smoke.txt index bdc5b56..10a7756 100644 --- a/__tests__/parseText/suites/smoke.txt +++ b/__tests__/parseText/suites/smoke.txt @@ -98,4 +98,13 @@ in 2 weeks 0 9 18 * * in 5 months -0 9 4 7 * \ No newline at end of file +0 9 4 7 * + +Thursdays +0 9 * * 4 + +mon +0 9 * * 1 + +weekdays +0 9 * * 1-5 \ No newline at end of file diff --git a/package.json b/package.json index 86dc662..ed815c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crontext", - "version": "0.2.10", + "version": "0.2.11", "description": "Simple utility for parsing human text into a cron schedule.", "files": [ "lib" diff --git a/src/parser/index.ts b/src/parser/index.ts new file mode 100644 index 0000000..90eb13e --- /dev/null +++ b/src/parser/index.ts @@ -0,0 +1,53 @@ +import type { Token } from '../tokenize'; +import type { Options } from '../options'; +import { rules } from './rules'; + +export type Crontext = { + minutes: string; + hour: string; + dayOfMonth: string; + dayOfWeek: string; + month: string; + repeat: boolean; +}; + +export const DEFAULT = '*'; +export const INIT = '_'; // Used to know whether the value has been set at all. +export const DEFAULT_DAY_MINUTES = '0'; +export const DEFAULT_DAY_HOURS = '9'; + +const defaultParsed: Crontext = { + minutes: INIT, + hour: INIT, + dayOfMonth: INIT, + dayOfWeek: INIT, + month: INIT, + repeat: false, +}; +export const parser = (tokens: Token[], options: Options): Crontext => { + let crontext = { ...defaultParsed }; + // Iterate all tokens + for (let t = 0; t < tokens.length; t++) { + // Check if any of the rules match the given token and forward lookups. + for (let r = 0; r < rules.length; r++) { + const rule = rules[r]; + const ruleLen = rule.match.length; + if (ruleLen <= tokens.length - t) { + const sub = tokens.slice(t, t + ruleLen); + let isMatch = true; + for (let s = 0; s < sub.length; s++) { + if (sub[s].type !== rule.match[s]) { + isMatch = false; + } + } + if (isMatch) { + t = t + sub.length - 1; + crontext = rule.update(crontext, sub, options); + } + } + } + } + return crontext; +}; + +export default parser; diff --git a/src/parser.ts b/src/parser/rules.ts similarity index 72% rename from src/parser.ts rename to src/parser/rules.ts index f9065c8..40a8517 100644 --- a/src/parser.ts +++ b/src/parser/rules.ts @@ -1,24 +1,12 @@ -import type { Token } from './tokenize'; -import { TokenType } from './tokens'; -import { testRepeat as freqTestRepeat } from './tokens/frequency'; -import { getNumber } from './tokens/number'; -import { getTime } from './tokens/clock'; -import { getDayOfWeek, pluralDayRegexOptions } from './tokens/day'; -import type { Options } from './options'; - -export type Crontext = { - minutes: string; - hour: string; - dayOfMonth: string; - dayOfWeek: string; - month: string; - repeat: boolean; -}; - -export const DEFAULT = '*'; -export const INIT = '_'; // Used to know whether the value has been set at all. -export const DEFAULT_DAY_MINUTES = '0'; -export const DEFAULT_DAY_HOURS = '9'; +import type { Token } from '../tokenize'; +import { TokenType } from '../tokens'; +import { testRepeat as freqTestRepeat } from '../tokens/frequency'; +import { getNumber } from '../tokens/number'; +import { getTime } from '../tokens/clock'; +import { getDayOfWeek, pluralDayRegexOptions } from '../tokens/day'; +import type { Options } from '../options'; +import { INIT, DEFAULT } from './index'; +import type { Crontext } from './index'; const { FREQUENCY, @@ -32,15 +20,6 @@ const { RELATIVE_DAY, } = TokenType; -const defaultParsed: Crontext = { - minutes: INIT, - hour: INIT, - dayOfMonth: INIT, - dayOfWeek: INIT, - month: INIT, - repeat: false, -}; - export const updateDay = ( crontext: Crontext, tokens: Token[], @@ -51,15 +30,15 @@ export const updateDay = ( if (crontext.minutes === INIT) crontext.minutes = options.defaultMinute; if (crontext.hour === INIT) crontext.hour = options.defaultHour; const re = new RegExp(pluralDayRegexOptions); - // Plural 'on mondays' means its repeating - if ( - tokens.length >= 2 && - tokens[0].value === 'on' && - re.test(tokens[1].value) - ) { - crontext.repeat = true; + const dayToken = tokens.find(t => t.type === DAY); + let dayOfWeek = '*'; + if (dayToken) { + // Plural 'on mondays' means its repeating + if (re.test(dayToken.value)) { + crontext.repeat = true; + } + dayOfWeek = getDayOfWeek(dayToken.value); } - const dayOfWeek = getDayOfWeek(tokens[1].value); return { ...crontext, dayOfWeek }; }; @@ -173,6 +152,10 @@ export const rules = [ match: [FREQUENCY, DAY], update: updateDay, }, + { + match: [DAY], + update: updateDay, + }, { match: [FREQUENCY, DAYS], update: ( @@ -219,31 +202,3 @@ export const rules = [ }, }, ]; - -export const parser = (tokens: Token[], options: Options): Crontext => { - let crontext = { ...defaultParsed }; - // Iterate all tokens - for (let t = 0; t < tokens.length; t++) { - // Check if any of the rules match the given token and forward lookups. - for (let r = 0; r < rules.length; r++) { - const rule = rules[r]; - const ruleLen = rule.match.length; - if (ruleLen <= tokens.length - t) { - const sub = tokens.slice(t, t + ruleLen); - let isMatch = true; - for (let s = 0; s < sub.length; s++) { - if (sub[s].type !== rule.match[s]) { - isMatch = false; - } - } - if (isMatch) { - t = t + sub.length - 1; - crontext = rule.update(crontext, sub, options); - } - } - } - } - return crontext; -}; - -export default parser;