pagy 43.0.0.rc4 → 43.0.0
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.
- checksums.yaml +4 -4
 - data/apps/calendar.ru +1 -2
 - data/apps/demo.ru +2 -2
 - data/apps/keynav.ru +1 -1
 - data/apps/keyset.ru +1 -1
 - data/apps/keyset_sequel.ru +1 -1
 - data/apps/rails.ru +1 -1
 - data/apps/repro.ru +1 -1
 - data/bin/pagy +1 -1
 - data/config/pagy.rb +1 -1
 - data/javascripts/pagy.js +2 -2
 - data/javascripts/pagy.js.map +2 -2
 - data/javascripts/pagy.min.js +1 -1
 - data/javascripts/pagy.mjs +1 -1
 - data/lib/pagy/classes/calendar/unit.rb +1 -0
 - data/lib/pagy/classes/keyset/keynav.rb +1 -0
 - data/lib/pagy/classes/offset/offset.rb +1 -0
 - data/lib/pagy/toolbox/helpers/data_hash.rb +4 -3
 - data/lib/pagy/toolbox/helpers/headers_hash.rb +10 -6
 - data/lib/pagy/toolbox/helpers/input_nav_js.rb +1 -2
 - data/lib/pagy/toolbox/helpers/series_nav.rb +1 -2
 - data/lib/pagy/toolbox/helpers/series_nav_js.rb +0 -1
 - data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +1 -1
 - data/lib/pagy/toolbox/paginators/meilisearch.rb +1 -1
 - data/lib/pagy/toolbox/paginators/searchkick.rb +1 -1
 - data/lib/pagy.rb +1 -1
 - metadata +1 -1
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 66a384673ddf0542be2e0a2b39001fef7780ef67fa39d5a1b0cf2f8b94e01761
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 564de9f2bd8c03bb1fa58226ee2a4c42f11c6e1dc9a3ed14ae6264f8f45186d3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 340e0c7178341b87c86d6930a60d6c1e3a25989f992193aacd0bb82b3f6631d0fba81f0d95d3c37db27bae971f8bd9a6db60194fa3cfc7c1e9bfde9294b360ef
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 46a3dfdf18bc20ba1d86eccb7d9883abfd5666ce4b3c2f5b1de9dbaa3583412e1da6544117074554088b64dc0b119d4358c676b37e1d31d4604964cbd89f827b
         
     | 
    
        data/apps/calendar.ru
    CHANGED
    
    | 
         @@ -16,7 +16,7 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            # URL
         
     | 
| 
       17 
17 
     | 
    
         
             
            #    http://127.0.0.1:8000
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
            VERSION = '43.0.0 
     | 
| 
      
 19 
     | 
    
         
            +
            VERSION = '43.0.0'
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            if VERSION != Pagy::VERSION
         
     | 
| 
       22 
22 
     | 
    
         
             
              Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
         
     | 
| 
         @@ -198,7 +198,6 @@ abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writab 
     | 
|
| 
       198 
198 
     | 
    
         
             
                  unless File.writable?(dir)
         
     | 
| 
       199 
199 
     | 
    
         
             
            # Connection
         
     | 
| 
       200 
200 
     | 
    
         
             
            ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-calendar.sqlite3")
         
     | 
| 
       201 
     | 
    
         
            -
            ActiveSupport.to_time_preserves_timezone = :zone  # Fix ActiveSupport deprecation
         
     | 
| 
       202 
201 
     | 
    
         
             
            Date.beginning_of_week = :monday   # just for rails default compatibiity
         
     | 
| 
       203 
202 
     | 
    
         
             
            # Groupdate initializer  (https://github.com/ankane/groupdate)
         
     | 
| 
       204 
203 
     | 
    
         
             
            # Groupdate week_start default is :sunday, while rails and pagy default to :monday
         
     | 
    
        data/apps/demo.ru
    CHANGED
    
    | 
         @@ -19,7 +19,7 @@ 
     | 
|
| 
       19 
19 
     | 
    
         
             
            # URL
         
     | 
| 
       20 
20 
     | 
    
         
             
            #    http://127.0.0.1:8000
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
            VERSION = '43.0.0 
     | 
| 
      
 22 
     | 
    
         
            +
            VERSION = '43.0.0'
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
            if VERSION != Pagy::VERSION
         
     | 
| 
       25 
25 
     | 
    
         
             
              Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
         
     | 
| 
         @@ -124,7 +124,7 @@ class PagyDemo < Sinatra::Base 
     | 
|
| 
       124 
124 
     | 
    
         | 
| 
       125 
125 
     | 
    
         
             
                def highlight(html, format: :html)
         
     | 
| 
       126 
126 
     | 
    
         
             
                  if format == :html
         
     | 
| 
       127 
     | 
    
         
            -
                    html = html.gsub( 
     | 
| 
      
 127 
     | 
    
         
            +
                    html = html.gsub(/>\s*</, '><').strip # template single line no spaces around/between tags
         
     | 
| 
       128 
128 
     | 
    
         
             
                    html = Formatter.new.format(html)
         
     | 
| 
       129 
129 
     | 
    
         
             
                  end
         
     | 
| 
       130 
130 
     | 
    
         
             
                  lexer     = Rouge::Lexers::ERB.new
         
     | 
    
        data/apps/keynav.ru
    CHANGED
    
    
    
        data/apps/keyset.ru
    CHANGED
    
    
    
        data/apps/keyset_sequel.ru
    CHANGED
    
    
    
        data/apps/rails.ru
    CHANGED
    
    
    
        data/apps/repro.ru
    CHANGED
    
    
    
        data/bin/pagy
    CHANGED
    
    
    
        data/config/pagy.rb
    CHANGED
    
    
    
        data/javascripts/pagy.js
    CHANGED
    
    | 
         @@ -124,7 +124,7 @@ window.Pagy = (() => { 
     | 
|
| 
       124 
124 
     | 
    
         
             
                });
         
     | 
| 
       125 
125 
     | 
    
         
             
              };
         
     | 
| 
       126 
126 
     | 
    
         
             
              return {
         
     | 
| 
       127 
     | 
    
         
            -
                version: "43.0.0 
     | 
| 
      
 127 
     | 
    
         
            +
                version: "43.0.0",
         
     | 
| 
       128 
128 
     | 
    
         
             
                init(arg) {
         
     | 
| 
       129 
129 
     | 
    
         
             
                  const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
         
     | 
| 
       130 
130 
     | 
    
         
             
                  for (const element of elements) {
         
     | 
| 
         @@ -147,5 +147,5 @@ window.Pagy = (() => { 
     | 
|
| 
       147 
147 
     | 
    
         
             
              };
         
     | 
| 
       148 
148 
     | 
    
         
             
            })();
         
     | 
| 
       149 
149 
     | 
    
         | 
| 
       150 
     | 
    
         
            -
            //# debugId= 
     | 
| 
      
 150 
     | 
    
         
            +
            //# debugId=46963D274F782A9664756E2164756E21
         
     | 
| 
       151 
151 
     | 
    
         
             
            //# sourceMappingURL=pagy.js.map
         
     | 
    
        data/javascripts/pagy.js.map
    CHANGED
    
    | 
         @@ -2,9 +2,9 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
              "version": 3,
         
     | 
| 
       3 
3 
     | 
    
         
             
              "sources": ["../../src/pagy.ts"],
         
     | 
| 
       4 
4 
     | 
    
         
             
              "sourcesContent": [
         
     | 
| 
       5 
     | 
    
         
            -
                "interface SyncData {\n  from?: number\n  to?:   number\n  key:   string\n  str?:  string\n}\ntype InitArgs = [\"k\",  KeynavArgs] |          // series_nav[_js] with keynav instance\n                [\"snj\", SeriesNavJsArgs] |    // series_nav_js\n                [\"inj\", InputNavJsArgs] |     // input_nav_js\n                [\"ltj\", LimitTagJsArgs]       // limit_tag_js\ntype AugmentKeynav = (nav:HTMLElement, keynavArgs:KeynavArgs) => Promise<((page: string) => string)>\ntype KeynavArgs = readonly [storageKey:  string | null,\n                            pageKey:     string,\n                            last:        number,\n                            spliceArgs?: SpliceArgs]\ntype SpliceArgs = readonly [start:       number,\n                            deleteCount: number,     // it would be optional, but ts complains\n                            ...items:    Cutoff[]]\ntype Cutoff = readonly (string | number | boolean)[]\ntype AugmentedPage = [browserId:   string,\n                      storageKey:  string,\n                      pageNumber:  number,\n                      pages:       number,\n                      priorCutoff: Cutoff | null,\n                      pageCutoff:  Cutoff | null]\ntype SeriesNavJsArgs = readonly [NavJsTokens, NavJsSeries, KeynavArgs?]\ntype NavJsSeries = readonly [widths: number[],\n                             series: (string | number)[][],\n                             labels: string[][] | null]\ntype InputNavJsArgs = readonly [urlToken: string, KeynavArgs?]\ntype LimitTagJsArgs = readonly [from:     number,\n                                urlToken: string]\ntype NavJsTokens = readonly [before:  string,\n                             anchor:  string,\n                             current: string,\n                             gap:     string,\n                             after:   string]\ninterface NavJsElement extends HTMLElement {\n  render(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Pagy = (() => {\n  const storageSupport = 'sessionStorage' in window && 'BroadcastChannel' in window,\n        pageRe         = \"P \";  // shorten the compiled size\n  // eslint-disable-next-line prefer-const\n  let pagy = \"pagy\", storage: Storage, sync: BroadcastChannel, tabId: number;\n  if (storageSupport) {\n    storage = sessionStorage; // shorten the compiled size\n    sync    = new BroadcastChannel(pagy);\n    tabId   = Date.now();\n    // Sync the sessionStorage keys for the cutoffs opened in a new tab/window\n    sync.addEventListener(\"message\", (e:MessageEvent<SyncData>) => {\n      if (e.data.from) { // request cutoffs\n        const cutoffs = storage.getItem(e.data.key);\n        if (cutoffs) {\n          sync.postMessage(<SyncData>{to: e.data.from, key: e.data.key, str: cutoffs});\n        } // send response\n      } else if (e.data.to) {  // receive cutoffs\n        if (e.data.to == tabId) {\n          storage.setItem(e.data.key, <string>e.data.str);\n        }\n      }\n    });\n  }\n  // The observer instance for responsive navs\n  const rjsObserver = new ResizeObserver(\n      entries => entries.forEach(e => {\n        e.target.querySelectorAll<NavJsElement>(\".pagy-rjs\").forEach(el => el.render());\n      }));\n\n  /* Full set of B64 functions\n  const B64Encode     = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode))),\n        B64Safe       = (unsafe:string)  => unsafe.replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n        B64SafeEncode = (unicode:string) => B64Safe(B64Encode(unicode)),\n        B64Decode     = (base64:string)  => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0))),\n        B64Unsafe     = (safe:string)    => safe.replace(/[-_]/g, (match) => match == \"-\" ? \"+\" : \"/\"),\n        B64SafeDecode = (base64:string)  => B64Decode(B64Unsafe(base64))\n  */\n  const B64SafeEncode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode)))\n                                            .replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n        B64Decode     = (base64:string)  => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0)));\n\n  // Return a random key: 3 chars max, base-36 number < 36**3\n  const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);\n\n  // Manage the page augmentation for Keynav, called only if storageSupport\n  const augmentKeynav: AugmentKeynav = async (nav, [storageKey, pageKey, last, spliceArgs]) => {\n    let augment;\n    const browserKey = document.cookie.split(/;\\s+/)  // it works even if malformed\n                               .find((row) => row.startsWith(pagy + \"=\"))\n                               ?.split(\"=\")[1] ?? randKey();\n    document.cookie = pagy + \"=\" + browserKey;  // Smaller .min size: set the cookie without checking\n    if (storageKey && !(storageKey in storage)) {\n      // Sync the sessiongStorage from other tabs/windows (e.g., open page in the new tab/window)\n      sync.postMessage(<SyncData>{ from: tabId, key: storageKey });\n      // Wait for the listener to copy the cutoffs in the current sessionStorage\n      await new Promise<string|null>((resolve) => setTimeout(() => resolve(\"\"), 100));\n      if (!(storageKey in storage)) { // the storageKey didn't get copied: fallback to countless pagination\n        augment = (page: string) => page + '+' + last;\n      }\n    }\n    if (!augment) { // regular keynav pagination\n      if (!storageKey) { do { storageKey = randKey() } while (storageKey in storage) } // no dup keys\n      const data = storage.getItem(storageKey),\n          cutoffs = <Cutoff[]>(data ? JSON.parse(data) : [undefined]);\n      if (spliceArgs) {\n        cutoffs.splice(...spliceArgs);\n        storage.setItem(storageKey, JSON.stringify(cutoffs));\n      }\n      // Augment function\n      augment = (page:string) => {\n        const pageNum = parseInt(page);\n        return B64SafeEncode(JSON.stringify(\n            <AugmentedPage>[browserKey,\n                            storageKey,\n                            pageNum,\n                            cutoffs.length,       // pages/last\n                            cutoffs[pageNum - 1], // priorCutoff\n                            cutoffs[pageNum]]));  // pageCutoff\n      };\n    }\n    // Augment the page param of each href\n    for (const a of <NodeListOf<HTMLAnchorElement>><unknown>nav.querySelectorAll('a[href]')) {\n      const url = a.href,\n            re  = new RegExp(`(?<=\\\\?.*)\\\\b${pageKey}=(\\\\d+)`);         // find the numeric page from pageKey\n      a.href    = url.replace(re, pageKey + \"=\" + augment(url.match(re)![1]));  // eslint-disable-line @typescript-eslint/no-non-null-assertion\n    }\n    // Return the augment function for further augmentation (i.e., url token in input_nav_js)\n    return augment;\n  };\n\n  // Build the series_nav_js helper\n  const buildNavJs = (nav:NavJsElement, [[before, anchor, current, gap, after],\n                                        [widths, series, labels], keynavArgs]:SeriesNavJsArgs) => {\n    const  parent = <HTMLElement>nav.parentElement;\n    let lastWidth = -1;\n    (nav.render = () => {\n      const index = widths.findIndex(w => w < parent.clientWidth);\n      if (widths[index] === lastWidth) { return } // no change: abort\n\n      let html = before;\n      series[index].forEach((item, i) => {\n        // Avoid the if blocks and chain the results (shorter pagy.min.js and easier reading)\n        html += item == \"gap\" ? gap :\n                // @ts-expect-error the item may be a number, but the 'replace' converts it to string (shorter pagy.min.js)\n                (typeof item == \"number\" ? anchor.replace(pageRe, item) : current)\n                    .replace(\"L<\", labels?.[index][i] ?? item + \"<\");\n      });\n      html         += after;\n      nav.innerHTML = \"\";\n      nav.insertAdjacentHTML(\"afterbegin\", html);\n      lastWidth = widths[index];\n      if (keynavArgs && storageSupport) { void augmentKeynav(nav, keynavArgs) }\n    })();\n    if (nav.classList.contains(pagy + \"-rjs\")) { rjsObserver.observe(parent) }\n  };\n\n  // Init the input_nav_js helpers\n  const initInputNavJs = async (nav:HTMLElement, [url_token, keynavArgs]:InputNavJsArgs) => {\n    const augment = keynavArgs && storageSupport\n                    ? await augmentKeynav(nav, keynavArgs)\n                    : (page: string) => page;\n    initInput(nav, inputValue => url_token.replace(pageRe, augment(inputValue)));\n  };\n\n  // Init the limit_tag_js helper\n  const initLimitTagJs = (span:HTMLSpanElement, [from, url_token]:LimitTagJsArgs) => {\n    initInput(span, inputValue => {\n      // @ts-expect-error the page is a number, but the 'replace' converts it to string (shorter pagy.min.js)\n      return url_token.replace(pageRe, Math.max(Math.ceil(from / parseInt(inputValue)), 1))\n                      .replace('L ', inputValue);\n    });\n  };\n\n  // Init the input element\n  const initInput = (element:HTMLElement, getUrl:(v:string) => string) => {\n    const input   = <HTMLInputElement>element.querySelector(\"input\"),\n          link    = <HTMLAnchorElement>element.querySelector(\"a\"),\n          initial = input.value,\n          action  = () => {\n                      if (input.value === initial) { return }  // not changed\n                      const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);\n                      if (val < min || val > max) {  // reset invalid/out-of-range\n                        input.value = initial;\n                        input.select();\n                        return;\n                      }\n                      link.href = getUrl(input.value);\n                      link.click();\n                    };\n    input.addEventListener(\"focus\", () => input.select());\n    input.addEventListener(\"focusout\", action);\n    input.addEventListener(\"keypress\", e => { if (e.key == \"Enter\") { action() } });\n  };\n\n  // Public interface\n  return {\n    version: \"43.0.0.rc4\",\n\n    // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n    init(arg?:HTMLElement) {\n      const target   = arg instanceof HTMLElement ? arg : document,\n            elements = target.querySelectorAll(\"[data-pagy]\");\n      for (const element of <NodeListOf<HTMLElement>>elements) {\n        try {\n          const [helperId, ...args] = <InitArgs>JSON.parse(B64Decode(<string>element.getAttribute(\"data-pagy\")));\n          if (helperId == \"k\") {\n            // @ts-expect-error spread 2 arguments, not 3 as it complains about\n            void augmentKeynav(element, ...<KeynavArgs><unknown>args);\n          } else if (helperId == \"snj\") {\n            buildNavJs(<NavJsElement>element, <SeriesNavJsArgs><unknown>args);\n          } else if (helperId == \"inj\") {\n            void initInputNavJs(element, <InputNavJsArgs><unknown>args);\n          } else if (helperId == \"ltj\") {\n            initLimitTagJs(element, <LimitTagJsArgs><unknown>args);\n          }\n          // else { console.warn(\"Pagy.init: %o\\nUnknown helperId '%s'\", element, helperId) }\n        } catch (err) { console.warn(\"Pagy.init: %o\\n%s\", element, err) }\n      }\n    }\n  };\n})();\n"
         
     | 
| 
      
 5 
     | 
    
         
            +
                "interface SyncData {\n  from?: number\n  to?:   number\n  key:   string\n  str?:  string\n}\ntype InitArgs = [\"k\",  KeynavArgs] |          // series_nav[_js] with keynav instance\n                [\"snj\", SeriesNavJsArgs] |    // series_nav_js\n                [\"inj\", InputNavJsArgs] |     // input_nav_js\n                [\"ltj\", LimitTagJsArgs]       // limit_tag_js\ntype AugmentKeynav = (nav:HTMLElement, keynavArgs:KeynavArgs) => Promise<((page: string) => string)>\ntype KeynavArgs = readonly [storageKey:  string | null,\n                            pageKey:     string,\n                            last:        number,\n                            spliceArgs?: SpliceArgs]\ntype SpliceArgs = readonly [start:       number,\n                            deleteCount: number,     // it would be optional, but ts complains\n                            ...items:    Cutoff[]]\ntype Cutoff = readonly (string | number | boolean)[]\ntype AugmentedPage = [browserId:   string,\n                      storageKey:  string,\n                      pageNumber:  number,\n                      pages:       number,\n                      priorCutoff: Cutoff | null,\n                      pageCutoff:  Cutoff | null]\ntype SeriesNavJsArgs = readonly [NavJsTokens, NavJsSeries, KeynavArgs?]\ntype NavJsSeries = readonly [widths: number[],\n                             series: (string | number)[][],\n                             labels: string[][] | null]\ntype InputNavJsArgs = readonly [urlToken: string, KeynavArgs?]\ntype LimitTagJsArgs = readonly [from:     number,\n                                urlToken: string]\ntype NavJsTokens = readonly [before:  string,\n                             anchor:  string,\n                             current: string,\n                             gap:     string,\n                             after:   string]\ninterface NavJsElement extends HTMLElement {\n  render(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst Pagy = (() => {\n  const storageSupport = 'sessionStorage' in window && 'BroadcastChannel' in window,\n        pageRe         = \"P \";  // shorten the compiled size\n  // eslint-disable-next-line prefer-const\n  let pagy = \"pagy\", storage: Storage, sync: BroadcastChannel, tabId: number;\n  if (storageSupport) {\n    storage = sessionStorage; // shorten the compiled size\n    sync    = new BroadcastChannel(pagy);\n    tabId   = Date.now();\n    // Sync the sessionStorage keys for the cutoffs opened in a new tab/window\n    sync.addEventListener(\"message\", (e:MessageEvent<SyncData>) => {\n      if (e.data.from) { // request cutoffs\n        const cutoffs = storage.getItem(e.data.key);\n        if (cutoffs) {\n          sync.postMessage(<SyncData>{to: e.data.from, key: e.data.key, str: cutoffs});\n        } // send response\n      } else if (e.data.to) {  // receive cutoffs\n        if (e.data.to == tabId) {\n          storage.setItem(e.data.key, <string>e.data.str);\n        }\n      }\n    });\n  }\n  // The observer instance for responsive navs\n  const rjsObserver = new ResizeObserver(\n      entries => entries.forEach(e => {\n        e.target.querySelectorAll<NavJsElement>(\".pagy-rjs\").forEach(el => el.render());\n      }));\n\n  /* Full set of B64 functions\n  const B64Encode     = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode))),\n        B64Safe       = (unsafe:string)  => unsafe.replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n        B64SafeEncode = (unicode:string) => B64Safe(B64Encode(unicode)),\n        B64Decode     = (base64:string)  => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0))),\n        B64Unsafe     = (safe:string)    => safe.replace(/[-_]/g, (match) => match == \"-\" ? \"+\" : \"/\"),\n        B64SafeDecode = (base64:string)  => B64Decode(B64Unsafe(base64))\n  */\n  const B64SafeEncode = (unicode:string) => btoa(String.fromCharCode(...(new TextEncoder).encode(unicode)))\n                                            .replace(/[+/=]/g, (m) => m == \"+\" ? \"-\" : m == \"/\" ? \"_\" : \"\"),\n        B64Decode     = (base64:string)  => (new TextDecoder()).decode(Uint8Array.from(atob(base64), c => c.charCodeAt(0)));\n\n  // Return a random key: 3 chars max, base-36 number < 36**3\n  const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);\n\n  // Manage the page augmentation for Keynav, called only if storageSupport\n  const augmentKeynav: AugmentKeynav = async (nav, [storageKey, pageKey, last, spliceArgs]) => {\n    let augment;\n    const browserKey = document.cookie.split(/;\\s+/)  // it works even if malformed\n                               .find((row) => row.startsWith(pagy + \"=\"))\n                               ?.split(\"=\")[1] ?? randKey();\n    document.cookie = pagy + \"=\" + browserKey;  // Smaller .min size: set the cookie without checking\n    if (storageKey && !(storageKey in storage)) {\n      // Sync the sessiongStorage from other tabs/windows (e.g., open page in the new tab/window)\n      sync.postMessage(<SyncData>{ from: tabId, key: storageKey });\n      // Wait for the listener to copy the cutoffs in the current sessionStorage\n      await new Promise<string|null>((resolve) => setTimeout(() => resolve(\"\"), 100));\n      if (!(storageKey in storage)) { // the storageKey didn't get copied: fallback to countless pagination\n        augment = (page: string) => page + '+' + last;\n      }\n    }\n    if (!augment) { // regular keynav pagination\n      if (!storageKey) { do { storageKey = randKey() } while (storageKey in storage) } // no dup keys\n      const data = storage.getItem(storageKey),\n          cutoffs = <Cutoff[]>(data ? JSON.parse(data) : [undefined]);\n      if (spliceArgs) {\n        cutoffs.splice(...spliceArgs);\n        storage.setItem(storageKey, JSON.stringify(cutoffs));\n      }\n      // Augment function\n      augment = (page:string) => {\n        const pageNum = parseInt(page);\n        return B64SafeEncode(JSON.stringify(\n            <AugmentedPage>[browserKey,\n                            storageKey,\n                            pageNum,\n                            cutoffs.length,       // pages/last\n                            cutoffs[pageNum - 1], // priorCutoff\n                            cutoffs[pageNum]]));  // pageCutoff\n      };\n    }\n    // Augment the page param of each href\n    for (const a of <NodeListOf<HTMLAnchorElement>><unknown>nav.querySelectorAll('a[href]')) {\n      const url = a.href,\n            re  = new RegExp(`(?<=\\\\?.*)\\\\b${pageKey}=(\\\\d+)`);         // find the numeric page from pageKey\n      a.href    = url.replace(re, pageKey + \"=\" + augment(url.match(re)![1]));  // eslint-disable-line @typescript-eslint/no-non-null-assertion\n    }\n    // Return the augment function for further augmentation (i.e., url token in input_nav_js)\n    return augment;\n  };\n\n  // Build the series_nav_js helper\n  const buildNavJs = (nav:NavJsElement, [[before, anchor, current, gap, after],\n                                        [widths, series, labels], keynavArgs]:SeriesNavJsArgs) => {\n    const  parent = <HTMLElement>nav.parentElement;\n    let lastWidth = -1;\n    (nav.render = () => {\n      const index = widths.findIndex(w => w < parent.clientWidth);\n      if (widths[index] === lastWidth) { return } // no change: abort\n\n      let html = before;\n      series[index].forEach((item, i) => {\n        // Avoid the if blocks and chain the results (shorter pagy.min.js and easier reading)\n        html += item == \"gap\" ? gap :\n                // @ts-expect-error the item may be a number, but the 'replace' converts it to string (shorter pagy.min.js)\n                (typeof item == \"number\" ? anchor.replace(pageRe, item) : current)\n                    .replace(\"L<\", labels?.[index][i] ?? item + \"<\");\n      });\n      html         += after;\n      nav.innerHTML = \"\";\n      nav.insertAdjacentHTML(\"afterbegin\", html);\n      lastWidth = widths[index];\n      if (keynavArgs && storageSupport) { void augmentKeynav(nav, keynavArgs) }\n    })();\n    if (nav.classList.contains(pagy + \"-rjs\")) { rjsObserver.observe(parent) }\n  };\n\n  // Init the input_nav_js helpers\n  const initInputNavJs = async (nav:HTMLElement, [url_token, keynavArgs]:InputNavJsArgs) => {\n    const augment = keynavArgs && storageSupport\n                    ? await augmentKeynav(nav, keynavArgs)\n                    : (page: string) => page;\n    initInput(nav, inputValue => url_token.replace(pageRe, augment(inputValue)));\n  };\n\n  // Init the limit_tag_js helper\n  const initLimitTagJs = (span:HTMLSpanElement, [from, url_token]:LimitTagJsArgs) => {\n    initInput(span, inputValue => {\n      // @ts-expect-error the page is a number, but the 'replace' converts it to string (shorter pagy.min.js)\n      return url_token.replace(pageRe, Math.max(Math.ceil(from / parseInt(inputValue)), 1))\n                      .replace('L ', inputValue);\n    });\n  };\n\n  // Init the input element\n  const initInput = (element:HTMLElement, getUrl:(v:string) => string) => {\n    const input   = <HTMLInputElement>element.querySelector(\"input\"),\n          link    = <HTMLAnchorElement>element.querySelector(\"a\"),\n          initial = input.value,\n          action  = () => {\n                      if (input.value === initial) { return }  // not changed\n                      const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);\n                      if (val < min || val > max) {  // reset invalid/out-of-range\n                        input.value = initial;\n                        input.select();\n                        return;\n                      }\n                      link.href = getUrl(input.value);\n                      link.click();\n                    };\n    input.addEventListener(\"focus\", () => input.select());\n    input.addEventListener(\"focusout\", action);\n    input.addEventListener(\"keypress\", e => { if (e.key == \"Enter\") { action() } });\n  };\n\n  // Public interface\n  return {\n    version: \"43.0.0\",\n\n    // Scan for elements with a \"data-pagy\" attribute and call their init functions with the decoded args\n    init(arg?:HTMLElement) {\n      const target   = arg instanceof HTMLElement ? arg : document,\n            elements = target.querySelectorAll(\"[data-pagy]\");\n      for (const element of <NodeListOf<HTMLElement>>elements) {\n        try {\n          const [helperId, ...args] = <InitArgs>JSON.parse(B64Decode(<string>element.getAttribute(\"data-pagy\")));\n          if (helperId == \"k\") {\n            // @ts-expect-error spread 2 arguments, not 3 as it complains about\n            void augmentKeynav(element, ...<KeynavArgs><unknown>args);\n          } else if (helperId == \"snj\") {\n            buildNavJs(<NavJsElement>element, <SeriesNavJsArgs><unknown>args);\n          } else if (helperId == \"inj\") {\n            void initInputNavJs(element, <InputNavJsArgs><unknown>args);\n          } else if (helperId == \"ltj\") {\n            initLimitTagJs(element, <LimitTagJsArgs><unknown>args);\n          }\n          // else { console.warn(\"Pagy.init: %o\\nUnknown helperId '%s'\", element, helperId) }\n        } catch (err) { console.warn(\"Pagy.init: %o\\n%s\", element, err) }\n      }\n    }\n  };\n})();\n"
         
     | 
| 
       6 
6 
     | 
    
         
             
              ],
         
     | 
| 
       7 
7 
     | 
    
         
             
              "mappings": "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",
         
     | 
| 
       8 
     | 
    
         
            -
              "debugId": " 
     | 
| 
      
 8 
     | 
    
         
            +
              "debugId": "46963D274F782A9664756E2164756E21",
         
     | 
| 
       9 
9 
     | 
    
         
             
              "names": []
         
     | 
| 
       10 
10 
     | 
    
         
             
            }
         
     | 
    
        data/javascripts/pagy.min.js
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            window.Pagy=(()=>{const L="sessionStorage"in window&&"BroadcastChannel"in window;let j="pagy",Y,D,O;if(L)Y=sessionStorage,D=new BroadcastChannel(j),O=Date.now(),D.addEventListener("message",(q)=>{if(q.data.from){const z=Y.getItem(q.data.key);if(z)D.postMessage({to:q.data.from,key:q.data.key,str:z})}else if(q.data.to){if(q.data.to==O)Y.setItem(q.data.key,q.data.str)}});const U=new ResizeObserver((q)=>q.forEach((z)=>{z.target.querySelectorAll(".pagy-rjs").forEach((C)=>C.render())})),S=(q)=>btoa(String.fromCharCode(...new TextEncoder().encode(q))).replace(/[+/=]/g,(z)=>z=="+"?"-":z=="/"?"_":""),_=(q)=>new TextDecoder().decode(Uint8Array.from(atob(q),(z)=>z.charCodeAt(0))),B=()=>Math.floor(Math.random()*46656).toString(36),P=async(q,[z,C,F,G])=>{let M;const R=document.cookie.split(/;\s+/).find((H)=>H.startsWith(j+"="))?.split("=")[1]??B();if(document.cookie=j+"="+R,z&&!(z in Y)){if(D.postMessage({from:O,key:z}),await new Promise((H)=>setTimeout(()=>H(""),100)),!(z in Y))M=(H)=>H+"+"+F}if(!M){if(!z)do z=B();while(z in Y);const H=Y.getItem(z),Q=H?JSON.parse(H):[void 0];if(G)Q.splice(...G),Y.setItem(z,JSON.stringify(Q));M=(X)=>{const Z=parseInt(X);return S(JSON.stringify([R,z,Z,Q.length,Q[Z-1],Q[Z]]))}}for(let H of q.querySelectorAll("a[href]")){const Q=H.href,X=new RegExp(`(?<=\\?.*)\\b${C}=(\\d+)`);H.href=Q.replace(X,C+"="+M(Q.match(X)[1]))}return M},x=(q,[[z,C,F,G,M],[R,H,Q],X])=>{const Z=q.parentElement;let J=-1;if((q.render=()=>{const E=R.findIndex(($)=>$<Z.clientWidth);if(R[E]===J)return;let T=z;if(H[E].forEach(($,A)=>{T+=$=="gap"?G:(typeof $=="number"?C.replace("P ",$):F).replace("L<",Q?.[E][A]??$+"<")}),T+=M,q.innerHTML="",q.insertAdjacentHTML("afterbegin",T),J=R[E],X&&L)P(q,X)})(),q.classList.contains(j+"-rjs"))U.observe(Z)},N=async(q,[z,C])=>{const F=C&&L?await P(q,C):(G)=>G;W(q,(G)=>z.replace("P ",F(G)))},V=(q,[z,C])=>{W(q,(F)=>{return C.replace("P ",Math.max(Math.ceil(z/parseInt(F)),1)).replace("L ",F)})},W=(q,z)=>{const C=q.querySelector("input"),F=q.querySelector("a"),G=C.value,M=()=>{if(C.value===G)return;const[R,H,Q]=[C.min,C.value,C.max].map((X)=>parseInt(X)||0);if(H<R||H>Q){C.value=G,C.select();return}F.href=z(C.value),F.click()};C.addEventListener("focus",()=>C.select()),C.addEventListener("focusout",M),C.addEventListener("keypress",(R)=>{if(R.key=="Enter")M()})};return{version:"43.0.0 
     | 
| 
      
 1 
     | 
    
         
            +
            window.Pagy=(()=>{const L="sessionStorage"in window&&"BroadcastChannel"in window;let j="pagy",Y,D,O;if(L)Y=sessionStorage,D=new BroadcastChannel(j),O=Date.now(),D.addEventListener("message",(q)=>{if(q.data.from){const z=Y.getItem(q.data.key);if(z)D.postMessage({to:q.data.from,key:q.data.key,str:z})}else if(q.data.to){if(q.data.to==O)Y.setItem(q.data.key,q.data.str)}});const U=new ResizeObserver((q)=>q.forEach((z)=>{z.target.querySelectorAll(".pagy-rjs").forEach((C)=>C.render())})),S=(q)=>btoa(String.fromCharCode(...new TextEncoder().encode(q))).replace(/[+/=]/g,(z)=>z=="+"?"-":z=="/"?"_":""),_=(q)=>new TextDecoder().decode(Uint8Array.from(atob(q),(z)=>z.charCodeAt(0))),B=()=>Math.floor(Math.random()*46656).toString(36),P=async(q,[z,C,F,G])=>{let M;const R=document.cookie.split(/;\s+/).find((H)=>H.startsWith(j+"="))?.split("=")[1]??B();if(document.cookie=j+"="+R,z&&!(z in Y)){if(D.postMessage({from:O,key:z}),await new Promise((H)=>setTimeout(()=>H(""),100)),!(z in Y))M=(H)=>H+"+"+F}if(!M){if(!z)do z=B();while(z in Y);const H=Y.getItem(z),Q=H?JSON.parse(H):[void 0];if(G)Q.splice(...G),Y.setItem(z,JSON.stringify(Q));M=(X)=>{const Z=parseInt(X);return S(JSON.stringify([R,z,Z,Q.length,Q[Z-1],Q[Z]]))}}for(let H of q.querySelectorAll("a[href]")){const Q=H.href,X=new RegExp(`(?<=\\?.*)\\b${C}=(\\d+)`);H.href=Q.replace(X,C+"="+M(Q.match(X)[1]))}return M},x=(q,[[z,C,F,G,M],[R,H,Q],X])=>{const Z=q.parentElement;let J=-1;if((q.render=()=>{const E=R.findIndex(($)=>$<Z.clientWidth);if(R[E]===J)return;let T=z;if(H[E].forEach(($,A)=>{T+=$=="gap"?G:(typeof $=="number"?C.replace("P ",$):F).replace("L<",Q?.[E][A]??$+"<")}),T+=M,q.innerHTML="",q.insertAdjacentHTML("afterbegin",T),J=R[E],X&&L)P(q,X)})(),q.classList.contains(j+"-rjs"))U.observe(Z)},N=async(q,[z,C])=>{const F=C&&L?await P(q,C):(G)=>G;W(q,(G)=>z.replace("P ",F(G)))},V=(q,[z,C])=>{W(q,(F)=>{return C.replace("P ",Math.max(Math.ceil(z/parseInt(F)),1)).replace("L ",F)})},W=(q,z)=>{const C=q.querySelector("input"),F=q.querySelector("a"),G=C.value,M=()=>{if(C.value===G)return;const[R,H,Q]=[C.min,C.value,C.max].map((X)=>parseInt(X)||0);if(H<R||H>Q){C.value=G,C.select();return}F.href=z(C.value),F.click()};C.addEventListener("focus",()=>C.select()),C.addEventListener("focusout",M),C.addEventListener("keypress",(R)=>{if(R.key=="Enter")M()})};return{version:"43.0.0",init(q){const z=q instanceof HTMLElement?q:document,C=z.querySelectorAll("[data-pagy]");for(let F of C)try{const[G,...M]=JSON.parse(_(F.getAttribute("data-pagy")));if(G=="k")P(F,...M);else if(G=="snj")x(F,M);else if(G=="inj")N(F,M);else if(G=="ltj")V(F,M)}catch(G){console.warn("Pagy.init: %o\n%s",F,G)}}}})();
         
     | 
    
        data/javascripts/pagy.mjs
    CHANGED
    
    | 
         @@ -123,7 +123,7 @@ const Pagy = (() => { 
     | 
|
| 
       123 
123 
     | 
    
         
             
                });
         
     | 
| 
       124 
124 
     | 
    
         
             
              };
         
     | 
| 
       125 
125 
     | 
    
         
             
              return {
         
     | 
| 
       126 
     | 
    
         
            -
                version: "43.0.0 
     | 
| 
      
 126 
     | 
    
         
            +
                version: "43.0.0",
         
     | 
| 
       127 
127 
     | 
    
         
             
                init(arg) {
         
     | 
| 
       128 
128 
     | 
    
         
             
                  const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
         
     | 
| 
       129 
129 
     | 
    
         
             
                  for (const element of elements) {
         
     | 
| 
         @@ -1,10 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class Pagy
         
     | 
| 
      
 4 
     | 
    
         
            +
              DEFAULT_DATA_KEYS = %i[url_template first_url previous_url page_url next_url last_url
         
     | 
| 
      
 5 
     | 
    
         
            +
                                     count page limit last in from to previous next options].freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       4 
7 
     | 
    
         
             
              # Generate a hash of the wanted internal data
         
     | 
| 
       5 
     | 
    
         
            -
              def data_hash(data_keys: @options[:data_keys] ||
         
     | 
| 
       6 
     | 
    
         
            -
                %i[url_template first_url previous_url page_url next_url last_url
         
     | 
| 
       7 
     | 
    
         
            -
                   count page limit last in from to previous next options], **)
         
     | 
| 
      
 8 
     | 
    
         
            +
              def data_hash(data_keys: @options[:data_keys] || DEFAULT_DATA_KEYS, **)
         
     | 
| 
       8 
9 
     | 
    
         
             
                data_keys   -= %i[count limit] if calendar?
         
     | 
| 
       9 
10 
     | 
    
         
             
                url_template = compose_page_url(PAGE_TOKEN, **)
         
     | 
| 
       10 
11 
     | 
    
         
             
                {}.tap do |data|
         
     | 
| 
         @@ -4,17 +4,21 @@ require_relative 'urls_hash' 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            # Add pagination response headers
         
     | 
| 
       6 
6 
     | 
    
         
             
            class Pagy
         
     | 
| 
      
 7 
     | 
    
         
            +
              DEFAULT_HEADERS_MAP = { page: 'current-page',
         
     | 
| 
      
 8 
     | 
    
         
            +
                                      limit: 'page-limit',
         
     | 
| 
      
 9 
     | 
    
         
            +
                                      count: 'total-count',
         
     | 
| 
      
 10 
     | 
    
         
            +
                                      pages: 'total-pages' }.freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       7 
12 
     | 
    
         
             
              # Generate a hash of RFC-8288-compliant http headers
         
     | 
| 
       8 
     | 
    
         
            -
              def headers_hash(headers_map: @options[:headers_map] ||
         
     | 
| 
       9 
     | 
    
         
            -
                { page: 'current-page', limit: 'page-limit', count: 'total-count', pages: 'total-pages' }, **)
         
     | 
| 
      
 13 
     | 
    
         
            +
              def headers_hash(headers_map: @options[:headers_map] || DEFAULT_HEADERS_MAP, **)
         
     | 
| 
       10 
14 
     | 
    
         
             
                links = urls_hash(**, absolute: true).map { |key, url| %(<#{url}>; rel="#{key}") }.join(', ')
         
     | 
| 
       11 
15 
     | 
    
         
             
                { 'link' => links }.tap do |hash|
         
     | 
| 
       12 
16 
     | 
    
         
             
                  hash[headers_map[:page]]  = @page.to_s if @page && headers_map[:page]
         
     | 
| 
       13 
17 
     | 
    
         
             
                  hash[headers_map[:limit]] = @limit.to_s if headers_map[:limit] && !calendar?
         
     | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                   
     | 
| 
      
 18 
     | 
    
         
            +
                  if @count
         
     | 
| 
      
 19 
     | 
    
         
            +
                    hash[headers_map[:pages]] = @last.to_s if headers_map[:pages]
         
     | 
| 
      
 20 
     | 
    
         
            +
                    hash[headers_map[:count]] = @count.to_s if headers_map[:count]
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
       18 
22 
     | 
    
         
             
                end
         
     | 
| 
       19 
23 
     | 
    
         
             
              end
         
     | 
| 
       20 
24 
     | 
    
         
             
            end
         
     | 
| 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require_relative 'support/wrap_input_nav_js'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            class Pagy
         
     | 
| 
       6 
     | 
    
         
            -
              #  
     | 
| 
      
 6 
     | 
    
         
            +
              # JavaScript input pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
         
     | 
| 
       7 
7 
     | 
    
         
             
              def input_nav_js(style = nil, **)
         
     | 
| 
       8 
8 
     | 
    
         
             
                return send(:"#{style}_input_nav_js", **) if style
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
         @@ -15,5 +15,4 @@ class Pagy 
     | 
|
| 
       15 
15 
     | 
    
         
             
                             next_tag(a_lambda)})
         
     | 
| 
       16 
16 
     | 
    
         
             
                wrap_input_nav_js(html, 'pagy input-nav-js', **)
         
     | 
| 
       17 
17 
     | 
    
         
             
              end
         
     | 
| 
       18 
     | 
    
         
            -
              alias pagy_input_nav_js input_nav_js
         
     | 
| 
       19 
18 
     | 
    
         
             
            end
         
     | 
| 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require_relative 'support/wrap_series_nav'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            class Pagy
         
     | 
| 
       6 
     | 
    
         
            -
              # Return the  
     | 
| 
      
 6 
     | 
    
         
            +
              # Return the HTML with the series of links to the pages
         
     | 
| 
       7 
7 
     | 
    
         
             
              def series_nav(style = nil, **)
         
     | 
| 
       8 
8 
     | 
    
         
             
                return send(:"#{style}_series_nav", **) if style
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
         @@ -25,5 +25,4 @@ class Pagy 
     | 
|
| 
       25 
25 
     | 
    
         
             
                html << next_tag(a_lambda)
         
     | 
| 
       26 
26 
     | 
    
         
             
                wrap_series_nav(html, 'pagy series-nav', **)
         
     | 
| 
       27 
27 
     | 
    
         
             
              end
         
     | 
| 
       28 
     | 
    
         
            -
              alias pagy_series_nav series_nav
         
     | 
| 
       29 
28 
     | 
    
         
             
            end
         
     | 
    
        data/lib/pagy.rb
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ require_relative 'pagy/toolbox/helpers/loader' 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            # Top superclass: it defines only what's common to all the subclasses
         
     | 
| 
       10 
10 
     | 
    
         
             
            class Pagy
         
     | 
| 
       11 
     | 
    
         
            -
              VERSION     = '43.0.0 
     | 
| 
      
 11 
     | 
    
         
            +
              VERSION     = '43.0.0'
         
     | 
| 
       12 
12 
     | 
    
         
             
              ROOT        = Pathname.new(__dir__).parent.freeze
         
     | 
| 
       13 
13 
     | 
    
         
             
              DEFAULT     = { limit: 20, limit_key: 'limit', page_key: 'page' }.freeze
         
     | 
| 
       14 
14 
     | 
    
         
             
              PAGE_TOKEN  = 'P '
         
     |