@jsenv/core 40.12.1 → 40.12.3

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.
@@ -2902,9 +2902,8 @@ const shouldHandleSourcemap = (urlInfo) => {
2902
2902
  return true;
2903
2903
  };
2904
2904
 
2905
- const inlineContentClientFileUrl = import.meta.resolve(
2906
- "../client/inline_content/inline_content.js",
2907
- );
2905
+ const inlineContentClientFileUrl = import.meta
2906
+ .resolve("../client/inline_content/inline_content.js");
2908
2907
 
2909
2908
  const createKitchen = ({
2910
2909
  name,
@@ -4101,9 +4100,8 @@ const jsenvPluginInlining = () => {
4101
4100
  };
4102
4101
 
4103
4102
  const jsenvPluginHtmlSyntaxErrorFallback = () => {
4104
- const htmlSyntaxErrorFileUrl = import.meta.resolve(
4105
- "../client/html_syntax_error/html_syntax_error.html",
4106
- );
4103
+ const htmlSyntaxErrorFileUrl = import.meta
4104
+ .resolve("../client/html_syntax_error/html_syntax_error.html");
4107
4105
 
4108
4106
  return {
4109
4107
  mustStayFirst: true,
@@ -6550,9 +6548,8 @@ const jsenvPluginVersionSearchParam = () => {
6550
6548
  */
6551
6549
 
6552
6550
 
6553
- const htmlFileUrlForDirectory = import.meta.resolve(
6554
- "../client/directory_listing/directory_listing.html",
6555
- );
6551
+ const htmlFileUrlForDirectory = import.meta
6552
+ .resolve("../client/directory_listing/directory_listing.html");
6556
6553
 
6557
6554
  const jsenvPluginDirectoryListing = ({
6558
6555
  spa,
@@ -7039,13 +7036,7 @@ const jsenvPluginFsRedirection = ({
7039
7036
  // 2. The url pathname does not have an extension
7040
7037
  // This point assume client is requesting a file when there is an extension
7041
7038
  // and it assumes all routes will not use extension
7042
- // 3. The url pathname does not ends with "/"
7043
- // In that case we assume client explicitely asks to load a directory
7044
- if (
7045
- spa &&
7046
- !urlToExtension(urlObject) &&
7047
- !urlToPathname(urlObject).endsWith("/")
7048
- ) {
7039
+ if (spa && !urlToExtension(urlObject)) {
7049
7040
  const { requestedUrl, rootDirectoryUrl, mainFilePath } =
7050
7041
  reference.ownerUrlInfo.context;
7051
7042
  const closestHtmlRootFile = getClosestHtmlRootFile(
@@ -7817,12 +7808,10 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
7817
7808
 
7818
7809
 
7819
7810
  const jsenvPluginImportMetaCss = () => {
7820
- const importMetaCssClientFileUrl = import.meta.resolve(
7821
- "../client/import_meta_css/import_meta_css.js",
7822
- );
7823
- const importMetaCssBuildFileUrl = import.meta.resolve(
7824
- "../client/import_meta_css/import_meta_css_build.js",
7825
- );
7811
+ const importMetaCssClientFileUrl = import.meta
7812
+ .resolve("../client/import_meta_css/import_meta_css.js");
7813
+ const importMetaCssBuildFileUrl = import.meta
7814
+ .resolve("../client/import_meta_css/import_meta_css_build.js");
7826
7815
 
7827
7816
  return {
7828
7817
  name: "jsenv:import_meta_css",
@@ -8154,9 +8143,8 @@ const htmlNodeCanHotReload = (node) => {
8154
8143
  };
8155
8144
 
8156
8145
  const jsenvPluginImportMetaHot = () => {
8157
- const importMetaHotClientFileUrl = import.meta.resolve(
8158
- "../client/import_meta_hot/import_meta_hot.js",
8159
- );
8146
+ const importMetaHotClientFileUrl = import.meta
8147
+ .resolve("../client/import_meta_hot/import_meta_hot.js");
8160
8148
 
8161
8149
  return {
8162
8150
  name: "jsenv:import_meta_hot",
@@ -8948,9 +8936,8 @@ const jsenvPluginChromeDevtoolsJson = () => {
8948
8936
  };
8949
8937
 
8950
8938
  const jsenvPluginAutoreloadOnServerRestart = () => {
8951
- const autoreloadOnRestartClientFileUrl = import.meta.resolve(
8952
- "@jsenv/server/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js",
8953
- );
8939
+ const autoreloadOnRestartClientFileUrl = import.meta
8940
+ .resolve("@jsenv/server/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js");
8954
8941
 
8955
8942
  return {
8956
8943
  name: "jsenv:autoreload_on_server_restart",
@@ -521,8 +521,6 @@ const SIGINT_CALLBACK = {
521
521
  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs#syntax
522
522
  */
523
523
 
524
- /* eslint-env browser, node */
525
-
526
524
  const DATA_URL = {
527
525
  parse: (string) => {
528
526
  const afterDataProtocol = string.slice("data:".length);
@@ -852,19 +850,47 @@ const setDecimalsPrecision = (
852
850
  // return numberTruncated
853
851
  // }
854
852
 
855
- const unitShort = {
856
- year: "y",
857
- month: "m",
858
- week: "w",
859
- day: "d",
860
- hour: "h",
861
- minute: "m",
862
- second: "s",
853
+ const UNIT_MS = {
854
+ year: 31_557_600_000,
855
+ month: 2_629_000_000,
856
+ week: 604_800_000,
857
+ day: 86_400_000,
858
+ hour: 3_600_000,
859
+ minute: 60_000,
860
+ second: 1000,
861
+ };
862
+ const UNIT_KEYS = Object.keys(UNIT_MS);
863
+ const SMALLEST_UNIT_NAME = UNIT_KEYS[UNIT_KEYS.length - 1];
864
+ const TIME_DICTIONARY_EN = {
865
+ year: { long: "year", plural: "years", short: "y" },
866
+ month: { long: "month", plural: "months", short: "m" },
867
+ week: { long: "week", plural: "weeks", short: "w" },
868
+ day: { long: "day", plural: "days", short: "d" },
869
+ hour: { long: "hour", plural: "hours", short: "h" },
870
+ minute: { long: "minute", plural: "minutes", short: "m" },
871
+ second: { long: "second", plural: "seconds", short: "s" },
872
+ joinDuration: (primary, remaining) => `${primary} and ${remaining}`,
873
+ };
874
+ const TIME_DICTIONARY_FR = {
875
+ year: { long: "an", plural: "ans", short: "a" },
876
+ month: { long: "mois", plural: "mois", short: "m" },
877
+ week: { long: "semaine", plural: "semaines", short: "s" },
878
+ day: { long: "jour", plural: "jours", short: "j" },
879
+ hour: { long: "heure", plural: "heures", short: "h" },
880
+ minute: { long: "minute", plural: "minutes", short: "m" },
881
+ second: { long: "seconde", plural: "secondes", short: "s" },
882
+ joinDuration: (primary, remaining) => `${primary} et ${remaining}`,
863
883
  };
864
884
 
865
885
  const humanizeDuration = (
866
886
  ms,
867
- { short, rounded = true, decimals } = {},
887
+ {
888
+ short,
889
+ rounded = true,
890
+ decimals,
891
+ lang = "en",
892
+ timeDictionnary = lang === "fr" ? TIME_DICTIONARY_FR : TIME_DICTIONARY_EN,
893
+ } = {},
868
894
  ) => {
869
895
  // ignore ms below meaningfulMs so that:
870
896
  // humanizeDuration(0.5) -> "0 second"
@@ -874,7 +900,9 @@ const humanizeDuration = (
874
900
  // yes we could return "0.1 millisecond" but we choosed consistency over precision
875
901
  // so that the prefered unit is "second" (and does not become millisecond when ms is super small)
876
902
  if (ms < 1) {
877
- return short ? "0s" : "0 second";
903
+ return short
904
+ ? `0${timeDictionnary.second.short}`
905
+ : `0 ${timeDictionnary.second.long}`;
878
906
  }
879
907
  const { primary, remaining } = parseMs(ms);
880
908
  if (!remaining) {
@@ -883,52 +911,51 @@ const humanizeDuration = (
883
911
  decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
884
912
  short,
885
913
  rounded,
914
+ timeDictionnary,
886
915
  });
887
916
  }
888
- return `${humanizeDurationUnit(primary, {
917
+ const primaryText = humanizeDurationUnit(primary, {
889
918
  decimals: decimals === undefined ? 0 : decimals,
890
919
  short,
891
920
  rounded,
892
- })} and ${humanizeDurationUnit(remaining, {
921
+ timeDictionnary,
922
+ });
923
+ const remainingText = humanizeDurationUnit(remaining, {
893
924
  decimals: decimals === undefined ? 0 : decimals,
894
925
  short,
895
926
  rounded,
896
- })}`;
927
+ timeDictionnary,
928
+ });
929
+ return timeDictionnary.joinDuration(primaryText, remainingText);
897
930
  };
898
- const humanizeDurationUnit = (unit, { decimals, short, rounded }) => {
931
+ const humanizeDurationUnit = (
932
+ unit,
933
+ { decimals, short, rounded, timeDictionnary },
934
+ ) => {
899
935
  const count = rounded
900
936
  ? setRoundedPrecision(unit.count, { decimals })
901
937
  : setPrecision(unit.count, { decimals });
902
- let name = unit.name;
938
+ const name = unit.name;
903
939
  if (short) {
904
- name = unitShort[name];
905
- return `${count}${name}`;
940
+ const unitText = timeDictionnary[name].short;
941
+ return `${count}${unitText}`;
906
942
  }
907
943
  if (count <= 1) {
908
- return `${count} ${name}`;
944
+ const unitText = timeDictionnary[name].long;
945
+ return `${count} ${unitText}`;
909
946
  }
910
- return `${count} ${name}s`;
911
- };
912
- const MS_PER_UNITS = {
913
- year: 31_557_600_000,
914
- month: 2_629_000_000,
915
- week: 604_800_000,
916
- day: 86_400_000,
917
- hour: 3_600_000,
918
- minute: 60_000,
919
- second: 1000,
947
+ const unitText = timeDictionnary[name].plural;
948
+ return `${count} ${unitText}`;
920
949
  };
921
950
 
922
951
  const parseMs = (ms) => {
923
- const unitNames = Object.keys(MS_PER_UNITS);
924
- const smallestUnitName = unitNames[unitNames.length - 1];
925
- let firstUnitName = smallestUnitName;
926
- let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
927
- const firstUnitIndex = unitNames.findIndex((unitName) => {
928
- if (unitName === smallestUnitName) {
952
+ let firstUnitName = SMALLEST_UNIT_NAME;
953
+ let firstUnitCount = ms / UNIT_MS[SMALLEST_UNIT_NAME];
954
+ const firstUnitIndex = UNIT_KEYS.findIndex((unitName) => {
955
+ if (unitName === SMALLEST_UNIT_NAME) {
929
956
  return false;
930
957
  }
931
- const msPerUnit = MS_PER_UNITS[unitName];
958
+ const msPerUnit = UNIT_MS[unitName];
932
959
  const unitCount = Math.floor(ms / msPerUnit);
933
960
  if (unitCount) {
934
961
  firstUnitName = unitName;
@@ -937,7 +964,7 @@ const parseMs = (ms) => {
937
964
  }
938
965
  return false;
939
966
  });
940
- if (firstUnitName === smallestUnitName) {
967
+ if (firstUnitName === SMALLEST_UNIT_NAME) {
941
968
  return {
942
969
  primary: {
943
970
  name: firstUnitName,
@@ -945,9 +972,9 @@ const parseMs = (ms) => {
945
972
  },
946
973
  };
947
974
  }
948
- const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
949
- const remainingUnitName = unitNames[firstUnitIndex + 1];
950
- const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
975
+ const remainingMs = ms - firstUnitCount * UNIT_MS[firstUnitName];
976
+ const remainingUnitName = UNIT_KEYS[firstUnitIndex + 1];
977
+ const remainingUnitCount = remainingMs / UNIT_MS[remainingUnitName];
951
978
  // - 1 year and 1 second is too much information
952
979
  // so we don't check the remaining units
953
980
  // - 1 year and 0.0001 week is awful
@@ -1,5 +1,3 @@
1
- /* eslint-env browser,node */
2
-
3
1
  /*
4
2
  * This file does not use export const InlineContent = function() {} on purpose:
5
3
  * - An export would be renamed by rollup,
@@ -2,14 +2,14 @@ const injectRibbon = ({ text }) => {
2
2
  const css = /* css */ `
3
3
  #jsenv_ribbon_container {
4
4
  position: fixed;
5
- z-index: 1001;
6
5
  top: 0;
7
6
  right: 0;
7
+ z-index: 1001;
8
8
  width: 100px;
9
9
  height: 100px;
10
- overflow: hidden;
11
10
  opacity: 0.5;
12
11
  pointer-events: none;
12
+ overflow: hidden;
13
13
  }
14
14
  #jsenv_ribbon {
15
15
  position: absolute;
@@ -20,20 +20,20 @@ const injectRibbon = ({ text }) => {
20
20
  }
21
21
  #jsenv_ribbon_text {
22
22
  position: absolute;
23
- left: 0px;
24
23
  top: 20px;
25
- transform: rotate(45deg);
24
+ left: 0px;
26
25
  display: block;
27
26
  width: 125px;
28
- line-height: 36px;
29
- background-color: orange;
30
27
  color: rgb(55, 7, 7);
31
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
32
28
  font-weight: 700;
33
29
  font-size: 16px;
34
30
  font-family: "Lato", sans-serif;
35
- text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
36
31
  text-align: center;
32
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
33
+ line-height: 36px;
34
+ background-color: orange;
35
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
36
+ transform: rotate(45deg);
37
37
  user-select: none;
38
38
  }
39
39
  `;
@@ -760,19 +760,47 @@ const setDecimalsPrecision = (
760
760
  // return numberTruncated
761
761
  // }
762
762
 
763
- const unitShort = {
764
- year: "y",
765
- month: "m",
766
- week: "w",
767
- day: "d",
768
- hour: "h",
769
- minute: "m",
770
- second: "s",
763
+ const UNIT_MS = {
764
+ year: 31_557_600_000,
765
+ month: 2_629_000_000,
766
+ week: 604_800_000,
767
+ day: 86_400_000,
768
+ hour: 3_600_000,
769
+ minute: 60_000,
770
+ second: 1000,
771
+ };
772
+ const UNIT_KEYS = Object.keys(UNIT_MS);
773
+ const SMALLEST_UNIT_NAME = UNIT_KEYS[UNIT_KEYS.length - 1];
774
+ const TIME_DICTIONARY_EN = {
775
+ year: { long: "year", plural: "years", short: "y" },
776
+ month: { long: "month", plural: "months", short: "m" },
777
+ week: { long: "week", plural: "weeks", short: "w" },
778
+ day: { long: "day", plural: "days", short: "d" },
779
+ hour: { long: "hour", plural: "hours", short: "h" },
780
+ minute: { long: "minute", plural: "minutes", short: "m" },
781
+ second: { long: "second", plural: "seconds", short: "s" },
782
+ joinDuration: (primary, remaining) => `${primary} and ${remaining}`,
783
+ };
784
+ const TIME_DICTIONARY_FR = {
785
+ year: { long: "an", plural: "ans", short: "a" },
786
+ month: { long: "mois", plural: "mois", short: "m" },
787
+ week: { long: "semaine", plural: "semaines", short: "s" },
788
+ day: { long: "jour", plural: "jours", short: "j" },
789
+ hour: { long: "heure", plural: "heures", short: "h" },
790
+ minute: { long: "minute", plural: "minutes", short: "m" },
791
+ second: { long: "seconde", plural: "secondes", short: "s" },
792
+ joinDuration: (primary, remaining) => `${primary} et ${remaining}`,
771
793
  };
772
794
 
773
795
  const humanizeDuration = (
774
796
  ms,
775
- { short, rounded = true, decimals } = {},
797
+ {
798
+ short,
799
+ rounded = true,
800
+ decimals,
801
+ lang = "en",
802
+ timeDictionnary = lang === "fr" ? TIME_DICTIONARY_FR : TIME_DICTIONARY_EN,
803
+ } = {},
776
804
  ) => {
777
805
  // ignore ms below meaningfulMs so that:
778
806
  // humanizeDuration(0.5) -> "0 second"
@@ -782,7 +810,9 @@ const humanizeDuration = (
782
810
  // yes we could return "0.1 millisecond" but we choosed consistency over precision
783
811
  // so that the prefered unit is "second" (and does not become millisecond when ms is super small)
784
812
  if (ms < 1) {
785
- return short ? "0s" : "0 second";
813
+ return short
814
+ ? `0${timeDictionnary.second.short}`
815
+ : `0 ${timeDictionnary.second.long}`;
786
816
  }
787
817
  const { primary, remaining } = parseMs(ms);
788
818
  if (!remaining) {
@@ -791,52 +821,51 @@ const humanizeDuration = (
791
821
  decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
792
822
  short,
793
823
  rounded,
824
+ timeDictionnary,
794
825
  });
795
826
  }
796
- return `${humanizeDurationUnit(primary, {
827
+ const primaryText = humanizeDurationUnit(primary, {
797
828
  decimals: decimals === undefined ? 0 : decimals,
798
829
  short,
799
830
  rounded,
800
- })} and ${humanizeDurationUnit(remaining, {
831
+ timeDictionnary,
832
+ });
833
+ const remainingText = humanizeDurationUnit(remaining, {
801
834
  decimals: decimals === undefined ? 0 : decimals,
802
835
  short,
803
836
  rounded,
804
- })}`;
837
+ timeDictionnary,
838
+ });
839
+ return timeDictionnary.joinDuration(primaryText, remainingText);
805
840
  };
806
- const humanizeDurationUnit = (unit, { decimals, short, rounded }) => {
841
+ const humanizeDurationUnit = (
842
+ unit,
843
+ { decimals, short, rounded, timeDictionnary },
844
+ ) => {
807
845
  const count = rounded
808
846
  ? setRoundedPrecision(unit.count, { decimals })
809
847
  : setPrecision(unit.count, { decimals });
810
- let name = unit.name;
848
+ const name = unit.name;
811
849
  if (short) {
812
- name = unitShort[name];
813
- return `${count}${name}`;
850
+ const unitText = timeDictionnary[name].short;
851
+ return `${count}${unitText}`;
814
852
  }
815
853
  if (count <= 1) {
816
- return `${count} ${name}`;
854
+ const unitText = timeDictionnary[name].long;
855
+ return `${count} ${unitText}`;
817
856
  }
818
- return `${count} ${name}s`;
819
- };
820
- const MS_PER_UNITS = {
821
- year: 31_557_600_000,
822
- month: 2_629_000_000,
823
- week: 604_800_000,
824
- day: 86_400_000,
825
- hour: 3_600_000,
826
- minute: 60_000,
827
- second: 1000,
857
+ const unitText = timeDictionnary[name].plural;
858
+ return `${count} ${unitText}`;
828
859
  };
829
860
 
830
861
  const parseMs = (ms) => {
831
- const unitNames = Object.keys(MS_PER_UNITS);
832
- const smallestUnitName = unitNames[unitNames.length - 1];
833
- let firstUnitName = smallestUnitName;
834
- let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
835
- const firstUnitIndex = unitNames.findIndex((unitName) => {
836
- if (unitName === smallestUnitName) {
862
+ let firstUnitName = SMALLEST_UNIT_NAME;
863
+ let firstUnitCount = ms / UNIT_MS[SMALLEST_UNIT_NAME];
864
+ const firstUnitIndex = UNIT_KEYS.findIndex((unitName) => {
865
+ if (unitName === SMALLEST_UNIT_NAME) {
837
866
  return false;
838
867
  }
839
- const msPerUnit = MS_PER_UNITS[unitName];
868
+ const msPerUnit = UNIT_MS[unitName];
840
869
  const unitCount = Math.floor(ms / msPerUnit);
841
870
  if (unitCount) {
842
871
  firstUnitName = unitName;
@@ -845,7 +874,7 @@ const parseMs = (ms) => {
845
874
  }
846
875
  return false;
847
876
  });
848
- if (firstUnitName === smallestUnitName) {
877
+ if (firstUnitName === SMALLEST_UNIT_NAME) {
849
878
  return {
850
879
  primary: {
851
880
  name: firstUnitName,
@@ -853,9 +882,9 @@ const parseMs = (ms) => {
853
882
  },
854
883
  };
855
884
  }
856
- const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
857
- const remainingUnitName = unitNames[firstUnitIndex + 1];
858
- const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
885
+ const remainingMs = ms - firstUnitCount * UNIT_MS[firstUnitName];
886
+ const remainingUnitName = UNIT_KEYS[firstUnitIndex + 1];
887
+ const remainingUnitCount = remainingMs / UNIT_MS[remainingUnitName];
859
888
  // - 1 year and 1 second is too much information
860
889
  // so we don't check the remaining units
861
890
  // - 1 year and 0.0001 week is awful
@@ -10,8 +10,6 @@ import { pathToFileURL, fileURLToPath } from "node:url";
10
10
  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs#syntax
11
11
  */
12
12
 
13
- /* eslint-env browser, node */
14
-
15
13
  const DATA_URL = {
16
14
  parse: (string) => {
17
15
  const afterDataProtocol = string.slice("data:".length);
@@ -360,19 +358,47 @@ const setDecimalsPrecision = (
360
358
  // return numberTruncated
361
359
  // }
362
360
 
363
- const unitShort = {
364
- year: "y",
365
- month: "m",
366
- week: "w",
367
- day: "d",
368
- hour: "h",
369
- minute: "m",
370
- second: "s",
361
+ const UNIT_MS = {
362
+ year: 31_557_600_000,
363
+ month: 2_629_000_000,
364
+ week: 604_800_000,
365
+ day: 86_400_000,
366
+ hour: 3_600_000,
367
+ minute: 60_000,
368
+ second: 1000,
369
+ };
370
+ const UNIT_KEYS = Object.keys(UNIT_MS);
371
+ const SMALLEST_UNIT_NAME = UNIT_KEYS[UNIT_KEYS.length - 1];
372
+ const TIME_DICTIONARY_EN = {
373
+ year: { long: "year", plural: "years", short: "y" },
374
+ month: { long: "month", plural: "months", short: "m" },
375
+ week: { long: "week", plural: "weeks", short: "w" },
376
+ day: { long: "day", plural: "days", short: "d" },
377
+ hour: { long: "hour", plural: "hours", short: "h" },
378
+ minute: { long: "minute", plural: "minutes", short: "m" },
379
+ second: { long: "second", plural: "seconds", short: "s" },
380
+ joinDuration: (primary, remaining) => `${primary} and ${remaining}`,
381
+ };
382
+ const TIME_DICTIONARY_FR = {
383
+ year: { long: "an", plural: "ans", short: "a" },
384
+ month: { long: "mois", plural: "mois", short: "m" },
385
+ week: { long: "semaine", plural: "semaines", short: "s" },
386
+ day: { long: "jour", plural: "jours", short: "j" },
387
+ hour: { long: "heure", plural: "heures", short: "h" },
388
+ minute: { long: "minute", plural: "minutes", short: "m" },
389
+ second: { long: "seconde", plural: "secondes", short: "s" },
390
+ joinDuration: (primary, remaining) => `${primary} et ${remaining}`,
371
391
  };
372
392
 
373
393
  const humanizeDuration = (
374
394
  ms,
375
- { short, rounded = true, decimals } = {},
395
+ {
396
+ short,
397
+ rounded = true,
398
+ decimals,
399
+ lang = "en",
400
+ timeDictionnary = lang === "fr" ? TIME_DICTIONARY_FR : TIME_DICTIONARY_EN,
401
+ } = {},
376
402
  ) => {
377
403
  // ignore ms below meaningfulMs so that:
378
404
  // humanizeDuration(0.5) -> "0 second"
@@ -382,7 +408,9 @@ const humanizeDuration = (
382
408
  // yes we could return "0.1 millisecond" but we choosed consistency over precision
383
409
  // so that the prefered unit is "second" (and does not become millisecond when ms is super small)
384
410
  if (ms < 1) {
385
- return short ? "0s" : "0 second";
411
+ return short
412
+ ? `0${timeDictionnary.second.short}`
413
+ : `0 ${timeDictionnary.second.long}`;
386
414
  }
387
415
  const { primary, remaining } = parseMs(ms);
388
416
  if (!remaining) {
@@ -391,52 +419,51 @@ const humanizeDuration = (
391
419
  decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
392
420
  short,
393
421
  rounded,
422
+ timeDictionnary,
394
423
  });
395
424
  }
396
- return `${humanizeDurationUnit(primary, {
425
+ const primaryText = humanizeDurationUnit(primary, {
397
426
  decimals: decimals === undefined ? 0 : decimals,
398
427
  short,
399
428
  rounded,
400
- })} and ${humanizeDurationUnit(remaining, {
429
+ timeDictionnary,
430
+ });
431
+ const remainingText = humanizeDurationUnit(remaining, {
401
432
  decimals: decimals === undefined ? 0 : decimals,
402
433
  short,
403
434
  rounded,
404
- })}`;
435
+ timeDictionnary,
436
+ });
437
+ return timeDictionnary.joinDuration(primaryText, remainingText);
405
438
  };
406
- const humanizeDurationUnit = (unit, { decimals, short, rounded }) => {
439
+ const humanizeDurationUnit = (
440
+ unit,
441
+ { decimals, short, rounded, timeDictionnary },
442
+ ) => {
407
443
  const count = rounded
408
444
  ? setRoundedPrecision(unit.count, { decimals })
409
445
  : setPrecision(unit.count, { decimals });
410
- let name = unit.name;
446
+ const name = unit.name;
411
447
  if (short) {
412
- name = unitShort[name];
413
- return `${count}${name}`;
448
+ const unitText = timeDictionnary[name].short;
449
+ return `${count}${unitText}`;
414
450
  }
415
451
  if (count <= 1) {
416
- return `${count} ${name}`;
452
+ const unitText = timeDictionnary[name].long;
453
+ return `${count} ${unitText}`;
417
454
  }
418
- return `${count} ${name}s`;
419
- };
420
- const MS_PER_UNITS = {
421
- year: 31_557_600_000,
422
- month: 2_629_000_000,
423
- week: 604_800_000,
424
- day: 86_400_000,
425
- hour: 3_600_000,
426
- minute: 60_000,
427
- second: 1000,
455
+ const unitText = timeDictionnary[name].plural;
456
+ return `${count} ${unitText}`;
428
457
  };
429
458
 
430
459
  const parseMs = (ms) => {
431
- const unitNames = Object.keys(MS_PER_UNITS);
432
- const smallestUnitName = unitNames[unitNames.length - 1];
433
- let firstUnitName = smallestUnitName;
434
- let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
435
- const firstUnitIndex = unitNames.findIndex((unitName) => {
436
- if (unitName === smallestUnitName) {
460
+ let firstUnitName = SMALLEST_UNIT_NAME;
461
+ let firstUnitCount = ms / UNIT_MS[SMALLEST_UNIT_NAME];
462
+ const firstUnitIndex = UNIT_KEYS.findIndex((unitName) => {
463
+ if (unitName === SMALLEST_UNIT_NAME) {
437
464
  return false;
438
465
  }
439
- const msPerUnit = MS_PER_UNITS[unitName];
466
+ const msPerUnit = UNIT_MS[unitName];
440
467
  const unitCount = Math.floor(ms / msPerUnit);
441
468
  if (unitCount) {
442
469
  firstUnitName = unitName;
@@ -445,7 +472,7 @@ const parseMs = (ms) => {
445
472
  }
446
473
  return false;
447
474
  });
448
- if (firstUnitName === smallestUnitName) {
475
+ if (firstUnitName === SMALLEST_UNIT_NAME) {
449
476
  return {
450
477
  primary: {
451
478
  name: firstUnitName,
@@ -453,9 +480,9 @@ const parseMs = (ms) => {
453
480
  },
454
481
  };
455
482
  }
456
- const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
457
- const remainingUnitName = unitNames[firstUnitIndex + 1];
458
- const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
483
+ const remainingMs = ms - firstUnitCount * UNIT_MS[firstUnitName];
484
+ const remainingUnitName = UNIT_KEYS[firstUnitIndex + 1];
485
+ const remainingUnitCount = remainingMs / UNIT_MS[remainingUnitName];
459
486
  // - 1 year and 1 second is too much information
460
487
  // so we don't check the remaining units
461
488
  // - 1 year and 0.0001 week is awful