CI / build (push) Failing after 6m2s
Introduce a Node build system for minified CSS/JS with content hashes, add PWA support, i18n helpers, accessibility improvements, and more translatable strings. Move theme configuration from bookmarks to localStorage, add Playwright tests, and set up CI workflows.
100 lines
5.0 KiB
HTML
100 lines
5.0 KiB
HTML
<footer class="footer-main">
|
|
<p>
|
|
{'Powered by'|t} <a href="https://github.com/shaarli/Shaarli" target="_blank" rel="noopener">Shaarli</a>.
|
|
{if="$is_logged_in"}
|
|
<span class="footer-separator">|</span> <a href="{$base_path}/admin/tools">{'Administration'|t}</a>
|
|
{/if}
|
|
</p>
|
|
<div class="footer-feeds">
|
|
<a href="{$base_path}/feed/rss" title="{'RSS Feed'|t}"><i class="mdi mdi-rss"></i> RSS</a>
|
|
<span class="footer-separator">•</span>
|
|
<a href="{$base_path}/feed/atom" title="{'Atom Feed'|t}">Atom</a>
|
|
<span class="footer-separator">•</span>
|
|
<a href="{$base_path}/daily" title="{'Daily'|t}">Daily</a>
|
|
</div>
|
|
|
|
{loop="$plugins_footer.js"}
|
|
<script src="/{function="ltrim($value, '/')"}"></script>
|
|
{/loop}
|
|
{if="$pageName=='editlink' || $pageName=='addlink' || $pageName=='editlinkbatch'"}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var inputs = document.querySelectorAll('input[data-list]');
|
|
Array.prototype.forEach.call(inputs, function(input) {
|
|
new Awesomplete(input, {
|
|
minChars: 1,
|
|
maxItems: 15,
|
|
filter: function(text, input) {
|
|
return Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]);
|
|
},
|
|
item: function(text, input) {
|
|
return Awesomplete.ITEM(text, input.match(/[^ ]*$/)[0]);
|
|
},
|
|
replace: function(text) {
|
|
var before = this.input.value.match(/.* /);
|
|
this.input.value = (before ? before[0] : "") + text + " ";
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
{/if}
|
|
|
|
<input type="hidden" name="js_base_path" value="{$base_path}" />
|
|
</footer>
|
|
</div>
|
|
<!-- Bulk Actions Bar (for multi-select) -->
|
|
<div class="bulk-actions-bar" id="bulk-actions-bar">
|
|
<div class="bulk-info">
|
|
<span id="bulk-count">0</span> {'links selected'|t} - <a class="bulk-select-all" id="bulk-select-all">{'select all'|t}</a>
|
|
</div>
|
|
<div class="bulk-buttons">
|
|
<button class="bulk-btn bulk-btn-cancel" id="bulk-cancel">{'CANCEL'|t}</button>
|
|
<button class="bulk-btn bulk-btn-delete" id="bulk-delete">{'DELETE'|t}</button>
|
|
<button class="bulk-btn bulk-btn-public" id="bulk-public">{'SET PUBLIC'|t}</button>
|
|
<button class="bulk-btn bulk-btn-private" id="bulk-private">{'SET PRIVATE'|t}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bulk confirmation modal -->
|
|
<div class="modal-overlay" id="bulk-confirm-modal" aria-hidden="true">
|
|
<div class="modal-content bulk-modal" role="dialog" aria-modal="true" aria-labelledby="bulk-modal-title">
|
|
<button class="modal-close" id="bulk-modal-close" type="button" aria-label="{'Close confirmation'|t}">×</button>
|
|
<div class="bulk-modal-header">
|
|
<h3 id="bulk-modal-title"></h3>
|
|
<p id="bulk-modal-subtitle"></p>
|
|
</div>
|
|
<div class="bulk-modal-list" id="bulk-modal-list"></div>
|
|
<div class="bulk-modal-actions">
|
|
<button class="bulk-modal-btn bulk-modal-cancel" id="bulk-modal-cancel" type="button">{'Cancel'|t}</button>
|
|
<button class="bulk-modal-btn bulk-modal-confirm" id="bulk-modal-confirm" type="button"></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Persistent Media Player -->
|
|
<div class="media-player-bar" id="media-player-bar">
|
|
<audio id="media-player-audio" preload="metadata"></audio>
|
|
<div class="media-player-inner">
|
|
<button class="media-player-btn" id="media-player-play" title="{'Play/Pause'|t}">
|
|
<i class="mdi mdi-play" id="media-player-play-icon"></i>
|
|
</button>
|
|
<div class="media-player-info">
|
|
<div class="media-player-title" id="media-player-title">{'No media'|t}</div>
|
|
<div class="media-player-progress-wrap">
|
|
<input type="range" class="media-player-progress" id="media-player-progress" min="0" max="100" value="0" step="0.1">
|
|
</div>
|
|
</div>
|
|
<div class="media-player-time" id="media-player-time">0:00 / 0:00</div>
|
|
<div class="media-player-volume-wrap">
|
|
<button class="media-player-btn media-player-btn-sm" id="media-player-vol-btn" title="{'Mute/Unmute'|t}">
|
|
<i class="mdi mdi-volume-high" id="media-player-vol-icon"></i>
|
|
</button>
|
|
<input type="range" class="media-player-volume" id="media-player-volume" min="0" max="1" value="0.8" step="0.01">
|
|
</div>
|
|
<button class="media-player-btn media-player-btn-sm media-player-close" id="media-player-close" title="{'Close player'|t}">
|
|
<i class="mdi mdi-close"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div><!-- /.main-content --> |