barefoot_js 0.21.4 → 0.24.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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/barefoot_js.rb +99 -0
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b7b1139c42325379799c479340b9fb822a001e32ebfbb3ae62e9a15d0f565aa
4
- data.tar.gz: fdcdeb39b7ee15dbb96b11f3dd24513fcc516bf242c8cc1f2e589be85b4e779f
3
+ metadata.gz: cd41229b2fa03f5b1e052a7ad7e21bbc5f81a9034740eb6f12055afd473b4b67
4
+ data.tar.gz: 0d175251cb5880996149e5dde87c17278855c3dac477fb698e4cee265788823c
5
5
  SHA512:
6
- metadata.gz: b0b956eed7b39587d7f9d07182c6285e7ad5846e34c495ec369043517c10048afe714a593d2f7ce8f47584f20b3d3ef6759d249cadd412c1fba036a8e26df6b0
7
- data.tar.gz: f5de21fb61748e44d7ebe311a65acac1d7e48f29ef6cf1f489f19c801307610fb3cda0bc7a7574e761781aeb78af6a966ab656ea6b320e4fb7c83f7f7b9f3ce2
6
+ metadata.gz: e430505c608b87a7bf80fbeecd433afa4a3495534ff17af683655fabcd06533a79811d5ded241f530a9da25a529ac3b98e2caf926dbb3da0d1e8a2a2121f9daa
7
+ data.tar.gz: 5a4e93faa339dbe79856153eeed378a3c8f369dba85f35df3ef9755f284fc844a3c0b629bf87094e82e709c0a5579741fbdea52ed08f6220e7a34b2cae2de4a2
data/lib/barefoot_js.rb CHANGED
@@ -529,6 +529,105 @@ module BarefootJS
529
529
  end
530
530
  end
531
531
 
532
+ # `tz` shapes FORMAT_DATE_OFFSET_RE matches: a fixed UTC offset `±HH:MM`
533
+ # (`'+09:00'`, `'-05:30'`) -- the ONLY non-UTC shape `format_date`
534
+ # recognizes (mirrors OFFSET_RE in packages/client/src/format-date.ts).
535
+ FORMAT_DATE_OFFSET_RE = /\A([+-])(\d{2}):(\d{2})\z/
536
+
537
+ # Longest-match pattern-token alternation (mirrors TOKEN_RE in
538
+ # packages/client/src/format-date.ts). Order matters: Onigmo, like JS's
539
+ # regex engine, resolves alternation leftmost-first (not POSIX
540
+ # leftmost-longest), so every multi-char token must be listed before any
541
+ # shorter alternative it prefixes -- YYYY before (nothing shorter
542
+ # shares its prefix), MMMM before MMM before MM before M, DD before D,
543
+ # dddd before ddd. (#2334)
544
+ FORMAT_DATE_TOKEN_RE = /YYYY|MMMM|MMM|MM|DD|dddd|ddd|M|D/
545
+
546
+ # `names`-table section offsets (spec/template-helpers.md "format_date",
547
+ # #2334) -- mirrors MONTHS_WIDE/MONTHS_ABBR/WEEKDAYS_WIDE/WEEKDAYS_ABBR in
548
+ # packages/client/src/format-date.ts.
549
+ FORMAT_DATE_MONTHS_WIDE = 0
550
+ FORMAT_DATE_MONTHS_ABBR = 12
551
+ FORMAT_DATE_WEEKDAYS_WIDE = 24
552
+ FORMAT_DATE_WEEKDAYS_ABBR = 31
553
+
554
+ # `format_date(recv, pattern, tz, names)` (#2324/#2334, spec entry
555
+ # "format_date" in spec/template-helpers.md) -- the lowering target for
556
+ # `formatDate(date, pattern, timeZone, names)`
557
+ # (packages/client/src/format-date.ts, the JS-normative reference this
558
+ # must match byte-for-byte). Total and deterministic: no locale, no host
559
+ # timezone, no `Time.now`.
560
+ #
561
+ # recv: the same receiver contract as `date` above -- a native `Time` or
562
+ # an ISO-8601 string, normalized identically. A nil / unparseable
563
+ # receiver renders '' (never raises mid-render).
564
+ #
565
+ # tz: a fixed UTC offset `±HH:MM` shifts the instant by
566
+ # sign*(HH*60+MM) minutes; ANY other value -- 'UTC', an IANA zone name
567
+ # ('Asia/Tokyo'), or a malformed offset ('+9:00') -- normalizes to a
568
+ # zero-minute shift (UTC), so every backend degrades identically instead
569
+ # of dragging in host tzdata. The shifted instant's UTC calendar fields
570
+ # (not the original instant's) are what pattern tokens read -- the
571
+ # shifted UTC clock face IS the local clock face at that offset. `Time`
572
+ # arithmetic here is exact (Ruby represents the instant as a Rational,
573
+ # not a floor-divided epoch-millis integer), so there's no pre-1970
574
+ # negative-epoch floor-division trap to dodge the way a naive
575
+ # epoch-millis-div-86400000 implementation would hit; the shifted
576
+ # `Time#wday` (0 = Sunday) is likewise exact across the epoch boundary,
577
+ # so it doubles directly as the weekday-name table index.
578
+ #
579
+ # names: the flat table (#2334) -- `[0..11]` wide months, `[12..23]`
580
+ # abbreviated months, `[24..30]` wide weekdays (Sunday-first, matching
581
+ # the shifted `Time#wday`), `[31..37]` abbreviated weekdays. The caller
582
+ # owns the values (locale selection is never this method's job). An
583
+ # index past a missing/short table renders '' rather than raising.
584
+ #
585
+ # pattern: longest-match token substitution
586
+ # (`YYYY|MMMM|MMM|MM|DD|dddd|ddd|M|D`); every other character --
587
+ # including multi-byte ones like 年/月/日 -- passes through literally.
588
+ # `YYYY` is `abs(year)` zero-padded to 4 digits, `-`-prefixed for a
589
+ # negative year; `MM`/`DD` zero-pad to 2; `M`/`D` are bare; `MMMM`/`MMM`
590
+ # read the month's wide/abbreviated name; `dddd`/`ddd` read the shifted
591
+ # weekday's wide/abbreviated name.
592
+ def format_date(recv, pattern, tz, names = [])
593
+ t =
594
+ if recv.is_a?(Time)
595
+ recv
596
+ else
597
+ begin
598
+ Time.iso8601(recv.to_s)
599
+ rescue ArgumentError
600
+ nil
601
+ end
602
+ end
603
+ return '' if t.nil?
604
+
605
+ m = FORMAT_DATE_OFFSET_RE.match(tz.to_s)
606
+ offset_minutes = m ? (m[1] == '-' ? -1 : 1) * ((m[2].to_i * 60) + m[3].to_i) : 0
607
+
608
+ shifted = (t.utc + (offset_minutes * 60)).utc
609
+ year = shifted.year
610
+ month = shifted.mon
611
+ day = shifted.mday
612
+ weekday = shifted.wday # 0 = Sunday, matching the table's Sunday-first layout
613
+ yyyy = (year.negative? ? '-' : '') + year.abs.to_s.rjust(4, '0')
614
+ name_at = ->(index) { (names[index] || '').to_s }
615
+
616
+ pattern.gsub(FORMAT_DATE_TOKEN_RE) do |token|
617
+ case token
618
+ when 'YYYY' then yyyy
619
+ when 'MMMM' then name_at.call(FORMAT_DATE_MONTHS_WIDE + month - 1)
620
+ when 'MMM' then name_at.call(FORMAT_DATE_MONTHS_ABBR + month - 1)
621
+ when 'MM' then format('%02d', month)
622
+ when 'M' then month.to_s
623
+ when 'DD' then format('%02d', day)
624
+ when 'D' then day.to_s
625
+ when 'dddd' then name_at.call(FORMAT_DATE_WEEKDAYS_WIDE + weekday)
626
+ when 'ddd' then name_at.call(FORMAT_DATE_WEEKDAYS_ABBR + weekday)
627
+ end
628
+ end
629
+ end
630
+
532
631
  # -----------------------------------------------------------------
533
632
  # Array / String method helpers
534
633
  # -----------------------------------------------------------------
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barefoot_js
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.4
4
+ version: 0.24.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - kobaken
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-17 00:00:00.000000000 Z
11
+ date: 2026-07-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Engine-agnostic BarefootJS server runtime targeting ERB, ported from
14
14
  packages/adapter-perl/lib/BarefootJS.pm.