Compare commits

..

No commits in common. "98043b37dcb1431e50c83bef05b4f5d453570c65" and "b62122eb59df4025d3752e8fa5f4d5241932939f" have entirely different histories.

15 changed files with 79 additions and 372 deletions

View File

@ -28,6 +28,7 @@ function getRevueAuthors($revueID)
}
}
return array_unique($authors);
s;
}
@ -46,82 +47,3 @@ function count_user_articles($userID, $postType)
$query = new WP_Query($args);
return $query->found_posts;
}
function build_sommaire_from_content($postID)
{
$blocks = parse_blocks(get_the_content($postID));
$titleBlocks = array_filter(
$blocks,
function ($block) {
return $block['blockName'] === 'core/heading' && isset($block['attrs']['level']) && in_array($block['attrs']['level'], array(2, 3), true);
}
);
$outputIndex = [];
foreach ($titleBlocks as $block) {
$title = strip_tags($block['innerHTML']);
$anchor = $block['attrs']['idName'] ?? sanitize_title($title);
$level = $block['attrs']['level'];
$outputIndex[] = [
'title' => $title,
'anchor' => $anchor,
];
}
return $outputIndex;
}
function build_footnotes_index_from_content($content)
{
if (empty($content)) {
return [];
}
$footnotes = [];
$dom = new DOMDocument();
// On supprime les erreurs de parsing pour le HTML5
@$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$links = $dom->getElementsByTagName('a');
foreach ($links as $key => $link) {
if ($link->hasAttribute('class') && strpos($link->getAttribute('class'), 'footnote-reference') !== false) {
$footnote_content = $link->getAttribute('footnote-content');
if (!empty($footnote_content)) {
$footnotes[] = array(
'key' => $key + 1,
'anchorID' => $key + 1,
'content' => $footnote_content
);
}
}
}
return $footnotes;
}
add_filter('the_content', 'apply_footnotes_urls_to_content', 10);
function apply_footnotes_urls_to_content($content)
{
$post_type = get_post_type();
if ($post_type !== 'articles' && !is_admin()) return $content;
$footnotes = build_footnotes_index_from_content($content);
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$links = $dom->getElementsByTagName('a');
foreach ($links as $key => $link) {
if ($link->hasAttribute('class') && strpos($link->getAttribute('class'), 'footnote-reference') !== false) {
$link->setAttribute('id', 'footnote-' . $key + 1);
}
}
return $dom->saveHTML();
}

View File

@ -27,9 +27,6 @@
@import './components/article-content.css';
@import './components/content-meta.css';
@import './components/post-header.css';
@import './components/sommaire-index.css';
@import './components/index-panel.css';
@import './components/footnotes-index.css';
/* ########### PAGES ############ */
@import './pages/singles.css';

View File

@ -1,5 +1,2 @@
.article-content {
.article-tags-list {
@apply mb-8;
}
}

View File

@ -1,19 +0,0 @@
.footnotes-index {
counter-reset: footnote-index;
@apply mb-4;
li {
@apply mb-4;
&:before {
content: counter(footnote-index);
counter-increment: footnote-index;
@apply mr-2 text-white text-base inline-flex bg-primary rounded-full w-8 h-8 items-center justify-center;
}
}
a {
@apply text-carhop-gray opacity-80;
&[active='true'] {
@apply text-primary font-bold;
}
}
}

View File

@ -1,34 +0,0 @@
.index-panel {
@apply p-6 m-0 border-primary border my-2;
max-height: 80vh;
overflow-y: auto;
&__header {
@apply flex gap-4 border-b border-gray-300 mb-8;
button {
@apply pb-3 text-carhop-gray opacity-60 relative;
box-sizing: border-box;
}
button[aria-selected='true'] {
@apply text-primary opacity-100;
&:after {
@apply bg-primary;
content: '';
display: block;
width: 100%;
height: 3px;
position: absolute;
bottom: -1px;
left: 0;
}
}
}
&__content {
overflow-wrap: anywhere;
ul[aria-hidden='true'] {
@apply hidden;
}
}
}

View File

@ -13,7 +13,7 @@
}
}
&__title {
@apply text-3xl font-normal uppercase;
@apply text-3xl font-normal;
}
&__date {
@apply capitalize pt-3 block;

View File

@ -1,9 +1,9 @@
.post-header {
@apply bg-primary text-white py-32;
@apply bg-purple-50 text-primary py-32;
h1.post-header__title,
h2.post-header__title {
@apply uppercase font-medium text-7xl text-white;
@apply uppercase font-medium text-7xl;
line-height: 1.2;
}
&__inner {
@ -15,9 +15,7 @@
grid-template-columns: 1fr;
}
}
.content-meta__revue-issue {
@apply bg-white text-primary;
}
.thumbnail-wrapper {
@apply bg-red-200;
img {
@ -31,7 +29,7 @@
grid-template-columns: 1fr 1fr;
&__label {
@apply uppercase font-bold text-lg text-white;
@apply uppercase font-bold text-lg;
letter-spacing: 0.2em;
}
}
@ -40,7 +38,7 @@
@apply flex gap-4;
&__button {
@apply bg-white text-carhop-green-700 px-4 py-2 font-normal rounded-full w-fit flex items-center gap-2;
@apply bg-white text-carhop-green-700 px-4 py-2 font-normal rounded-full border-primary w-fit border-2 flex items-center gap-2;
transition: transform 0.3s ease-in-out;
&:hover {
transform: scale(1.05);
@ -57,12 +55,5 @@
}
.article-meta__related-revue a {
@apply hover:underline underline-offset-8 text-white;
text-decoration-color: #fff;
text-decoration-thickness: 1px;
}
.article-meta__value {
@apply text-white font-light tracking-wide;
letter-spacing: 0.0015em;
@apply hover:underline underline-offset-8;
}

View File

@ -1,9 +0,0 @@
.sommaire-index {
@apply list-none;
li {
@apply mb-4;
}
a {
@apply text-xl text-carhop-gray opacity-80;
}
}

View File

@ -1,30 +1,11 @@
.page--single-revue,
.page--single-articles {
.content-wrapper {
@apply container mx-auto grid grid-cols-12 gap-12 py-12 items-start;
grid-template-columns: 1fr 2fr;
}
.top-toolbar {
@apply col-span-2;
.tablist {
@apply flex gap-12 border-b border-primary;
button {
@apply text-xl mt-8 nunito pb-4;
&[aria-selected='true'] {
@apply text-primary border-b-4 border-primary;
}
&[aria-selected='false'] {
@apply text-carhop-gray opacity-80;
}
}
}
@apply container mx-auto grid grid-cols-12 gap-12 py-12;
grid-template-columns: 1fr 4fr;
}
.sidebar {
@apply sticky top-0 left-0 h-fit;
.search-field {
input {
@apply border border-primary w-full;

View File

@ -1,5 +1,6 @@
import menuInit from './header';
import singlesInit from './singles/singles';
import singleRevue from './single-revue';
import singlesInit from './singles';
window.addEventListener('DOMContentLoaded', function () {
menuInit();

63
resources/js/singles.ts Normal file
View File

@ -0,0 +1,63 @@
export default function singles(): void {
const isSingleRevue: HTMLElement | null =
document.querySelector('.page--single-revue');
const isSingleArticle: HTMLElement | null =
document.querySelector('.page--single-articles');
if (!isSingleRevue && !isSingleArticle) return;
handleCiteButton();
}
function handleCiteButton(): void {
const citeButton: HTMLElement | null =
document.querySelector(
'.socials-buttons__button--cite'
);
const citeReference: HTMLElement | null =
document.querySelector('#cite-reference');
if (!citeButton || !citeReference) return;
if (!window.isSecureContext) {
citeButton.setAttribute('disabled', 'true');
citeButton.setAttribute(
'title',
'Vous devez utiliser un navigation sécurisé (https) pour copier la citation'
);
}
citeButton.addEventListener('click', () => {
const textToCopy = citeReference.textContent;
if (!textToCopy) return;
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard
.writeText(textToCopy)
.then(() => {
const notyf = new Notyf({
duration: 4000,
ripple: false,
dismissible: true,
types: [
{
type: 'success',
icon: {
className: 'notyf__icon--success',
tagName: 'i',
},
},
],
position: {
x: 'right',
y: 'top',
},
});
notyf.success(
'Citation copiée dans le presse-papiers ! <br> Vous pouvez maintenant la coller dans votre document.'
);
})
.catch((err) => {
console.error('Failed to copy text: ', err);
});
}
});
}

View File

@ -1,80 +0,0 @@
export default function handleIndexPanels(): void {
const indexPanel = document.querySelector('.index-panel');
if (!indexPanel) return;
observeTabsButtons();
observeFootnotesLinks();
}
// HANDLE TABS
function observeTabsButtons(): void {
const buttons = document.querySelectorAll('.index-panel__header button');
buttons.forEach((button) => {
button.addEventListener('click', () => {
toggleActiveTabsButton(button as HTMLElement);
toggleActiveTabsPanel(button as HTMLElement);
});
});
}
function toggleActiveTabsButton(button: HTMLElement): void {
const buttons = document.querySelectorAll('.index-panel__header button');
buttons.forEach((button) => {
button.setAttribute('aria-selected', 'false');
});
button.setAttribute('aria-selected', 'true');
}
function toggleActiveTabsPanel(activeButton: HTMLElement): void {
const dataIndex = activeButton.getAttribute('data-index');
const activePanel = document.querySelector<HTMLElement>(
`.index-panel__content > [data-index="${dataIndex}"]`
);
if (!dataIndex || !activePanel) return;
// Hide all buttons and panels
const allButtons = document.querySelectorAll<HTMLElement>('.index-panel__header button');
const allPanels = document.querySelectorAll<HTMLElement>('.index-panel__content > [data-index]');
allButtons.forEach((button) => {
button.setAttribute('aria-selected', 'false');
});
allPanels.forEach((panel) => {
panel.setAttribute('aria-hidden', 'true');
});
// Active the button and the panel
activeButton.setAttribute('aria-selected', 'true');
activePanel.setAttribute('aria-hidden', 'false');
}
function observeFootnotesLinks(): void {
const footnotesButtons = document.querySelectorAll('.footnotes-index a');
footnotesButtons.forEach((footnoteButton) => {
footnoteButton.addEventListener('click', (e) => {
e.preventDefault();
const target = e.target as HTMLElement;
const targetId = target.getAttribute('href');
if (!targetId) return;
document.querySelector(targetId)?.scrollIntoView({ behavior: 'smooth' });
toggleActiveFootnote(footnoteButton as HTMLElement);
});
});
}
function toggleActiveFootnote(button: HTMLElement): void {
const buttons = document.querySelectorAll('footnote-reference-item');
const footnotesItems = document.querySelectorAll('.footnote-reference-item');
footnotesItems.forEach((footnoteItem) => {
footnoteItem.setAttribute('active', 'false');
});
button.setAttribute('active', 'true');
}

View File

@ -1,94 +0,0 @@
import handleIndexPanels from './index-panel';
export default function singles(): void {
const isSingleRevue: HTMLElement | null = document.querySelector('.page--single-revue');
const isSingleArticle: HTMLElement | null = document.querySelector('.page--single-articles');
if (!isSingleRevue && !isSingleArticle) return;
injectIdToNativeTitles();
handleIndexPanels();
handleCiteButton();
handleSmoothScrollToTitle();
}
function handleCiteButton(): void {
const citeButton: HTMLElement | null = document.querySelector('.socials-buttons__button--cite');
const citeReference: HTMLElement | null = document.querySelector('#cite-reference');
if (!citeButton || !citeReference) return;
if (!window.isSecureContext) {
citeButton.setAttribute('disabled', 'true');
citeButton.setAttribute(
'title',
'Vous devez utiliser un navigation sécurisé (https) pour copier la citation'
);
}
citeButton.addEventListener('click', () => {
const textToCopy = citeReference.textContent;
if (!textToCopy) return;
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard
.writeText(textToCopy)
.then(() => {
const notyf = new Notyf({
duration: 4000,
ripple: false,
dismissible: true,
types: [
{
type: 'success',
icon: {
className: 'notyf__icon--success',
tagName: 'i',
},
},
],
position: {
x: 'right',
y: 'top',
},
});
notyf.success(
'Citation copiée dans le presse-papiers ! <br> Vous pouvez maintenant la coller dans votre document.'
);
})
.catch((err) => {
console.error('Failed to copy text: ', err);
});
}
});
}
function injectIdToNativeTitles(): void {
const titles = document.querySelectorAll('.content-area h2, .content-area h3');
titles.forEach((title) => {
const titleText = title.textContent || '';
const slug = titleText
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/\s+/g, '-')
.replace(/[^\w-]+/g, '');
title.setAttribute('id', slug);
});
}
function handleSmoothScrollToTitle(): void {
const sommaireTitles: NodeListOf<Element> = document.querySelectorAll('.sommaire-index li a');
for (const title of sommaireTitles) {
title.addEventListener('click', (e) => {
e.preventDefault();
const target = title.getAttribute('href');
if (!target) return;
const targetElement = document.querySelector(target);
if (!targetElement) return;
targetElement.scrollIntoView({ behavior: 'smooth' });
});
}
}

View File

@ -3,18 +3,11 @@ $articleID = $args['ID'];
$articleContent = get_the_content($articleID);
$articleTitle = get_the_title($articleID);
$citeReference = get_field('cite_reference', $articleID);
$tags = get_the_terms($articleID, 'etiquettes');
?>
<article class="article-content">
<ul class="article-tags-list">
<?php foreach ($tags as $tag) : ?>
<li class="article-tag">
<?php echo $tag->name; ?>
</li>
<?php endforeach; ?>
</ul>
<?php the_content(); ?>
<h1><?php echo $articleTitle; ?></h1>
<?php echo $articleContent; ?>
<?php if ($citeReference) : ?>
<p id="cite-reference">
<?php echo $citeReference; ?>

View File

@ -14,8 +14,6 @@ $issueNumber = get_field('issue_number', $currentRevueID);
$post_type = get_post_type();
$hasThumbnail = has_post_thumbnail();
$citeReference = get_field('cite_reference', $currentRevueID);
?>
<section class="post-header post-header--<?php echo $post_type; ?> ">
@ -44,7 +42,7 @@ $citeReference = get_field('cite_reference', $currentRevueID);
<?php if ($post_type === 'revues') : ?>
<h1 class="post-header__title"> <?php echo $revueTitle; ?></h1>
<?php elseif ($post_type === 'articles') : ?>
<h2 class="post-header__title"> <?php echo get_the_title(); ?></h2>
<h2 class="post-header__title"> <?php echo $revueTitle; ?></h2>
<?php endif; ?>
<div class="post-details">
@ -64,7 +62,7 @@ $citeReference = get_field('cite_reference', $currentRevueID);
</div>
<?php endif; ?>
<div class="socials-buttons">
<button class="socials-buttons__button socials-buttons__button--cite" disabled="<?php echo empty($citeReference) ? 'true' : 'false'; ?>" title="<?php echo empty($citeReference) ? 'Citation non disponible' : 'Copier la citation'; ?>">
<button class="socials-buttons__button socials-buttons__button--cite">
<img src="<?php echo get_template_directory_uri(); ?>/resources/img/icons/carhop-citer-article.svg" alt="">
Citer
</button>