feat: sweep complet — tous les émojis → outline SVG icons

Templates modifiés (22 fichiers):
- _icons.html: +14 new icons (paperclip, external-link, sparkles, lightbulb, tag,
  file-text, save, upload, trending-up, zap, alert-triangle, user, eye-off)
- base.html: +8 JS icons, 🦎🐙🔑🔗👁📋🔲📑❓⚠️→SVG
- page_editor.html: 43→0 émojis (📎📄🔒🔗⭐📋📁✨📝🗄📑📊📅🗓🖼📥🌐✏💬💡 etc)
- settings.html: 30→0 (⚙️📋🏷🧩👥💾🙈👁🔒🌙☀️🌳📊📝⚠🦎✅🐙🔗✏🗑)
- local_workspace.html: 25→0 (📄📁✏🗑⚠📋➕)
- gitea_workspace.html: 25→0 (🔗📄📤🔄⚙📁📄🔒✏🗑💾)
- board.html: 13→0 (📁📊📋☰📈👥✕✓🗑⚡🔍)
- workspace.html: 11→0 (🏠🔑⚙📁🔗📂🐙)
- landing.html: 8→0 (📚🚀📝📊🦎🌐🔒⚡)
- trash.html, table_view, dashboard, accounts, card_detail, public_page,
  workspaces, team_load, notes, _header, detailed_board, card, board_fragment
- Ajouté import _icons.html aux fragments standalone
- 143 tests passent
This commit is contained in:
2026-07-21 08:27:10 -04:00
parent b88a972531
commit 3fcc12ad8c
23 changed files with 204 additions and 169 deletions
+34 -34
View File
@@ -1,8 +1,8 @@
{% extends "base.html" %} {% block page_icon %}{% if page.content_format == 'file' %}📎{% else %}📄{% endif %}{% endblock %} {% block
{% extends "base.html" %} {% block page_icon %}{% if page.content_format == 'file' %}{{ fd_icon("paperclip",14) }}{% else %}{{ fd_icon("file",14) }}{% endif %}{% endblock %} {% block
page_title %}{{ page.title }}{% endblock %} {% block topbar %}
{% set page_icon = "📄" if page.content_format != 'file' else "📎" %}
{% set page_icon = "file" if page.content_format != 'file' else "paperclip" %}
{% set page_title = page.title %}
{% set right_actions = '<span class="topbar-edited" style="cursor:pointer;" @click="window.E && window.E.toggleActivityOpen()">Edited <span x-text="window.E && window.E.timeAgo || \'\'"></span> ▾</span><button class="topbar-btn share-btn" @click="window.E && window.E.toggleShareOpen()">🔒 Share ▾</button><button class="topbar-btn" @click="window.E && window.E.copyPageLink()" title="Copy link">🔗</button><button class="topbar-btn star-btn" @click="window.E && window.E.toggleFavorite()" x-text="(window.E && window.E.favorited) ? \'⭐\' : \'☆\'"></button><button class="topbar-btn relative" @click="window.E && window.E.toggleMoreOpen()">⋯</button>' %}
{% set right_actions = '<span class="topbar-edited" style="cursor:pointer;" @click="window.E && window.E.toggleActivityOpen()">Edited <span x-text="window.E && window.E.timeAgo || \'\'"></span> ▾</span><button class="topbar-btn share-btn" @click="window.E && window.E.toggleShareOpen()">{{ fd_icon("lock",14) }} Share ▾</button><button class="topbar-btn" @click="window.E && window.E.copyPageLink()" title="Copy link">{{ fd_icon("link",14) }}</button><button class="topbar-btn star-btn" @click="window.E && window.E.toggleFavorite()" x-text="(window.E && window.E.favorited) ? \'{{ fd_icon("star",14) }}\' : \'{{ fd_icon("star",14) }}\'"></button><button class="topbar-btn relative" @click="window.E && window.E.toggleMoreOpen()">⋯</button>' %}
{% include '_header.html' %}
{% endblock %} {% block content %}
<div class="page-editor-wrapper" x-data="editorState()">
@@ -148,7 +148,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
@click="accessMenuOpen = !accessMenuOpen"
>
<span
x-text="generalAccess === 'invited' ? '🔒 Only people invited' : '🌐 Anyone with the link'"
x-text="generalAccess === 'invited' ? 'Only people invited' : 'Anyone with the link'"
></span>
<span class="chevron-down">▾</span>
</button>
@@ -163,7 +163,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
:class="{ active: generalAccess === 'invited' }"
@click="generalAccess='invited'; accessMenuOpen=false"
>
<span>🔒 Only people invited</span>
<span>{{ fd_icon('lock',14) }} Only people invited</span>
<span class="sd-perm-desc"
>People need to be invited</span
>
@@ -173,7 +173,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
:class="{ active: generalAccess === 'anyone' }"
@click="generalAccess='anyone'; accessMenuOpen=false"
>
<span>🌐 Anyone with the link</span>
<span>{{ fd_icon('globe',14) }} Anyone with the link</span>
<span class="sd-perm-desc"
>Can view the page</span
>
@@ -213,7 +213,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
>? Learn about sharing</a
>
<button class="sd-footer-action" @click="copyPageLink">
🔗 Copy link
{{ fd_icon("link",14) }} Copy link
</button>
</div>
</div>
@@ -229,7 +229,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
<div class="sd-publish-preview">
<div class="sd-preview-bar"></div>
<div class="sd-preview-title">
🌐 {{ page.title }}
{{ fd_icon('globe',14) }} {{ page.title }}
</div>
</div>
<h3 class="sd-publish-heading">Publish to web</h3>
@@ -280,26 +280,26 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
<!-- Settings list -->
<div class="sd-settings">
<div class="sd-setting-row">
<span>🔗 Link expires</span>
<span>{{ fd_icon("link",14) }} Link expires</span>
<span style="color: var(--text-dim)"
>Never ▾</span
>
</div>
<div class="sd-setting-row">
<span>🔍 Search engine indexing</span>
<span>{{ fd_icon('search',14) }} Search engine indexing</span>
<span style="color: var(--text-dim)"
>Off ▾</span
>
</div>
<div class="sd-setting-row">
<span>📄 Allow duplicate as template</span>
<span>{{ fd_icon("file",14) }} Allow duplicate as template</span>
<label class="toggle-switch sm">
<input type="checkbox" checked />
<span class="toggle-slider"></span>
</label>
</div>
<div class="sd-setting-row">
<span>✏️ Allow editing</span>
<span>{{ fd_icon("edit",14) }} Allow editing</span>
<label class="toggle-switch sm">
<input
type="checkbox"
@@ -309,7 +309,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
</label>
</div>
<div class="sd-setting-row">
<span>💬 Allow comments</span>
<span>{{ fd_icon("message-square",14) }} Allow comments</span>
<label class="toggle-switch sm">
<input
type="checkbox"
@@ -354,12 +354,12 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
>
<div class="more-menu-item" @click="exportPage">↗ Export</div>
<div class="more-menu-item" @click="duplicatePage">
📋 Duplicate
{{ fd_icon("copy",14) }} Duplicate
</div>
<div class="more-menu-item" @click="movePage">↗ Move to</div>
<div class="more-menu-sep"></div>
<div class="more-menu-item danger" @click="deletePage">
🗑️ Move to Trash
{{ fd_icon("trash",14) }} Move to Trash
</div>
</div>
@@ -376,7 +376,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
<div class="move-ws-item"
@click="doMove(ws.id)"
style="display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:13px;">
<span>📁</span>
<span>{{ fd_icon("folder",14) }}</span>
<span x-text="ws.name" style="flex:1;"></span>
<span style="font-size:11px;color:var(--text-tertiary);" x-text="ws.page_count + ' pages'"></span>
</div>
@@ -390,7 +390,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
<!-- ═══════════ Page Content ═══════════ -->
<div class="page-cover-area">
<div class="page-title-block">
<span class="page-icon-emoji">{% if page.content_format == 'file' %}📎{% else %}📄{% endif %}</span>
<span class="page-icon-emoji">{% if page.content_format == 'file' %}{{ fd_icon("paperclip",14) }}{% else %}{{ fd_icon("file",14) }}{% endif %}</span>
<div
class="page-title-input"
contenteditable="true"
@@ -426,7 +426,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
<button @click="fmtApply('italic')"><em>I</em></button>
<button @click="fmtApply('underline')"><u>U</u></button>
<button @click="fmtApply('strikeThrough')"><s>S</s></button>
<button @click="fmtLink()">🔗</button>
<button @click="fmtLink()">{{ fd_icon("link",14) }}</button>
</div>
<!-- ═══════════ Copy Link Toast ═══════════ -->
@@ -447,31 +447,31 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
class="gs-pill"
@click="replaceBlock(0, 'paragraph');blocks[0].content='Ask AI to write...';render()"
>
<span class="gs-icon">✨</span> Ask AI
<span class="gs-icon">{{ fd_icon("sparkles",14) }}</span> Ask AI
</button>
<button
class="gs-pill"
@click="replaceBlock(0, 'heading_1');blocks[0].content='AI Meeting Note';render()"
>
<span class="gs-icon">📝</span> AI meeting note
<span class="gs-icon">{{ fd_icon('edit',14) }}</span> AI meeting note
</button>
<button
class="gs-pill"
@click="replaceBlock(0, 'paragraph');blocks[0].content='Database';render()"
>
<span class="gs-icon">🗄️</span> Database
<span class="gs-icon">{{ fd_icon("folder",14) }}</span> Database
</button>
<button
class="gs-pill"
@click="replaceBlock(0, 'paragraph');blocks[0].content='Form';render()"
>
<span class="gs-icon">📋</span> Form
<span class="gs-icon">{{ fd_icon("copy",14) }}</span> Form
</button>
<button
class="gs-pill"
@click="replaceBlock(0, 'paragraph');blocks[0].content='Templates';render()"
>
<span class="gs-icon">📑</span> Templates
<span class="gs-icon">{{ fd_icon("file",14) }}</span> Templates
</button>
<div style="position: relative">
<button class="gs-pill" @click="gsMoreOpen = !gsMoreOpen">
@@ -484,26 +484,26 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
x-transition
>
<div class="gs-more-item" @click="gsMoreOpen=false">
📊 Table
{{ fd_icon("bar-chart",14) }} Table
</div>
<div class="gs-more-item" @click="gsMoreOpen=false">
📋 Board
{{ fd_icon("copy",14) }} Board
</div>
<div class="gs-more-item" @click="gsMoreOpen=false">
📝 List
{{ fd_icon('list',14) }} List
</div>
<div class="gs-more-item" @click="gsMoreOpen=false">
📅 Timeline
{{ fd_icon("calendar",14) }} Timeline
</div>
<div class="gs-more-item" @click="gsMoreOpen=false">
🗓️ Calendar
{{ fd_icon("calendar",14) }} Calendar
</div>
<div class="gs-more-item" @click="gsMoreOpen=false">
🖼️ Gallery
{{ fd_icon("image",14) }} Gallery
</div>
<div class="gs-more-sep"></div>
<div class="gs-more-item" @click="gsMoreOpen=false">
📥 Import
{{ fd_icon("download",14) }} Import
</div>
</div>
</div>
@@ -528,8 +528,8 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
{id:'paragraph',name:'Text',icon:'¶'},{id:'heading_1',name:'Heading 1',icon:'H1'},{id:'heading_2',name:'Heading 2',icon:'H2'},
{id:'heading_3',name:'Heading 3',icon:'H3'},{id:'heading_4',name:'Heading 4',icon:'H4'},{id:'bulleted_list',name:'Bulleted list',icon:'•'},{id:'numbered_list',name:'Numbered list',icon:'1.'},
{id:'to_do',name:'To-do',icon:'☐'},{id:'toggle',name:'Toggle',icon:'▶'},{id:'quote',name:'Quote',icon:'❝'},
{id:'callout',name:'Callout',icon:'💡'},{id:'divider',name:'Divider',icon:'—'},{id:'code',name:'Code block',icon:'<>'},
]},{name:'MEDIA',items:[{id:'image',name:'Image',icon:'🖼'}]}];
{id:'callout',name:'Callout',icon:'lightbulb'},{id:'divider',name:'Divider',icon:'—'},{id:'code',name:'Code block',icon:'<>'},
]},{name:'MEDIA',items:[{id:'image',name:'Image',icon:'image'}]}];
let _bid=0;function genId(){return 'b'+(++_bid)+'_'+Date.now().toString(36);}
function cp(e){const s=window.getSelection();if(!s.rangeCount)return 0;const r=s.getRangeAt(0).cloneRange();r.selectNodeContents(e);r.setEnd(s.getRangeAt(0).endContainer,s.getRangeAt(0).endOffset);return r.toString().length;}
@@ -578,7 +578,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
if(b.embed_type==='pdf')return `<div class="block-wrapper"><div class="block-content block-embed" style="padding:0;"><iframe src="${b.src||''}" style="width:100%;height:80vh;border:none;border-radius:8px;"></iframe></div></div>`;
if(b.embed_type==='download'){
var sz=b.file_size||0;var szStr=sz<1024?sz+' B':sz<1048576?(sz/1024).toFixed(1)+' KB':(sz/1048576).toFixed(1)+' MB';
return `<div class="block-wrapper"><div class="block-content block-embed" style="text-align:center;padding:60px 20px;"><div style="font-size:48px;margin-bottom:12px;">📎</div><div style="font-size:16px;font-weight:500;color:var(--text-primary);margin-bottom:4px;">${esc(b.file_name||'File')}</div><div style="font-size:12px;color:var(--text-tertiary);margin-bottom:16px;">${szStr} · ${esc(b.file_mime||'')}</div><a href="${b.src||''}" download style="display:inline-block;padding:8px 20px;background:var(--accent);color:#fff;text-decoration:none;border-radius:8px;font-size:13px;font-weight:500;">⬇ Download</a></div></div>`;
return `<div class="block-wrapper"><div class="block-content block-embed" style="text-align:center;padding:60px 20px;"><div style="font-size:48px;margin-bottom:12px;">{{ fd_icon("paperclip",14) }}</div><div style="font-size:16px;font-weight:500;color:var(--text-primary);margin-bottom:4px;">${esc(b.file_name||'File')}</div><div style="font-size:12px;color:var(--text-tertiary);margin-bottom:16px;">${szStr} · ${esc(b.file_mime||'')}</div><a href="${b.src||''}" download style="display:inline-block;padding:8px 20px;background:var(--accent);color:#fff;text-decoration:none;border-radius:8px;font-size:13px;font-weight:500;">⬇ Download</a></div></div>`;
}
}
const ph=b.type==='heading_1'?'Heading 1':b.type==='heading_2'?'Heading 2':b.type==='heading_3'?'Heading 3':b.type==='heading_4'?'Heading 4':b.type==='bulleted_list'?'List':b.type==='numbered_list'?'List':b.type==='to_do'?'To-do':b.type==='toggle'?'Toggle list':b.type==='quote'?'Empty quote':b.type==='code'?'Type code...':b.type==='callout'?'Type something...':'Press \'/\' for commands...';
@@ -586,7 +586,7 @@ page_title %}{{ page.title }}{% endblock %} {% block topbar %}
if(b.type==='to_do')inner=`<input type="checkbox" class="todo-checkbox" ${b.checked?'checked':''} onchange="E._doToggle('${b.id}',this.checked)"><div data-bid="${b.id}" contenteditable="true" data-placeholder="${ph}" spellcheck="false">${esc(b.content)}</div>`;
else if(b.type==='toggle')inner=`<button class="toggle-chevron ${b.expanded?'open':''}" onclick="E._doToggleExpand('${b.id}')">▶</button><div data-bid="${b.id}" contenteditable="true" data-placeholder="${ph}" spellcheck="false">${esc(b.content)}</div>`;
else if(b.type==='code')inner=`<div class="code-lang-label">${b.language||'Plain Text'}</div><pre><code data-bid="${b.id}" contenteditable="true" spellcheck="false">${esc(b.content)}</code></pre>`;
else if(b.type==='callout')inner=`<span class="callout-icon">${b.icon||'💡'}</span><div data-bid="${b.id}" contenteditable="true" data-placeholder="${ph}" spellcheck="false">${esc(b.content)}</div>`;
else if(b.type==='callout')inner=`<span class="callout-icon">${b.icon||'lightbulb'}</span><div data-bid="${b.id}" contenteditable="true" data-placeholder="${ph}" spellcheck="false">${esc(b.content)}</div>`;
else inner=`<div data-bid="${b.id}" contenteditable="true" data-placeholder="${ph}" spellcheck="false">${esc(b.content)}</div>`;
const tag=b.type.startsWith('heading_')?'h'+b.type.slice(-1):b.type==='quote'?'blockquote':'div';
const cls=tag==='div'?`block-content ${b.type==='bulleted_list'?'block-bullet':b.type==='numbered_list'?'block-numbered':b.type==='to_do'?'block-todo':b.type==='toggle'?'block-toggle':b.type==='code'?'block-code':b.type==='callout'?'block-callout':''}`:`block-content block-${tag}`;