mirror of
https://github.com/s427/MARL.git
synced 2025-01-19 05:21:30 +01:00
22 lines
45 KiB
HTML
22 lines
45 KiB
HTML
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><title>MARL - Mastodon Archive Reader Lite</title><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="icon" href="data:,"><base target="_blank"><link rel="stylesheet" href="./_astro/index.uwcihdcd.css"></head> <body> <noscript> <div class="nojs">JavaScript is required for this app to run.</div> </noscript> <div class="main-page" id="app" x-data :class="$store.ui.appClasses" x-init="$watch('$store.files.appReady', value => checkAppReady(value))"> <template x-if="!$store.files.appReady && !$store.files.someFilesLoaded && !$store.files.loading"> <main class="welcome"> <div class="intro"> <h1 x-html="$t('welcome.title', {appName: `MARL <span class='accronym'>(Mastodon Archive Reader Lite)</span>`})"></h1> <p x-html="$t('welcome.p1')"></p> <p x-html="$t('welcome.p2')"></p> <p x-html="$t('welcome.p3', {labelStart: `<label for='file-loader' tabindex='0'>`, labelEnd: `</label>`})"></p> <input id="file-loader" class="file-loader" type="file" accept=".zip" multiple @change="unZip(Object.values($event.target.files))"> </div> <div class="about"> <a href="https://github.com/s427/MARL"> <span x-text="$t('welcome.projectPage')"></span> </a> </div> </main> </template> <template x-if="(!$store.files.appReady && $store.files.someFilesLoaded) || $store.files.loading"> <main class="welcome loading-more"> <div class="intro"> <div class="file-loader loading"> <div>... <span x-text="$t('misc.loading')"></span> ...</div> <div class="filename" x-text="$store.files.loadingName"></div> </div> </div> </main> </template> <template x-if="$store.files.appReady"> <main class="main-section" id="main-section" tabindex="-1" x-on:resize.window="$store.ui.checkMenuState()"> <div class="main-section-inner" id="main-section-inner" :class="$store.files.sources.length > 1 ? 'multiple-actors' : ''"> <div class="mobile-menu" id="mobile-menu"> <nav> <ul> <li> <button class="menu-actor" @click="$store.ui.menuToggle('actor')"> <svg aria-hidden="true"><use href="#menu-actor"></use></svg> <span x-text="$t('menu.profile')"></span> </button> </li> <li> <button class="menu-filters" :class="$store.files.filtersActive ? 'filters-active' : ''" @click="$store.ui.menuToggle('filters')"> <svg aria-hidden="true"><use href="#menu-filters"></use></svg> <span x-text="$t('menu.filters')"></span> <em x-text="$t('menu.filtersActive')" x-show="$store.files.filtersActive" class="visually-hidden"></em> </button> </li> <li> <button class="menu-tags" @click="$store.ui.menuToggle('tags')"> <svg aria-hidden="true"><use href="#menu-tags"></use></svg> <span x-text="$t('menu.tags')"></span> </button> </li> <li> <button class="menu-new" @click="startOver"> <svg aria-hidden="true"><use href="#menu-new"></use></svg> <span x-text="$t('menu.newFile')"></span> </button> </li> </ul> </nav> </div> <div class="panel-backdrop" aria-hidden="true" @click="$store.ui.menuClose()" @keyup.esc="$store.ui.menuClose()"></div> <div class="actor mobile-menu-panel" id="panel-actor" role="region" aria-labelledby="actor-title" tabindex="-1"> <button class="panel-close" @click="$store.ui.menuClose()" x-show="$store.ui.menuIsActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#close"></use> </svg> <span class="visually-hidden" x-text="$t('misc.closePanelBtn')"></span> </button> <h2 class="visually-hidden" id="actor-title" x-text="$t('actor.accountInfo')"></h2> <h3 class="visually-hidden" id="actor-tabs-title" x-text="$t('actor.accounts')"></h3> <div class="actors-wrapper" :style="'--actor-hue: '+ $store.files.sources[$store.ui.actorPanel].hue"> <template x-if="$store.files.sources.length > 1"> <div class="actors-tabs" role="tablist" aria-labelledby="actor-tabs-title"> <template x-for="(_, source) in $store.files.sources"> <button type="button" role="tab" :id="'actortab-' + source" :aria-selected="source === $store.ui.actorPanel ? 'true': 'false'" :aria-controls="'actorpanel-' + source" :style="'--actor-hue: '+ $store.files.sources[source].hue" @click="$store.ui.openActorPanel(source)" @keyup.right="$store.ui.switchActorPanel('up')" @keyup.left="$store.ui.switchActorPanel('down')"> <span x-text="$store.files.sources[source].actor.name"></span> </button> </template> </div> </template> <template x-if="$store.files.sources.length === 1"> <span class="visually-hidden" id="actortab-0" x-text="$store.files.sources[0].actor.name"></span> </template> <template x-for="source in $store.files.sources"> <div class="actor-panel" tabindex="0" role="tabpanel" :id="'actorpanel-' + source.id" :aria-labelledby="'actortab-' + source.id" x-data="{a: source.actor}" x-show="$store.ui.actorPanel === source.id"> <div class="actor-pretty"> <div class="actor-banner"> <template x-if="source.header.noImg"><div class="actor-header no-header"><img alt="$t(actor.noHeaderImage)" src="./_astro/no-header.DKXzxkmt.png"></div></template><template x-if="! source.header.noImg"><button id="actor-header" class="actor-header" @click="$store.lightbox.openProfileImg('header', 'actor-header', source.id)"><img alt="$t(actor.headerImage)" :src="`data:${source.header.type}; base64,${source.header.content}`"></button></template> </div> <div class="actor-id"> <template x-if="source.avatar.noImg"><div class="actor-avatar no-avatar"><img alt="$t(actor.noAvatarImage)" src="./_astro/no-avatar.DeffBVR2.png"></div></template><template x-if="! source.avatar.noImg"><button id="actor-avatar" class="actor-avatar" @click="$store.lightbox.openProfileImg('avatar', 'actor-avatar', source.id)"><img :alt="a.name" :src="`data:${source.avatar.type}; base64,${source.avatar.content}`"></button></template> <h1 class="actor-name" x-text="await a.name"></h1> <div class="actor-url"> <a :href="await a.url" x-text="await a.url"></a> </div> </div> <div class="actor-summary" x-show="a.summary" x-html="await a.summary"></div> <div class="actor-infos"> <dl> <dt x-text="$t('actor.memberSince')"></dt> <dd x-text="await formatDate(a.published)"></dd> </dl> <template x-for="item in await a.attachment"> <dl> <dt x-text="item.name"></dt> <dd x-html="item.value"></dd> </dl> </template> </div> <div class="actor-posts-count"> <div class="total"> <span class="count" x-text="formatNumber(source.outbox.totalItems)"></span> <span class="label" x-text="$t('actor.countPosts')"></span> </div> <div class="archive"> <span class="count" x-text="formatNumber(source.nbToots)"></span> <span class="label" x-text="$t('actor.countInArchive')"></span> </div> <details class="comment" x-show="source.nbToots != source.outbox.totalItems"> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#question"></use> </svg> </span> <span class="summary-label" x-text="$t('actor.countDiffWhy')"></span> </summary> <div class="details-content"> <p x-text="$t('actor.countDiffExplanation')"></p> </div> </details> </div> </div> <div class="actor-raw"> <div class="actor-raw-inner"> <details> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#json"></use> </svg> </span> <span class="summary-label" x-html="$t('actor.rawData', {fileName: `<em>(actor.json)</em>`})" :id="source + 'raw-data-label'"></span> </summary> <div class="details-content"> <textarea x-text="formatJson(await a)" :aria-labelledby="source + 'raw-data-label'" readonly></textarea> </div> </details> </div> </div> <div class="actor-likes-bookmarks"> <div class="actor-likes"> <details> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#favorite"></use> </svg> </span> <h2 class="summary-label"> <span x-text="$t('actor.likes')"></span>
|
|
(<span class="count" x-text="source.likes.length"></span>)
|
|
</h2> </summary> <div class="details-content"> <template x-if="source.likes.length"> <ul> <template x-for="url in source.likes"> <li> <a :href="url" x-html="formatLikesBookmarks(url)"></a> </li> </template> </ul> </template> <template x-if="! source.likes.length"> <p class="no-content">… <span x-text="$t('actor.likesEmpty')"></span> …</p> </template> </div> </details> </div> <div class="actor-bookmarks"> <details> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#favorite"></use> </svg> </span> <h2 class="summary-label"> <span x-text="$t('actor.bookmarks')"></span>
|
|
(<span class="count" x-text="source.bookmarks.length"></span>)
|
|
</h2> </summary> <div class="details-content"> <template x-if="source.bookmarks.length"> <ul> <template x-for="url in source.bookmarks"> <li> <a :href="url" x-html="formatLikesBookmarks(url)"></a> </li> </template> </ul> </template> <template x-if="! source.bookmarks.length"> <p class="no-content">… <span x-text="$t('actor.bookmarksEmpty')"></span> …</p> </template> </div> </details> </div> </div> </div> </template> </div> </div> <div class="toots-filters mobile-menu-panel" id="panel-filters" role="search" aria-labelledby="toots-filter-title" tabindex="-1"> <button class="panel-close" @click="$store.ui.menuClose()" x-show="$store.ui.menuIsActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#close"></use> </svg> <span class="visually-hidden" x-text="$t('misc.closePanelBtn')"></span> </button> <h2 id="toots-filter-title" x-text="$t('filters.panelTitle')"></h2> <p class="visually-hidden" x-text="$t('filters.panelNotice')"></p> <div class="toots-filters-group"> <div class="toots-filter text" :class="isFilterActive('fullText') ? 'active' : ''"> <label for="filter-fullText" x-text="$t('filters.fullText')"></label> <div class="input-wrapper"> <input id="filter-fullText" type="text" x-model.debounce="$store.files.filters.fullText" @keyup.debounce="$store.files.setFilter()" @change.debounce="$store.files.setFilter()"> </div> </div> <div class="toots-filter text" :class="isFilterActive('hashtagText') ? 'active' : ''"> <label for="filter-hashtagText" x-text="$t('filters.hashtagText')"></label> <div class="input-wrapper"> <input id="filter-hashtagText" type="text" x-model.debounce="$store.files.filters.hashtagText" @keyup.debounce="$store.files.setFilter()" @change.debounce="$store.files.setFilter()"> </div> </div> <div class="toots-filter text" :class="isFilterActive('mentionText') ? 'active' : ''"> <label for="filter-mentionText" x-text="$t('filters.mentionText')"></label> <div class="input-wrapper"> <input id="filter-mentionText" type="text" x-model.debounce="$store.files.filters.mentionText" @keyup.debounce="$store.files.setFilter()" @change.debounce="$store.files.setFilter()"> </div> </div> <div class="toots-filter text" :class="isFilterActive('externalLink') ? 'active' : ''"> <label for="filter-externalLink" x-text="$t('filters.externalLink')"></label> <div class="input-wrapper"> <input id="filter-externalLink" type="text" x-model.debounce="$store.files.filters.externalLink" @keyup.debounce="$store.files.setFilter()" @change.debounce="$store.files.setFilter()"> </div> </div> <div class="toots-filter text" :class="isFilterActive('summary') ? 'active' : ''"> <label for="filter-summary" x-text="$t('filters.summary')"></label> <div class="input-wrapper"> <input id="filter-summary" type="text" x-model.debounce="$store.files.filters.summary" @keyup.debounce="$store.files.setFilter()" @change.debounce="$store.files.setFilter()"> </div> </div> </div> <div class="toots-filters-group"> <div class="toots-filter checkbox" :class="isFilterActive('isEdited') ? 'active' : ''"> <label for="filter-isEdited"> <input id="filter-isEdited" type="checkbox" x-model.debounce="$store.files.filters.isEdited" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.isEdited')"></span> </label> </div> <template x-show="$store.files.duplicates"> <div class="toots-filter checkbox" :class="isFilterActive('isDuplicate') ? 'active' : ''"> <label for="filter-isDuplicate"> <input id="filter-isDuplicate" type="checkbox" x-model.debounce="$store.files.filters.isDuplicate" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.isDuplicate')"></span> </label> </div> </template> </div> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.mustContain')"></h3> <div class="toots-filter checkbox" :class="isFilterActive('hasHashtags') ? 'active' : ''"> <label for="filter-hasHashtags"> <input id="filter-hasHashtags" type="checkbox" x-model.debounce="$store.files.filters.hasHashtags" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.hasHashtags')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('hasMentions') ? 'active' : ''"> <label for="filter-hasMentions"> <input id="filter-hasMentions" type="checkbox" x-model.debounce="$store.files.filters.hasMentions" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.hasMentions')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('hasExternalLink') ? 'active' : ''"> <label for="filter-hasExternalLink"> <input id="filter-hasExternalLink" type="checkbox" x-model.debounce="$store.files.filters.hasExternalLink" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.hasExternalLink')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('hasSummary') ? 'active' : ''"> <label for="filter-hasSummary"> <input id="filter-hasSummary" type="checkbox" x-model.debounce="$store.files.filters.hasSummary" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.hasSummary')"></span> </label> </div> </div> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.type')"></h3> <div class="toots-filter checkbox" :class="isFilterActive('typeOriginal') ? 'active' : ''"> <label for="filter-typeOriginal"> <input id="filter-typeOriginal" type="checkbox" x-model.debounce="$store.files.filters.typeOriginal" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.typeOriginal')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('typeBoost') ? 'active' : ''"> <label for="filter-typeBoost"> <input id="filter-typeBoost" type="checkbox" x-model.debounce="$store.files.filters.typeBoost" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.typeBoost')"></span> </label> </div> </div> <div class="toots-filters-group"> <div class="toots-filter checkbox" :class="isFilterActive('noStartingAt') ? 'active' : ''"> <label for="filter-noStartingAt"> <input id="filter-noStartingAt" type="checkbox" x-model.debounce="$store.files.filters.noStartingAt" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.noStartingAt')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('isSensitive') ? 'active' : ''"> <label for="filter-isSensitive"> <input id="filter-isSensitive" type="checkbox" x-model.debounce="$store.files.filters.isSensitive" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.isSensitive')"></span> </label> </div> </div> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.mustHaveAttachement')"></h3> <div class="toots-filter checkbox" :class="isFilterActive('attachmentAny') ? 'active' : ''"> <label for="filter-attachmentAny"> <input id="filter-attachmentAny" type="checkbox" x-model.debounce="$store.files.filters.attachmentAny" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentAny')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('attachmentImage') ? 'active' : ''"> <label for="filter-attachmentImage"> <input id="filter-attachmentImage" type="checkbox" x-model.debounce="$store.files.filters.attachmentImage" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentImage')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('attachmentVideo') ? 'active' : ''"> <label for="filter-attachmentVideo"> <input id="filter-attachmentVideo" type="checkbox" x-model.debounce="$store.files.filters.attachmentVideo" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentVideo')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('attachmentSound') ? 'active' : ''"> <label for="filter-attachmentSound"> <input id="filter-attachmentSound" type="checkbox" x-model.debounce="$store.files.filters.attachmentSound" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentSound')"></span> </label> </div> </div> <div class="toots-filters-group"> <div class="toots-filter checkbox" :class="isFilterActive('attachmentNoAltText') ? 'active' : ''"> <label for="filter-attachmentNoAltText"> <input id="filter-attachmentNoAltText" type="checkbox" x-model.debounce="$store.files.filters.attachmentNoAltText" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentNoAltText')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('attachmentWithAltText') ? 'active' : ''"> <label for="filter-attachmentWithAltText"> <input id="filter-attachmentWithAltText" type="checkbox" x-model.debounce="$store.files.filters.attachmentWithAltText" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.attachmentWithAltText')"></span> </label> </div> </div> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.visibility')"></h3> <div class="toots-filter checkbox" :class="isFilterActive('visibilityPublic') ? 'active' : ''"> <label for="filter-visibilityPublic"> <input id="filter-visibilityPublic" type="checkbox" x-model.debounce="$store.files.filters.visibilityPublic" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.visibilityPublic')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('visibilityUnlisted') ? 'active' : ''"> <label for="filter-visibilityUnlisted"> <input id="filter-visibilityUnlisted" type="checkbox" x-model.debounce="$store.files.filters.visibilityUnlisted" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.visibilityUnlisted')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('visibilityFollowers') ? 'active' : ''"> <label for="filter-visibilityFollowers"> <input id="filter-visibilityFollowers" type="checkbox" x-model.debounce="$store.files.filters.visibilityFollowers" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.visibilityFollowers')"></span> </label> </div> <div class="toots-filter checkbox" :class="isFilterActive('visibilityMentioned') ? 'active' : ''"> <label for="filter-visibilityMentioned"> <input id="filter-visibilityMentioned" type="checkbox" x-model.debounce="$store.files.filters.visibilityMentioned" @change.debounce="$store.files.setFilter()"> <span x-text="$t('filters.visibilityMentioned')"></span> </label> </div> </div> <div class="toots-filters-group" x-show="$store.files.toots.length"> <h3 class="toots-filters-group-title" x-text="$t('filters.language')"></h3> <template x-for="lang in $store.files.sortedLanguages"> <div class="toots-filter checkbox" :class="isFilterActive('lang_' + lang[0]) ? 'active' : ''"> <label :for="'filter-lang-' + lang[0]"> <input :id="'filter-lang-' + lang[0]" type="checkbox" x-model="$store.files.filters['lang_' + lang[0]]" @change="$store.files.setFilter()"> <span> <span x-text="lang[0]"></span>
|
|
(<span x-text="lang[1]"></span>)
|
|
</span> </label> </div> </template> </div> <template x-if="$store.files.sources.length > 1"> <div class="toots-filters-group"> <h3 class="toots-filters-group-title" x-text="$t('filters.author')"></h3> <template x-for="source in $store.files.sources"> <div class="toots-filter checkbox" :class="isFilterActive('actor_' + source.id) ? 'active' : ''"> <label :for="'filter-actor-' + source.id"> <input :id="'filter-actor-' + source.id" type="checkbox" x-model="$store.files.filters['actor_' + source.id]" @change="$store.files.setFilter()"> <span> <span x-text="source.actor.name"></span> </span> </label> </div> </template> </div> </template> <div class="toots-filters-reset"> <button @click="$store.files.resetFilters(true)" :disabled="!$store.files.filtersActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#reset-filters"></use> </svg> <span class="btn-label" x-text="$t('filters.resetFilters')"></span> </button> </div> </div> <header class="toots-header" aria-labelledby="toots-header-title"> <h2 id="toots-header-title"> <span class="count"> <span x-text="await formatNumber($store.files.filteredToots.length)" class="nb"></span> <span x-text="$t('header.countLabel')"></span> </span> <span class="order">
|
|
-
|
|
<span x-text="await $store.files.sortAsc ? $t('header.oldestFirst') : $t('header.latestFirst')"></span> <button @click="$store.files.toggleTootsOrder()" class="toggle-order"> <svg class="btn-icon" aria-hidden="true"> <use href="#toggle-order"></use> </svg> <span class="btn-label" x-text="$t('header.reverse')"></span> </button> </span> <button @click="startOver" class="load-new"> <svg class="btn-icon" aria-hidden="true"> <use href="#load-file"></use></svg><span class="btn-label" x-text="$t('header.loadNewFile')"></span> </button> </h2> <div class="paging"> <div class="direction-back"> <button id="paging-btn-first" @click="$store.files.firstPage()" :disabled="$store.files.currentPage <= 1"> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-first"></use> </svg> <span class="btn-label" x-text="$t('paging.first')"></span> </button> <button id="paging-btn-prev" @click="$store.files.prevPage()" :disabled="$store.files.currentPage <= 1"> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-prev"></use> </svg> <span class="btn-label" x-text="$t('paging.prev')"></span> </button> </div> <div class="paging-options-toggle"> <button @click="$store.ui.togglePagingOptions()"> <svg class="btn-icon" aria-hidden="true"> <use href="#options"></use> </svg> <span class="btn-label" x-text="$t('paging.pagingOptions')"></span> </button> </div> <div class="paging-options" id="paging-options" :class="$store.ui.pagingOptionsClass" tabindex="-1"> <div class="paging-options-inner"> <label for="paging-current-page" x-text="$t('paging.page')"></label> <input class="current-page" id="paging-current-page" type="number" min="1" max="$store.files.totalPages" x-model="$store.files.currentPage" @keyup="$store.files.checkPagingValue()" @change="$store.files.checkPagingValue()" onclick="this.select()">
|
|
/
|
|
<span class="total-pages" x-text="formatNumber($store.files.totalPages)"></span>
|
|
(
|
|
<input class="page-size" id="paging-page-size" type="number" min="1" x-model="$store.files.pageSize" @keyup="$store.files.checkPagingValue()" @change="$store.files.checkPagingValue()" onclick="this.select()"> <label for="paging-page-size" x-text="$t('paging.postsPerPage')"></label>)
|
|
</div> <div class="paging-options-reverse"> <button @click="$store.files.toggleTootsOrder()"> <svg class="btn-icon" aria-hidden="true"> <use href="#toggle-order"></use> </svg> <span class="btn-label" x-text="$t('paging.reverseOrder')"></span> </button> </div> </div> <div class="direction-fwd"> <button id="paging-btn-next" @click="$store.files.nextPage()" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.next')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-next"></use> </svg> </button> <button id="paging-btn-last" @click="$store.files.lastPage()" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.last')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-last"></use> </svg> </button> </div> </div> </header> <div class="toots" id="toots" role="region" aria-labelledby="toots-title" tabindex="-1"> <h2 id="toots-title" class="visually-hidden" x-text="$t('posts.panelTitle')"></h2> <template x-show="$store.files.pagedToots.length" x-for="toot in await $store.files.pagedToots"> <div class="toot" :class="['toot-type-' + contentType(toot.type).toLowerCase(), 'toot-visibility-' + toot._marl.visibility[0]]" :style="'--actor-hue: '+ $store.files.sources[toot._marl.source].hue"> <h3 class="toot-header visually-hidden"> <span x-text="contentType(toot.type)"></span> <span x-text="$t('post.by')"></span> <span x-text="formatAuthor(toot.actor, true)"></span>,
|
|
<span x-text="formatDateTime(toot.published)"></span> </h3> <template x-if="toot.type === 'Create'"> <div class="toot-pretty"> <div class="toot-summary" x-show="toot.object.summary"> <span x-text="toot.object.summary"></span> </div> <div class="toot-content" x-html="toot.object.content"></div> <div class="toot-attachments" x-show="toot.object.attachment && toot.object.attachment.length"> <ul> <template x-for="(att, index) in toot.object.attachment"> <li :class="attachmentWrapperClass(att)" :data-trigger="loadAttachedMedia(att, toot._marl.source)"> <template x-if="attachmentIsImage(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><button class="att-img-wrapper" @click="$store.lightbox.open(toot, index, 'att-' + toot._marl.id + '-' + index)" :id="'att-' + toot._marl.id + '-' + index"><img alt="" :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></button><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></strong> <span x-text="att.url"></span> </span> </div></div></template> <template x-if="attachmentIsSound(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><audio controls :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></audio><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></strong> <span x-text="att.url"></span> </span> </div></div></template> <template x-if="attachmentIsVideo(att) && $store.files.sources[toot._marl.source][att.url]"><div class="att-wrapper"><video controls :width="att.width" :height="att.height" :src="`data:${att.mediaType}; base64,${await $store.files.sources[toot._marl.source][att.url].content}`" :aria-labelledby="'att-' + toot._marl.id + '-' + index + '-desc'"></video><div class="att-description"> <span class="desc-body" x-text="att.name ?? $t('posts.attachmentNoAlt')" :id="'att-' + toot._marl.id + '-' + index + '-desc'" aria-hidden="true"></span> <span class="desc-source"> <strong x-text="$t('post.attachmentInArchive')"></strong> <span x-text="att.url"></span> </span> </div></div></template> </li> </template> </ul> </div> </div> </template> <template x-if="toot.type === 'Announce' && toot.object && toot.object.content"> <div class="toot-pretty"> <div class="toot-content"> <div class="toot-content-inner" x-html="toot.object.content"></div> </div> </div> </template> <template x-if="toot.type === 'Announce' && toot.object && !toot.object.content"> <div class="toot-pretty"> <div class="toot-content"> <div class="toot-content-inner"> <a :href="toot.object" x-text="toot.object"></a> </div> </div> </div> </template> <div class="toot-infos"> <span class="type"> <span x-text="contentType(toot.type)"></span>
|
|
</span> <span class="author"> <span x-text="$t('post.by')"></span> <span x-html="formatAuthor(toot.actor)"></span> </span> <span class="published"><span x-text="formatDateTime(toot.published)"></span> <span x-show="toot.object && toot.object.updated" class="updated"> <span x-text="$t('post.lastUpdated')"></span> <span x-text="formatDateTime(toot.object.updated)"></span> </span> </span> <span class="visibility"> <span x-text="toot._marl.visibility[1]"></span> </span> <span class="link"> <a x-show="toot.object.id" :href="toot.object.id" x-text="$t('post.linkToPost')"></a> </span> </div> <template x-if="(toot.object.tag && toot.object.tag.length) || (toot._marl.externalLinks && toot._marl.externalLinks.length)"> <div class="toot-meta"> <template x-if="toot.object.tag && toot.object.tag.filter(x => x.type === 'Mention').length"> <div class="toot-people"> <h4 x-text="$t('post.people')"></h4> <ul> <template x-for="tag in toot.object.tag"> <li x-show="tag.type === 'Mention'"> <a :href="tag.href" x-text="tag.name"></a> </li> </template> </ul> </div> </template> <template x-if="toot.object.tag && toot.object.tag.filter(x => x.type === 'Hashtag').length"> <div class="toot-hashtags"> <h4 x-text="$t('post.hashtags')"></h4> <ul> <template x-for="tag in toot.object.tag"> <li x-show="tag.type === 'Hashtag'"> <a :href="tag.href" x-text="tag.name"></a> </li> </template> </ul> </div> </template> <template x-if="toot._marl.externalLinks.length"> <div class="toot-links"> <h4 x-text="$t('post.extLinks')"></h4> <ul> <template x-for="link in toot._marl.externalLinks"> <li> <a :href="link.href" x-text="link.text"></a> </li> </template> </ul> </div> </template> </div> </template> <div class="toot-raw"> <details> <summary> <span class="summary-icon"> <svg aria-hidden="true"> <use href="#json"></use> </svg> </span> <span class="summary-label" :id="'raw-' + toot._marl.id" x-text="$t('post.rawData')"></span> </summary> <div class="details-content"> <textarea x-text="formatJson(toot)" :aria-labelledby="'raw-' + toot._marl.id" readonly></textarea> </div> </details> </div> </div> </template> <div class="toots-no-results" x-show="$store.files.pagedToots.length === 0"> <div x-show="$store.files.filtersActive"> <p x-text="$t('posts.noResults')"></p> <p class="action"> <button @click="$store.files.resetFilters(true)" :disabled="!$store.files.filtersActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#reset-filters"></use> </svg> <span class="btn-label" x-text="$t('filters.resetFilters')"></span> </button> </p> </div> <div x-show="!$store.files.filtersActive"> <p x-text="$t('posts.noPostsError')"></p> </div> </div> <div class="paging"> <div class="direction-back"> <button @click="$store.files.firstPage('toots')" :disabled="$store.files.currentPage <= 1"> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-first"></use> </svg> <span class="btn-label" x-text="$t('paging.first')"></span> </button> <button @click="$store.files.prevPage('paging-btn-prev')" :disabled="$store.files.currentPage <= 1"> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-prev"></use> </svg> <span class="btn-label" x-text="$t('paging.prev')"></span> </button> </div> <div class="direction-fwd"> <button @click="$store.files.nextPage('paging-btn-next')" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.next')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-next"></use> </svg> </button> <button @click="$store.files.lastPage('toots')" :disabled="$store.files.currentPage >= $store.files.totalPages"> <span class="btn-label" x-text="$t('paging.last')"></span> <svg class="btn-icon" aria-hidden="true"> <use href="#nav-last"></use> </svg> </button> </div> </div> </div> <aside class="toots-tags mobile-menu-panel" id="panel-tags" aria-labelledby="toots-tags-title" tabindex="-1"> <button class="panel-close" @click="$store.ui.menuClose()" x-show="$store.ui.menuIsActive"> <svg class="btn-icon" aria-hidden="true"> <use href="#close"></use> </svg> <span class="visually-hidden" x-text="$t('misc.closePanelBtn')"></span> </button> <h2 class="tags-title" id="toots-tags-title" x-text="$t('tags.panelTitle')"></h2> <div class="tags-group"> <div class="tags-group-header"> <h3> <span x-text="$t('tags.hashtags')"></span> <span class="count">
|
|
(<span x-text="formatNumber($store.files.listHashtags.length)"></span>)
|
|
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-hashtags-filter" class="visually-hidden" x-text="$t('tags.hashtagsFilter')"></label> <input id="tags-group-hashtags-filter" type="text" onclick="this.select()" x-model.debounce="$store.files.tagsFilters.hashtags"> </div> </div> <div class="tags-group-scroll"> <ul x-show="$store.files.listHashtags.length"> <template x-for="item in await $store.files.listHashtags"> <li :class="item.name === $store.files.filters.hashtagText ? 'active' : ''"> <button :id="'filter-hashtag-' + item.name.toLowerCase().slice(1)" @click="$store.files.filterByTag('hashtagText', item.name, 'filter-hashtag-' + item.name.toLowerCase().slice(1))"> <div> <span class="visually-hidden" x-text="item.name === $store.files.filters.hashtagText ? 'active item:' : ''"></span> <span class="count" x-text="`(${item.nb})`"></span> <span class="name" x-text="item.name"></span> </div> </button> </li> </template> </ul> </div> </div> <div class="tags-group"> <div class="tags-group-header"> <h3> <span x-text="$t('tags.mentions')"></span> <span class="count">
|
|
(<span x-text="formatNumber($store.files.listMentions.length)"></span>)
|
|
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-mentions-filter" class="visually-hidden" x-text="$t('tags.mentionsFilter')"></label> <input id="tags-group-mentions-filter" type="text" onclick="this.select()" x-model.debounce="$store.files.tagsFilters.mentions"> </div> </div> <div class="tags-group-scroll"> <ul x-show="$store.files.listMentions.length"> <template x-for="item in await $store.files.listMentions"> <li :class="item.name === $store.files.filters.mentionText ? 'active' : ''"> <button :id="'filter-mention-' + item.name.toLowerCase().replaceAll('@', '_').replaceAll('.', '_')" @click="$store.files.filterByTag('mentionText', item.name, 'filter-mention-' + item.name.toLowerCase().replaceAll('@', '_').replaceAll('.', '_'))"> <div> <span class="visually-hidden" x-text="item.name === $store.files.filters.mentionText ? 'active item:' : ''"></span> <span class="count" x-text="`(${item.nb})`"></span> <span class="name" x-text="item.name"></span> </div> </button> </li> </template> </ul> </div> </div> <div class="tags-group"> <div class="tags-group-header"> <h3> <span x-text="$t('tags.boosts')"></span> <span class="count">
|
|
(<span x-text="formatNumber($store.files.listBoostsAuthors.length)"></span>)
|
|
</span> </h3> <div class="tags-group-filter"> <label for="tags-group-boostsAuthors-filter" class="visually-hidden" x-text="$t('tags.boostsFilter')"></label> <input id="tags-group-boostsAuthors-filter" type="text" onclick="this.select()" x-model.debounce="$store.files.tagsFilters.boostsAuthors"> </div> </div> <div class="tags-group-scroll"> <ul x-show="$store.files.listBoostsAuthors.length"> <template x-for="item in await $store.files.listBoostsAuthors"> <li :class="item.url === $store.files.filters.fullText ? 'active' : ''"> <button :id="'filter-boost-author-' + item.url.toLowerCase().replaceAll('/', '_')" @click="$store.files.filterByTag('fullText', item.url, 'filter-boost-author-' + item.url.toLowerCase().replaceAll('/', '_'))"> <div> <span class="visually-hidden" x-text="item.url === $store.files.filters.fullText ? 'active item:' : ''"></span> <span class="count" x-text="`(${item.nb})`"></span> <span class="name"> <span x-text="item.name"></span> <span x-text="item.domain" class="domain"></span> </span> </div> </button> </li> </template> </ul> </div> </div> </aside> </div> <template x-if="$store.lightbox.show && $store.lightbox.data.length"><div id="lightbox" class="lightbox overlay" tabindex="-1" @keyup.left="$store.lightbox.showPrev()" @keyup.right="$store.lightbox.showNext()" @keyup.esc="$store.lightbox.close()"><div class="overlay-content"><img :alt="$store.lightbox.data[$store.lightbox.index].name" :src="`data:${$store.lightbox.data[$store.lightbox.index].mediaType}; base64,${$store.files.sources[$store.lightbox.source][$store.lightbox.data[$store.lightbox.index].url].content}`" @click="$store.lightbox.showNext()"></div><div class="overlay-ui"><div class="backdrop" @click="$store.lightbox.close()"></div><button x-show="$store.lightbox.data.length > 1" class="viewer-next" @click="$store.lightbox.showNext()"><svg class="btn-icon" aria-hidden="true"><use href="#viewer-next"></use></svg><span class="visually-hidden" x-text="$t('lightbox.next')"></span></button><button x-show="$store.lightbox.data.length > 1" class="viewer-prev" @click="$store.lightbox.showPrev()"><svg class="btn-icon" aria-hidden="true"><use href="#viewer-prev"></use></svg><span class="visually-hidden" x-text="$t('lightbox.prev')"></span></button><button class="viewer-close" @click="$store.lightbox.close()"><svg class="btn-icon" aria-hidden="true"><use href="#close"></use></svg><span class="visually-hidden" x-text="$t('lightbox.close')"></span></button></div></div></template> </main> </template> </div> <svg style="display: none"> <symbol viewBox="0 -960 960 960" id="reset-filters"> <path d="m653-208-46 46q-17 17-42 17.5T522-162q-17-17-17-42.5t17-42.5l46-46q-4-11-6-23t-2-24q0-58 41-99t99-41q9 0 18 .5t17 3.5q11 4 13.5 16.5T743-439l-43 43q-11 11-11 28t11 28q11 11 28 11t28-11l43-43q8-8 20.5-5.5T836-375q3 8 3.5 17t.5 18q0 58-41 99t-99 41q-13 0-24.5-2t-22.5-6ZM480-760q-117 0-198.5 81.5T200-480q0 72 32.5 132t87.5 98v-70q0-17 11.5-28.5T360-360q17 0 28.5 11.5T400-320v160q0 17-11.5 28.5T360-120H200q-17 0-28.5-11.5T160-160q0-17 11.5-28.5T200-200h54q-62-50-98-122.5T120-480q0-75 28.5-140.5t77-114q48.5-48.5 114-77T480-840q113 0 203.5 63T814-615q6 16 0 31t-22 21q-16 6-31.5 0T739-585q-31-78-100.5-126.5T480-760Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="toggle-order"> <path d="M360-440q-17 0-28.5-11.5T320-480v-247l-75 75q-11 11-27.5 11T189-652q-12-12-12-28.5t12-28.5l143-143q6-6 13-8.5t15-2.5q8 0 15 2.5t13 8.5l144 144q12 12 11.5 28T531-652q-12 11-28 11.5T475-652l-75-75v247q0 17-11.5 28.5T360-440ZM600-97q-8 0-15-2.5t-13-8.5L428-252q-12-12-11.5-28t12.5-28q12-11 28-11.5t28 11.5l75 75v-247q0-17 11.5-28.5T600-520q17 0 28.5 11.5T640-480v247l75-75q11-11 27.5-11t28.5 11q12 12 12 28.5T771-251L628-108q-6 6-13 8.5T600-97Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="load-file"> <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H447l-80-80H160v480l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm-84-262v-218 218Zm84 262 72-240-72 240Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="nav-first"> <path d="m313-480 155 156q11 11 11.5 27.5T468-268q-11 11-28 11t-28-11L228-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T468-692q11 11 11 28t-11 28L313-480Zm264 0 155 156q11 11 11.5 27.5T732-268q-11 11-28 11t-28-11L492-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T732-692q11 11 11 28t-11 28L577-480Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="nav-prev"> <path d="m432-480 156 156q11 11 11 28t-11 28q-11 11-28 11t-28-11L348-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 28-11t28 11q11 11 11 28t-11 28L432-480Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="nav-next"> <path d="M504-480 348-636q-11-11-11-28t11-28q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L404-268q-11 11-28 11t-28-11q-11-11-11-28t11-28l156-156Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="nav-last"> <path d="M383-480 228-636q-11-11-11.5-27.5T228-692q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L284-268q-11 11-27.5 11.5T228-268q-11-11-11-28t11-28l155-156Zm264 0L492-636q-11-11-11.5-27.5T492-692q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L548-268q-11 11-27.5 11.5T492-268q-11-11-11-28t11-28l155-156Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="close"> <path d="M480-424 284-228q-11 11-28 11t-28-11q-11-11-11-28t11-28l196-196-196-196q-11-11-11-28t11-28q11-11 28-11t28 11l196 196 196-196q11-11 28-11t28 11q11 11 11 28t-11 28L536-480l196 196q11 11 11 28t-11 28q-11 11-28 11t-28-11L480-424Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="viewer-next"> <path d="M504-480 348-636q-11-11-11-28t11-28q11-11 28-11t28 11l184 184q6 6 8.5 13t2.5 15q0 8-2.5 15t-8.5 13L404-268q-11 11-28 11t-28-11q-11-11-11-28t11-28l156-156Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="viewer-prev"> <path d="m432-480 156 156q11 11 11 28t-11 28q-11 11-28 11t-28-11L348-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 28-11t28 11q11 11 11 28t-11 28L432-480Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="menu-actor"> <path d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-240v-32q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v32q0 33-23.5 56.5T720-160H240q-33 0-56.5-23.5T160-240Zm80 0h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="menu-filters"> <path d="M440-240q-17 0-28.5-11.5T400-280q0-17 11.5-28.5T440-320h80q17 0 28.5 11.5T560-280q0 17-11.5 28.5T520-240h-80ZM280-440q-17 0-28.5-11.5T240-480q0-17 11.5-28.5T280-520h400q17 0 28.5 11.5T720-480q0 17-11.5 28.5T680-440H280ZM160-640q-17 0-28.5-11.5T120-680q0-17 11.5-28.5T160-720h640q17 0 28.5 11.5T840-680q0 17-11.5 28.5T800-640H160Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="menu-tags"> <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h440q19 0 36 8.5t28 23.5l180 240q16 21 16 48t-16 48L664-192q-11 15-28 23.5t-36 8.5H160Zm0-80h440l180-240-180-240H160v480Zm310-240Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="menu-new"> <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h207q16 0 30.5 6t25.5 17l57 57h360q17 0 28.5 11.5T880-680q0 17-11.5 28.5T840-640H447l-80-80H160v480l79-263q8-26 29.5-41.5T316-560h516q41 0 64.5 32.5T909-457l-72 240q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm-84-262v-218 218Zm84 262 72-240-72 240Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="fetch-data"> <path d="M440-474v-242q-76 14-118 73.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41h480q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-48-22-89.5T600-680v-93q74 35 117 103.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H260q-91 0-155.5-63T40-377q0-78 47-139t123-78q17-72 85-137t145-65q33 0 56.5 23.5T520-716v242l36-35q11-11 27.5-11t28.5 12q11 11 11 28t-11 28L508-348q-12 12-28 12t-28-12L348-452q-11-11-11.5-27.5T348-508q11-11 27.5-11.5T404-509l36 35Zm40-44Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="options"> <path d="M433-80q-27 0-46.5-18T363-142l-9-66q-13-5-24.5-12T307-235l-62 26q-25 11-50 2t-39-32l-47-82q-14-23-8-49t27-43l53-40q-1-7-1-13.5v-27q0-6.5 1-13.5l-53-40q-21-17-27-43t8-49l47-82q14-23 39-32t50 2l62 26q11-8 23-15t24-12l9-66q4-26 23.5-44t46.5-18h94q27 0 46.5 18t23.5 44l9 66q13 5 24.5 12t22.5 15l62-26q25-11 50-2t39 32l47 82q14 23 8 49t-27 43l-53 40q1 7 1 13.5v27q0 6.5-2 13.5l53 40q21 17 27 43t-8 49l-48 82q-14 23-39 32t-50-2l-60-26q-11 8-23 15t-24 12l-9 66q-4 26-23.5 44T527-80h-94Zm7-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="json"> <path d="M190-360h70q17 0 28.5-11.5T300-400v-200h-60v190h-40v-50h-50v60q0 17 11.5 28.5T190-360Zm177 0h60q17 0 28.5-11.5T467-400v-60q0-17-11.5-28.5T427-500h-50v-50h40v20h50v-30q0-17-11.5-28.5T427-600h-60q-17 0-28.5 11.5T327-560v60q0 17 11.5 28.5T367-460h50v50h-40v-20h-50v30q0 17 11.5 28.5T367-360Zm176-60v-120h40v120h-40Zm-10 60h60q17 0 28.5-11.5T633-400v-160q0-17-11.5-28.5T593-600h-60q-17 0-28.5 11.5T493-560v160q0 17 11.5 28.5T533-360Zm127 0h50v-105l40 105h50v-240h-50v105l-40-105h-50v240ZM120-160q-33 0-56.5-23.5T40-240v-480q0-33 23.5-56.5T120-800h720q33 0 56.5 23.5T920-720v480q0 33-23.5 56.5T840-160H120Zm0-80h720v-480H120v480Zm0 0v-480 480Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="question"> <path d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="bookmark"> <path d="M200-120v-640q0-33 23.5-56.5T280-840h400q33 0 56.5 23.5T760-760v640L480-240 200-120Zm80-122 200-86 200 86v-518H280v518Zm0-518h400-400Z"></path> </symbol> <symbol viewBox="0 -960 960 960" id="favorite"> <path d="m354-287 126-76 126 77-33-144 111-96-146-13-58-136-58 135-146 13 111 97-33 143ZM233-120l65-281L80-590l288-25 112-265 112 265 288 25-218 189 65 281-247-149-247 149Zm247-350Z"></path> </symbol> </svg> <script src="./js/strings.js"></script> <script src="./js/main.js"></script> </body> </html> |