cdnV2

git clone https://github.com/notamitgamer/cdnV2.git
· rebuilt hourlyOpen on GitHub
root / app / templates / _listing.html

_listing.html (9006B)


      1 {#-
      2   Page fragments shared by the server-rendered pages and the client-side "instant folder" renderer
      3   (static/fasttree.js). Each fragment is written once, here. The server calls these macros with real
      4   values; /api/shell calls them with @@placeholders@@ that the browser fills in from the cached tree.
      5   Change markup here and both stay in step (tests/test_fast_tree.py checks they do).
      6 
      7   Rules for editing: keep every macro's signature; only put data in via the macro arguments; keep the
      8   hooks the scripts use (ids, data-name / data-full-name / data-path, data-action).
      9 -#}
     10 {% from "_icons.html" import icon %}
     11 
     12 {% macro root_header() %}
     13         <section class="hero">
     14             <h1>A small file shelf for <a href="https://amit.is-a.dev">my</a> projects.</h1>
     15             <p class="site-notice" role="note">
     16                 {{ icon('info', 16) }}
     17                 <span>Files here can now be synced straight from GitHub on every push — click
     18                 <a href="/gh-sync">Sync</a> at the top to see how to set it up. Project assets live here;
     19                 files and paths may change over time, so use direct links with that in mind.</span>
     20                 <button type="button" class="notice-close" data-action="dismiss-notice" aria-label="Dismiss this notice" title="Dismiss">{{ icon('close', 14, 2.5) }}</button>
     21             </p>
     22         </section>
     23 {% endmacro %}
     24 
     25 {% macro count(n, word, s) %}<strong>{{ n }}</strong> {{ word }}{{ s }}{% endmacro %}
     26 
     27 {% macro counts(dir_count, file_count) %}
     28                 {% if dir_count > 0 %}
     29                     {{ count(dir_count, 'folder', 's' if dir_count != 1 else '') }}
     30                 {% endif %}
     31                 {% if dir_count > 0 and file_count > 0 %} &amp; {% endif %}
     32                 {% if file_count > 0 %}
     33                     {{ count(file_count, 'file', 's' if file_count != 1 else '') }}
     34                 {% endif %}
     35                 {% if dir_count == 0 and file_count == 0 %}
     36                     0 items
     37                 {% endif %}
     38 {% endmacro %}
     39 
     40 {% macro toolbar(counts_html, path) %}
     41         <div class="listing-toolbar">
     42             <p class="listing-toolbar__counts">
     43                 {{ counts_html }}
     44             </p>
     45             <div class="listing-toolbar__actions">
     46                 <label class="select-wrap" title="Sort this folder">
     47                     {{ icon('sort', 14) }}
     48                     <span class="sr-only">Sort by</span>
     49                     <select id="sort-select" class="select" data-action="sort">
     50                         <option value="default">Default</option>
     51                         <option value="name">Name A–Z</option>
     52                         <option value="name-desc">Name Z–A</option>
     53                         <option value="size-desc">Largest</option>
     54                         <option value="size-asc">Smallest</option>
     55                     </select>
     56                 </label>
     57                 <button id="download-zip-btn" type="button" class="btn" data-path="{{ path }}" title="Download everything in this folder as a .zip" aria-label="Download everything in this folder as a .zip">
     58                     <svg id="zip-spinner" class="spin-anim" style="display: none;" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
     59                     {{ icon('download') }}
     60                     <span id="zip-btn-text"><span class="zip-long">Download all (.zip)</span><span class="zip-short">.zip</span></span>
     61                 </button>
     62             </div>
     63         </div>
     64 {% endmacro %}
     65 
     66 {% macro go_up(parent_path) %}
     67                     <div class="list-item" data-name="..">
     68                         <div class="item-name">
     69                             <svg class="folder-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg>
     70                             <a href="{{ parent_path }}" class="folder-link">Go up a directory</a>
     71                         </div>
     72                     </div>
     73 {% endmacro %}
     74 
     75 {% macro row_dir(name, path) %}
     76                     <div class="list-item" data-name="{{ name }}">
     77                         <div class="item-name">
     78                             <svg class="folder-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
     79                             <a href="/{{ path }}" class="folder-link" data-full-name="{{ name }}/">{{ name }}/</a>
     80                         </div>
     81                         <div class="item-meta">
     82                         </div>
     83                     </div>
     84 {% endmacro %}
     85 
     86 {% macro row_file(name, path, size_str) %}
     87                     <div class="list-item" data-name="{{ name }}">
     88                         <div class="item-name">
     89                             <svg class="file-icon-list" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>
     90                             <a href="/{{ path }}" class="file-link" data-full-name="{{ name }}">{{ name }}</a>
     91                         </div>
     92                         <div class="item-meta">
     93                             <span class="size-label">{{ size_str }}</span>
     94                             <a href="/api/get/{{ path }}" class="download-icon" title="Download" aria-label="Download {{ name }}" data-turbo="false">
     95                                 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
     96                             </a>
     97                         </div>
     98                     </div>
     99 {% endmacro %}
    100 
    101 {% macro empty_state() %}
    102                     <div class="empty-state">
    103                         <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
    104                         <p>This folder is empty.</p>
    105                         <a href="/new" class="btn btn-sm">Upload a file</a>
    106                     </div>
    107 {% endmacro %}
    108 
    109 {% macro footer_stats(n, s, size_str) %}
    110             <div class="footer-stats" title="Across the whole repo">
    111                 <strong>{{ n }}</strong> file{{ s }} · {{ size_str }} total
    112             </div>
    113 {% endmacro %}
    114 
    115 {% macro crumb_container(inner, cdn_base, tail) %}
    116         <div class="breadcrumb-container" data-cdn-base="{{ cdn_base }}">
    117             <nav class="breadcrumb" id="breadcrumb" aria-label="Breadcrumb">
    118 {{ inner }}
    119 {{ tail }}
    120             </nav>
    121         </div>
    122 {% endmacro %}
    123 
    124 {% macro crumb_link(href, name) %}<a href="{{ href }}">{{ name }}</a>{% endmacro %}
    125 
    126 {% macro crumb_collapsed(menu) %}
    127                     <div class="breadcrumb-collapsed">
    128                         <button type="button" class="breadcrumb-ellipsis" data-action="crumb-menu" aria-expanded="false" aria-label="Show hidden path segments">&hellip;</button>
    129                         <div class="breadcrumb-menu">
    130                             {{ menu }}
    131                         </div>
    132                     </div>
    133 {% endmacro %}
    134 
    135 {% macro copy_btn(path) %}
    136                 <button type="button" class="copy-path-btn" title="Copy link to this location" aria-label="Copy link to this location" data-action="copy-path" data-path="{{ path }}">
    137                     <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
    138                 </button>
    139 {% endmacro %}
    140 
    141 {% macro visit_script(fields) %}
    142         (function () {
    143             try {
    144                 var KEY = 'cdn_visited_v1';
    145                 var MAX = 50;
    146                 var entry = {
    147                     {{ fields }}
    148                     ts: Date.now()
    149                 };
    150                 var entries = JSON.parse(localStorage.getItem(KEY) || '[]').filter(function (e) { return e.path !== entry.path; });
    151                 entries.unshift(entry);
    152                 localStorage.setItem(KEY, JSON.stringify(entries.slice(0, MAX)));
    153             } catch (e) {}
    154         })();
    155 {% endmacro %}