telemark 0.1.0__py3-none-any.whl

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.
telemark/__init__.py ADDED
File without changes
telemark/oil.py ADDED
@@ -0,0 +1 @@
1
+ print("doil")
@@ -0,0 +1,379 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="light">
3
+ <head>
4
+ <meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
5
+ <title>{{ title }} — DocNet</title>
6
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
7
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
8
+ <link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;1,400&family=IBM+Plex+Mono:wght@400;500&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" id="prism-light" />
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" id="prism-dark" disabled />
11
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.6.1/mermaid.min.js"></script>
12
+ <style>
13
+ :root {
14
+ --bg: #faf9f6; --bg2: #f2f0eb; --bg3: #e8e5de;
15
+ --border: #ddd9cf; --text: #1a1814; --text2: #6b6560;
16
+ --text3: #a09890; --accent: #c47c2b; --acc-bg: #fdf3e6;
17
+ --acc-t: #8a5518; --sidebar: 248px; --top: 48px;
18
+ --r: 6px; --prism: light;
19
+ --f-body: 'DM Sans', sans-serif;
20
+ --f-mono: 'IBM Plex Mono', monospace;
21
+ --f-serif: 'Lora', serif;
22
+ }
23
+ [data-theme=dark] {
24
+ --bg: #111318; --bg2: #181b22; --bg3: #1f2330;
25
+ --border: #2c3044; --text: #e4e2dc; --text2: #8a8fa8;
26
+ --text3: #4a4f68; --accent: #e8a040; --acc-bg: rgba(232,160,64,.1); --acc-t: #e8a040;
27
+ }
28
+ [data-theme=ocean] {
29
+ --bg: #0d1b2a; --bg2: #122436; --bg3: #1a3148;
30
+ --border: #1e3d5c; --text: #d6eaf8; --text2: #7fb3d3;
31
+ --text3: #3d6b8a; --accent: #38bdf8; --acc-bg: rgba(56,189,248,.1); --acc-t: #7dd3fc;
32
+ }
33
+ [data-theme=forest] {
34
+ --bg: #f4f6f0; --bg2: #eaede4; --bg3: #dde3d4;
35
+ --border: #cdd6c0; --text: #1a2414; --text2: #4a6741;
36
+ --text3: #8aa882; --accent: #4a7c59; --acc-bg: rgba(74,124,89,.1); --acc-t: #2d5e3e;
37
+ }
38
+ [data-theme=rose] {
39
+ --bg: #fff8f8; --bg2: #fdf0f0; --bg3: #fae3e3;
40
+ --border: #f3d0d0; --text: #1f1214; --text2: #7a4a52;
41
+ --text3: #b8909a; --accent: #c0415a; --acc-bg: rgba(192,65,90,.08); --acc-t: #9b2d45;
42
+ }
43
+ *,*::before,*::after { box-sizing: border-box; margin: 0; padding: 0; }
44
+ html, body { height: 100%; background: var(--bg); color: var(--text); font-family: var(--f-body); font-size: 15px; line-height: 1.65; -webkit-font-smoothing: antialiased; }
45
+ a { color: var(--accent); text-decoration: none; }
46
+ a:hover { color: var(--acc-t); }
47
+ button { cursor: pointer; font-family: var(--f-body); }
48
+
49
+ /* Layout */
50
+ .app { display: flex; flex-direction: column; height: 100vh; }
51
+ .body { display: flex; flex: 1; overflow: hidden; }
52
+
53
+ /* Topbar */
54
+ .top { height: var(--top); background: var(--bg2); border-bottom: 1px solid var(--border); display: flex; align-items: center; padding: 0 1rem; gap: .75rem; flex-shrink: 0; }
55
+ .logo { font-family: var(--f-serif); font-size: 1.15rem; font-style: italic; color: var(--accent); text-decoration: none; }
56
+ .divider { width: 1px; height: 18px; background: var(--border); }
57
+ .search-wrap { flex: 1; max-width: 420px; display: flex; gap: .4rem; }
58
+ .search-wrap input, .search-wrap select { background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); color: var(--text); font-family: var(--f-body); font-size: 13px; padding: 5px 9px; outline: none; }
59
+ .search-wrap input { flex: 1; }
60
+ .search-wrap input:focus { border-color: var(--accent); }
61
+ .search-wrap input::placeholder { color: var(--text3); }
62
+ .search-wrap select { color: var(--text2); }
63
+ .search-wrap button { background: var(--accent); color: #fff; border: none; border-radius: var(--r); font-size: 13px; font-weight: 600; padding: 5px 12px; }
64
+ .spacer { flex: 1; }
65
+ .theme-btn { background: none; border: 1px solid var(--border); border-radius: var(--r); color: var(--text2); font-size: 12px; padding: 4px 9px; }
66
+ .theme-btn:hover { border-color: var(--accent); color: var(--accent); }
67
+ .theme-wrap { position: relative; }
68
+ .theme-picker { display: none; position: absolute; right: 0; top: calc(100% + 6px); background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r); padding: 4px; z-index: 200; min-width: 110px; box-shadow: 0 4px 16px rgba(0,0,0,.12); }
69
+ .theme-picker.open { display: flex; flex-direction: column; }
70
+ .theme-picker button { background: none; border: none; color: var(--text2); font-size: 13px; padding: 6px 10px; border-radius: calc(var(--r) - 2px); text-align: left; transition: .1s; }
71
+ .theme-picker button:hover { background: var(--bg3); color: var(--accent); }
72
+ .theme-picker button.active { color: var(--accent); font-weight: 600; }
73
+
74
+ /* Sidebar */
75
+ .sidebar { width: var(--sidebar); flex-shrink: 0; background: var(--bg2); border-right: 1px solid var(--border); overflow-y: auto; overflow-x: hidden; padding: .5rem 0 1rem; display: flex; flex-direction: column; }
76
+ .sidebar::-webkit-scrollbar { width: 3px; }
77
+ .sidebar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
78
+
79
+ /* Sidebar section label */
80
+ .s-label { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text3); padding: .75rem .75rem .3rem; }
81
+
82
+ /* Recent */
83
+ #recent-list { padding: 0 0 .25rem; }
84
+ .recent-item { display: flex; align-items: center; gap: 5px; padding: 3px .75rem; font-size: 12.5px; color: var(--text2); border-radius: var(--r); margin: 1px 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; transition: .1s; }
85
+ .recent-item:hover { background: var(--bg3); color: var(--text); }
86
+ .recent-sep { height: 1px; background: var(--border); margin: .5rem .75rem; }
87
+
88
+ /* Tree */
89
+ .tree-dir summary { display: flex; align-items: center; gap: 5px; padding: 4px .75rem; font-size: 12.5px; font-weight: 600; color: var(--text2); cursor: pointer; user-select: none; list-style: none; }
90
+ .tree-dir summary::-webkit-details-marker { display: none; }
91
+ .tree-dir summary::before { content: '▸'; font-size: 9px; color: var(--text3); transition: transform .15s; }
92
+ .tree-dir[open] summary::before { transform: rotate(90deg); }
93
+ .tree-dir summary:hover { color: var(--text); }
94
+ .tree-children { padding-left: .5rem; border-left: 1px solid var(--border); margin-left: 1.2rem; }
95
+ .tree-file a { display: flex; align-items: center; justify-content: space-between; gap: 5px; padding: 3px .75rem; font-size: 13px; color: var(--text2); border-radius: var(--r); margin: 1px 4px; transition: .1s; }
96
+ .tree-file a:hover { background: var(--bg3); color: var(--text); }
97
+ .tree-file a.active { background: var(--acc-bg); color: var(--accent); }
98
+ .ext { font-family: var(--f-mono); font-size: 9px; padding: 1px 4px; border-radius: 3px; background: var(--bg3); color: var(--text3); text-transform: uppercase; flex-shrink: 0; border: 1px solid var(--border); }
99
+ .tree-file a.active .ext { background: var(--acc-bg); color: var(--accent); border-color: transparent; }
100
+
101
+ /* Main */
102
+ .main { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
103
+ .main::-webkit-scrollbar { width: 5px; }
104
+ .main::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
105
+ .crumb { padding: 9px 2rem; border-bottom: 1px solid var(--border); background: var(--bg2); font-size: 12px; color: var(--text3); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; flex-shrink: 0; }
106
+ .crumb a { color: var(--text2); }
107
+ .crumb a:hover { color: var(--accent); }
108
+ .crumb .cur { color: var(--text); font-weight: 500; }
109
+ .content { padding: 2.5rem 3rem; max-width: 860px; width: 100%; }
110
+ .page-title { font-family: var(--f-serif); font-size: 1.9rem; font-weight: 400; font-style: italic; color: var(--text); margin-bottom: 1.75rem; letter-spacing: -.02em; line-height: 1.2; }
111
+ .ext-tag { display: inline-block; font-family: var(--f-mono); font-size: 10px; padding: 2px 7px; border-radius: var(--r); background: var(--bg3); color: var(--text3); border: 1px solid var(--border); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 1.25rem; }
112
+
113
+ /* Markdown */
114
+ .md-body h1,.md-body h2,.md-body h3,.md-body h4 { font-family: var(--f-serif); font-weight: 400; color: var(--text); margin: 2rem 0 .6rem; line-height: 1.25; }
115
+ .md-body h1 { font-size: 1.6rem; font-style: italic; }
116
+ .md-body h2 { font-size: 1.25rem; border-bottom: 1px solid var(--border); padding-bottom: .35rem; }
117
+ .md-body h3 { font-size: 1.05rem; color: var(--text2); }
118
+ .md-body p { margin: 0 0 .9rem; }
119
+ .md-body a { border-bottom: 1px solid rgba(196,124,43,.3); }
120
+ .md-body a:hover { border-color: var(--accent); }
121
+ .md-body ul,.md-body ol { margin: 0 0 .9rem 1.5rem; }
122
+ .md-body li { margin-bottom: .2rem; }
123
+ .md-body blockquote { border-left: 3px solid var(--accent); margin: 1.25rem 0; padding: .65rem 1rem; background: var(--acc-bg); border-radius: 0 var(--r) var(--r) 0; color: var(--text2); font-style: italic; }
124
+ .md-body code { font-family: var(--f-mono); font-size: .83em; background: var(--bg3); border: 1px solid var(--border); border-radius: 3px; padding: 1px 4px; color: var(--acc-t); }
125
+ .md-body pre { margin: 1.1rem 0; border-radius: var(--r); overflow: hidden; border: 1px solid var(--border); }
126
+ .md-body pre code { background: transparent; border: none; padding: 0; color: inherit; font-size: 13px; }
127
+ .md-body table { width: 100%; border-collapse: collapse; margin: 1.1rem 0; font-size: 13.5px; }
128
+ .md-body th { background: var(--bg3); color: var(--text2); font-size: 11px; text-transform: uppercase; letter-spacing: .07em; padding: 7px 10px; border: 1px solid var(--border); text-align: left; }
129
+ .md-body td { padding: 7px 10px; border: 1px solid var(--border); }
130
+ .md-body tr:hover td { background: var(--bg2); }
131
+ .md-body img { max-width: 100%; border-radius: var(--r); border: 1px solid var(--border); margin: .75rem 0; }
132
+ .md-body hr { border: none; border-top: 1px solid var(--border); margin: 1.75rem 0; }
133
+ .mermaid { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r); padding: 1.25rem; margin: 1.1rem 0; overflow-x: auto; }
134
+ pre[class*="language-"] { border: 1px solid var(--border) !important; border-radius: var(--r) !important; font-family: var(--f-mono) !important; font-size: 13px !important; line-height: 1.6 !important; }
135
+
136
+ /* CSV */
137
+ .csv-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r); }
138
+ .csv-wrap table { border-collapse: collapse; font-size: 13px; font-family: var(--f-mono); width: 100%; }
139
+ .csv-wrap th { background: var(--bg3); color: var(--accent); font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; padding: 7px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; position: sticky; top: 0; }
140
+ .csv-wrap td { padding: 5px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
141
+ .csv-wrap tr:last-child td { border-bottom: none; }
142
+ .csv-wrap tr:hover td { background: var(--bg2); }
143
+
144
+ /* Misc renderers */
145
+ .img-wrap img { max-width: 100%; max-height: 80vh; border-radius: var(--r); border: 1px solid var(--border); }
146
+ .pdf-frame { width: 100%; height: 82vh; border: 1px solid var(--border); border-radius: var(--r); }
147
+ pre.plain { font-family: var(--f-mono); font-size: 13px; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r); padding: 1.25rem; overflow: auto; white-space: pre-wrap; word-break: break-word; line-height: 1.6; color: var(--text2); }
148
+
149
+ /* Search */
150
+ .s-head { margin-bottom: 2rem; }
151
+ .s-title { font-family: var(--f-serif); font-size: 1.7rem; font-style: italic; font-weight: 400; margin-bottom: .25rem; }
152
+ .s-meta { font-size: 13px; color: var(--text3); }
153
+ .s-meta strong { color: var(--accent); }
154
+ .sec-label { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--text3); margin-bottom: .6rem; display: flex; align-items: center; gap: 8px; }
155
+ .sec-label::after { content: ''; flex: 1; height: 1px; background: var(--border); }
156
+ .s-block { margin-bottom: 2rem; }
157
+ .chips { display: flex; flex-wrap: wrap; gap: .4rem; }
158
+ .chip { display: inline-flex; align-items: center; gap: 5px; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r); padding: 4px 9px; font-size: 13px; color: var(--text2); transition: .12s; }
159
+ .chip:hover { border-color: var(--accent); color: var(--accent); }
160
+ .s-card { background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r); padding: .85rem 1rem; margin-bottom: .5rem; display: block; color: inherit; transition: .12s; }
161
+ .s-card:hover { background: var(--bg3); }
162
+ .s-card-top { display: flex; align-items: center; gap: 7px; margin-bottom: .5rem; }
163
+ .s-card-name { font-weight: 600; font-size: 14px; color: var(--text); }
164
+ .s-card-dir { font-size: 11px; color: var(--text3); font-family: var(--f-mono); }
165
+ .s-card-count { margin-left: auto; font-family: var(--f-mono); font-size: 11px; padding: 2px 7px; border-radius: 999px; background: var(--acc-bg); color: var(--accent); white-space: nowrap; }
166
+ .s-snippet { font-size: 12.5px; font-family: var(--f-mono); color: var(--text2); background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); padding: .5rem .75rem; line-height: 1.55; overflow: hidden; }
167
+ .s-snippet mark { background: rgba(196,124,43,.18); color: var(--acc-t); border-radius: 2px; padding: 0 2px; }
168
+ .empty { text-align: center; padding: 4rem 2rem; color: var(--text3); }
169
+ .empty h2 { font-family: var(--f-serif); font-size: 1.5rem; font-style: italic; font-weight: 400; color: var(--text2); margin-bottom: .4rem; }
170
+ .landing { text-align: center; padding: 5rem 2rem; }
171
+ .landing h1 { font-family: var(--f-serif); font-size: 2.25rem; font-style: italic; font-weight: 400; margin-bottom: .5rem; }
172
+ .landing p { color: var(--text2); max-width: 360px; margin: 0 auto; }
173
+ </style>
174
+ </head>
175
+ <body>
176
+ <div class="app">
177
+
178
+ <header class="top">
179
+ <a href="/" class="logo">DocNet</a>
180
+ <div class="divider"></div>
181
+ <form class="search-wrap" action="/search" method="GET">
182
+ <input type="text" name="query" value="{{ query or '' }}" placeholder="Search…" autocomplete="off" />
183
+ {% if page == 'search' %}
184
+ <select name="type">
185
+ <option value="all" {% if kind=='all' %}selected{% endif %}>All</option>
186
+ <option value="name" {% if kind=='name' %}selected{% endif %}>Names</option>
187
+ <option value="content" {% if kind=='content' %}selected{% endif %}>Content</option>
188
+ </select>
189
+ {% endif %}
190
+ <button type="submit">Go</button>
191
+ </form>
192
+ <div class="spacer"></div>
193
+ <div class="theme-wrap">
194
+ <button class="theme-btn" id="theme-btn" onclick="togglePicker()">◑ Theme</button>
195
+ <div class="theme-picker" id="theme-picker">
196
+ <button onclick="applyTheme('light')">☀ Light</button>
197
+ <button onclick="applyTheme('dark')">☾ Dark</button>
198
+ <button onclick="applyTheme('ocean')">◉ Ocean</button>
199
+ <button onclick="applyTheme('forest')">❧ Forest</button>
200
+ <button onclick="applyTheme('rose')">✿ Rose</button>
201
+ </div>
202
+ </div>
203
+ </header>
204
+
205
+ <div class="body">
206
+
207
+ <nav class="sidebar">
208
+ <!-- Recent pages (populated by JS) -->
209
+ <div id="recent-section" style="display:none">
210
+ <div class="s-label">Recent</div>
211
+ <div id="recent-list"></div>
212
+ <div class="recent-sep"></div>
213
+ </div>
214
+
215
+ <!-- File tree -->
216
+ <div class="s-label">Files</div>
217
+ {% macro render(nodes, depth=0) %}
218
+ {% for n in nodes %}
219
+ {% if n.type == 'dir' %}
220
+ <details class="tree-dir" {% if current_parts[depth] is defined and current_parts[depth] == n.name %}open{% endif %}>
221
+ <summary>{{ n.name }}</summary>
222
+ <div class="tree-children">{{ render(n.children, depth+1) }}</div>
223
+ </details>
224
+ {% else %}
225
+ <div class="tree-file">
226
+ <a href="/pages/{{ n.path }}" class="{{ 'active' if current == n.path else '' }}">
227
+ <span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ n.name }}</span>
228
+ <span class="ext">{{ n.ext }}</span>
229
+ </a>
230
+ </div>
231
+ {% endif %}
232
+ {% endfor %}
233
+ {% endmacro %}
234
+ {{ render(tree) }}
235
+ </nav>
236
+
237
+ <main class="main">
238
+ <div class="crumb">
239
+ <a href="/">Home</a>
240
+ {% for c in crumbs %}
241
+ <span>/</span>
242
+ {% if loop.last %}<span class="cur">{{ c }}</span>
243
+ {% else %}<a href="#">{{ c }}</a>{% endif %}
244
+ {% endfor %}
245
+ </div>
246
+
247
+ <div class="content">
248
+ {% if page == 'view' %}
249
+ {% if ext %}<span class="ext-tag">{{ ext }}</span>{% endif %}
250
+ <h1 class="page-title">{{ title }}</h1>
251
+ {{ content | safe }}
252
+
253
+ {% elif page == 'search' %}
254
+ {% if not query %}
255
+ <div class="landing">
256
+ <h1>Search the wiki</h1>
257
+ <p>Find files by name or search across all content.</p>
258
+ </div>
259
+ {% elif not by_name and not by_content %}
260
+ <div class="empty">
261
+ <h2>Nothing found for "{{ query }}"</h2>
262
+ <p style="font-size:13px">Try different keywords or a broader search type.</p>
263
+ </div>
264
+ {% else %}
265
+ <div class="s-head">
266
+ <h1 class="s-title">Results for "{{ query }}"</h1>
267
+ <p class="s-meta"><strong>{{ (by_name|length) + (by_content|length) }}</strong> result{{ 's' if (by_name|length + by_content|length) != 1 }}</p>
268
+ </div>
269
+ {% if by_name %}
270
+ <div class="s-block">
271
+ <div class="sec-label">Filename matches &nbsp;{{ by_name|length }}</div>
272
+ <div class="chips">
273
+ {% for f in by_name %}
274
+ <a href="/{{ f.path }}" class="chip">{{ f.name }}<span class="ext">{{ f.ext }}</span></a>
275
+ {% endfor %}
276
+ </div>
277
+ </div>
278
+ {% endif %}
279
+ {% if by_content %}
280
+ <div class="s-block">
281
+ <div class="sec-label">Content matches &nbsp;{{ by_content|length }}</div>
282
+ {% for r in by_content %}
283
+ <a href="/{{ r.path }}" class="s-card">
284
+ <div class="s-card-top">
285
+ <span class="ext">{{ r.ext }}</span>
286
+ <span class="s-card-name">{{ r.name }}</span>
287
+ {% if r.dir and r.dir != '.' %}<span class="s-card-dir">{{ r.dir }}</span>{% endif %}
288
+ <span class="s-card-count">{{ r.count }} hit{{ 's' if r.count != 1 }}</span>
289
+ </div>
290
+ {% if r.snippet %}<div class="s-snippet">{{ r.snippet | safe }}</div>{% endif %}
291
+ </a>
292
+ {% endfor %}
293
+ </div>
294
+ {% endif %}
295
+ {% endif %}
296
+ {% endif %}
297
+ </div>
298
+ </main>
299
+ </div>
300
+ </div>
301
+
302
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
303
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
304
+ <script>
305
+ // ── Theme ─────────────────────────────────────────────────────────────────────
306
+ const root = document.documentElement;
307
+ const pLight = document.getElementById('prism-light');
308
+ const pDark = document.getElementById('prism-dark');
309
+ const DARK_THEMES = new Set(['dark', 'ocean']);
310
+
311
+ function applyTheme(t) {
312
+ root.setAttribute('data-theme', t);
313
+ const dark = DARK_THEMES.has(t);
314
+ pLight.disabled = dark;
315
+ pDark.disabled = !dark;
316
+ mermaid.initialize({ startOnLoad: false, theme: dark ? 'dark' : 'default' });
317
+ localStorage.setItem('wiki-theme', t);
318
+ // mark active button
319
+ document.querySelectorAll('.theme-picker button').forEach(b => {
320
+ b.classList.toggle('active', b.textContent.toLowerCase().includes(t));
321
+ });
322
+ closePicker();
323
+ }
324
+
325
+ function togglePicker() {
326
+ document.getElementById('theme-picker').classList.toggle('open');
327
+ }
328
+ function closePicker() {
329
+ document.getElementById('theme-picker').classList.remove('open');
330
+ }
331
+ document.addEventListener('click', e => {
332
+ if (!e.target.closest('.theme-wrap')) closePicker();
333
+ });
334
+
335
+ const saved = localStorage.getItem('wiki-theme');
336
+ if (saved) applyTheme(saved);
337
+
338
+ // ── Recent pages ─────────────────────────────────────────────────────────────
339
+ const RECENT_KEY = 'wiki-recent';
340
+ const RECENT_MAX = 6;
341
+
342
+ function getRecent() {
343
+ try { return JSON.parse(localStorage.getItem(RECENT_KEY) || '[]'); }
344
+ catch { return []; }
345
+ }
346
+
347
+ function pushRecent(path, title) {
348
+ let pages = getRecent().filter(p => p.path !== path);
349
+ pages.unshift({ path, title });
350
+ pages = pages.slice(0, RECENT_MAX);
351
+ localStorage.setItem(RECENT_KEY, JSON.stringify(pages));
352
+ }
353
+
354
+ function renderRecent() {
355
+ const pages = getRecent();
356
+ const section = document.getElementById('recent-section');
357
+ const list = document.getElementById('recent-list');
358
+ if (!pages.length) return;
359
+ list.innerHTML = pages.map(p =>
360
+ `<a class="recent-item" href="/pages/${p.path}">
361
+ <span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1">${p.title}</span>
362
+ </a>`
363
+ ).join('');
364
+ section.style.display = 'block';
365
+ }
366
+
367
+ // Track current page view
368
+ {% if page == 'view' %}
369
+ pushRecent("{{ current }}", "{{ title | replace('"', '\\"') }}");
370
+ {% endif %}
371
+
372
+ renderRecent();
373
+
374
+ // ── Syntax & diagrams ─────────────────────────────────────────────────────────
375
+ mermaid.initialize({ startOnLoad: true, theme: 'default' });
376
+ Prism.highlightAll();
377
+ </script>
378
+ </body>
379
+ </html>
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: telemark
3
+ Version: 0.1.0
4
+ Summary: Instant local file documentation — point it at any folder and browse
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/yourname/telemark
7
+ Project-URL: Issues, https://github.com/yourname/telemark/issues
8
+ Keywords: documentation,markdown,file browser,notes,local
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: flask>=2.3
20
+ Requires-Dist: markdown>=3.4
21
+ Dynamic: license-file
22
+
23
+ # OIL
24
+
25
+
26
+ ## License
27
+
28
+ MIT
@@ -0,0 +1,9 @@
1
+ telemark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ telemark/oil.py,sha256=63iNTAFHcdH4EIkITGuEB0M0LgYSffWzCJk_Wc-znoI,13
3
+ telemark/templates/wiki.html,sha256=yBJQP4ChAFz1rViw-gOY7mZYTj78BXRVgfej5kGKMBw,21395
4
+ telemark-0.1.0.dist-info/licenses/LICENSE,sha256=ESYyLizI0WWtxMeS7rGVcX3ivMezm-HOd5WdeOh-9oU,1056
5
+ telemark-0.1.0.dist-info/METADATA,sha256=SUwr1-qw3uISH2syVlGnTbw5VeyvfBUcUOPQGXJTBy4,861
6
+ telemark-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
+ telemark-0.1.0.dist-info/entry_points.txt,sha256=1h-xZ4_QhuYv9zbFzpeDEgjIOKq2XqNOlZ8Bb0IhwDI,47
8
+ telemark-0.1.0.dist-info/top_level.txt,sha256=jAATI5y0u_YVdR7NCNMDuXahSBmbLONchts4Raioyy0,9
9
+ telemark-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ telemark = telemark.app:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ telemark