feat: impact-media page type with OG scraping and cache
All checks were successful
Deploy / Deploy to Production (push) Successful in 12s
All checks were successful
Deploy / Deploy to Production (push) Successful in 12s
- Add impact-media blueprint (entries field + linked investigation) - Add minimal impact-media template - Refactor card-open-graph snippet: accepts $url param, Kirby cache (6h TTL), decode HTML entities, empty alt on images - Update impacts.yml to allow impact-media pages - Render impact-media in investigation aside with dynamic count + details/summary - Add OG cache config in config.php - CSS formatting fixes (body, card-block-small, category) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b8352c81fa
commit
f757906584
11 changed files with 505 additions and 452 deletions
|
|
@ -1,74 +1,74 @@
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-font-smoothing: antialiased;
|
-moz-font-smoothing: antialiased;
|
||||||
-o-font-smoothing: antialiased;
|
-o-font-smoothing: antialiased;
|
||||||
|
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
}
|
}
|
||||||
button{
|
button {
|
||||||
background: none;
|
background: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--color-txt);
|
color: var(--color-txt);
|
||||||
}
|
}
|
||||||
iframe{
|
iframe {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{
|
body {
|
||||||
font-family: var(--font);
|
font-family: var(--font);
|
||||||
line-height: var(--leading-normal);
|
line-height: var(--leading-normal);
|
||||||
font-size: var(--fs-normal);
|
font-size: var(--fs-normal);
|
||||||
|
|
||||||
color: var(--color-txt);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
|
|
||||||
|
|
||||||
|
color: var(--color-txt);
|
||||||
|
background-color: var(--color-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
img{
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-block{
|
.link-block {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
// &:hover{
|
// &:hover{
|
||||||
// background-color: rgba(255, 0, 0, 0.244);
|
// background-color: rgba(255, 0, 0, 0.244);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-button-next, .swiper-button-prev,
|
.swiper-button-next,
|
||||||
body, #site-header, #site-footer{
|
.swiper-button-prev,
|
||||||
transition: background-color 0.3s ease, color 0.3s ease;
|
body,
|
||||||
|
#site-header,
|
||||||
|
#site-footer {
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin grid-content(){
|
@mixin grid-content() {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: var(--padding-inner);
|
grid-gap: var(--padding-inner);
|
||||||
grid-template-columns: 2fr 3fr;
|
grid-template-columns: 2fr 3fr;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin hide-scroll() {
|
||||||
@mixin hide-scroll(){
|
scrollbar-width: none;
|
||||||
scrollbar-width: none;
|
-ms-overflow-style: none;
|
||||||
-ms-overflow-style: none;
|
&::-webkit-scrollbar {
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin clamp($lines) {
|
@mixin clamp($lines) {
|
||||||
|
|
@ -78,67 +78,60 @@ body, #site-header, #site-footer{
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin hover-card-line(){
|
@mixin hover-card-line() {
|
||||||
border-bottom: var(--border-light);
|
border-bottom: var(--border-light);
|
||||||
&:first-of-type{
|
&:first-of-type {
|
||||||
border-top: var(--border-light);
|
border-top: var(--border-light);
|
||||||
}
|
}
|
||||||
position: relative;
|
position: relative;
|
||||||
&::before{
|
&::before {
|
||||||
content: '';
|
content: "";
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top: 1px solid transparent;
|
border-top: 1px solid transparent;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover{
|
&:not([data-impact-type="media"]) {
|
||||||
background-color: var(--grey-950);
|
&:hover {
|
||||||
|
background-color: var(--grey-950);
|
||||||
|
border-color: var(--color-txt);
|
||||||
|
&::before {
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
&::before{
|
}
|
||||||
border-color: var(--color-txt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin pin() {
|
||||||
@mixin pin(){
|
.pin {
|
||||||
.pin{
|
z-index: 90;
|
||||||
z-index: 90;
|
width: 18px;
|
||||||
width: 18px;
|
height: 18px;
|
||||||
height: 18px;
|
transform: rotate(45deg);
|
||||||
transform: rotate(45deg);
|
transform-origin: center;
|
||||||
transform-origin: center;
|
svg {
|
||||||
svg{
|
width: 100%;
|
||||||
width: 100%;
|
height: 100%;
|
||||||
height: 100%;
|
fill: var(--color-txt);
|
||||||
fill: var(--color-txt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin icon($size) {
|
||||||
@mixin icon($size){
|
.icon {
|
||||||
|
display: flex;
|
||||||
.icon{
|
width: $size;
|
||||||
display: flex;
|
height: $size;
|
||||||
width: $size;
|
svg {
|
||||||
height: $size;
|
width: $size;
|
||||||
svg{
|
height: $size;
|
||||||
width: $size;
|
|
||||||
height: $size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
body.menu-open,
|
body.menu-open,
|
||||||
body.is-hidden{
|
body.is-hidden {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,153 +1,141 @@
|
||||||
.card--block-small {
|
.card--block-small {
|
||||||
|
border-bottom: var(--border-light);
|
||||||
|
padding: var(--padding-inner) 0;
|
||||||
|
padding-bottom: calc(var(--spacing) * 0.75);
|
||||||
|
|
||||||
border-bottom: var(--border-light);
|
&:first-of-type {
|
||||||
padding: var(--padding-inner) 0;
|
border-top: var(--border-light);
|
||||||
padding-bottom: calc(var(--spacing)*0.75);
|
}
|
||||||
|
|
||||||
&:first-of-type {
|
@include grid-content();
|
||||||
border-top: var(--border-light);
|
@include hover-card-line();
|
||||||
}
|
|
||||||
|
|
||||||
@include grid-content();
|
.group-top {
|
||||||
@include hover-card-line();
|
position: relative;
|
||||||
|
// top: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include btn--go-to();
|
||||||
|
|
||||||
.group-top {
|
.btn--go-to {
|
||||||
position: relative;
|
top: calc(var(--padding-inner) * 1);
|
||||||
// top: -5px;
|
bottom: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include btn--go-to();
|
.title {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 2;
|
||||||
|
font-size: var(--fs-normal);
|
||||||
|
line-height: var(--leading-title);
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-right: 4ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
font-size: var(--fs-small);
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media #{$small} {
|
||||||
|
display: block;
|
||||||
|
padding-bottom: calc(var(--spacing) * 0.5);
|
||||||
|
|
||||||
.btn--go-to {
|
.btn--go-to {
|
||||||
top: calc(var(--padding-inner)*1);
|
top: auto;
|
||||||
bottom: auto;
|
bottom: calc(var(--padding-inner) * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-top {
|
||||||
|
top: 0px;
|
||||||
|
margin-bottom: calc(var(--spacing) * 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
grid-column: 2;
|
margin-bottom: calc(var(--spacing) * 0.75);
|
||||||
grid-row: 2;
|
margin-right: 1ch;
|
||||||
font-size: var(--fs-normal);
|
|
||||||
line-height: var(--leading-title);
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-right: 4ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
font-size: var(--fs-small);
|
margin-top: 0px;
|
||||||
grid-column: 2;
|
|
||||||
grid-row: 1;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@media #{$small} {
|
|
||||||
display: block;
|
|
||||||
padding-bottom: calc(var(--spacing)*0.5);
|
|
||||||
|
|
||||||
.btn--go-to{
|
|
||||||
top: auto;
|
|
||||||
bottom: calc(var(--padding-inner)*1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-top {
|
|
||||||
top: 0px;
|
|
||||||
margin-bottom: calc(var(--spacing)*0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title{
|
|
||||||
margin-bottom: calc(var(--spacing)*0.75);
|
|
||||||
margin-right: 1ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date{
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.card--block-small {
|
.card--block-small {
|
||||||
|
|
||||||
.card--open-graph {
|
.card--open-graph {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card--open-graph:not(:last-child) {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open-graph__details {
|
||||||
|
grid-column: 2;
|
||||||
|
|
||||||
|
summary,
|
||||||
|
.summary-inner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
gap: 0.5ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.open-graph__details {
|
.arrow-details {
|
||||||
grid-column: 2;
|
line-height: 0;
|
||||||
|
--size: 11px;
|
||||||
|
height: var(--size);
|
||||||
|
width: var(--size);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transition: transform 0.2s ease-in;
|
||||||
|
width: 100%;
|
||||||
|
fill: var(--color-txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary:hover {
|
||||||
|
color: var(--color-txt);
|
||||||
|
|
||||||
|
.arrow-details svg {
|
||||||
|
fill: var(--color-txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[open] {
|
||||||
|
.arrow-details svg {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
color: var(--color-txt-light);
|
||||||
|
|
||||||
|
.arrow-details svg {
|
||||||
|
fill: var(--color-txt-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media #{$x-small} {
|
||||||
|
summary {
|
||||||
|
@include grid-content();
|
||||||
|
grid-row-gap: 0;
|
||||||
|
|
||||||
summary,
|
|
||||||
.summary-inner {
|
.summary-inner {
|
||||||
display: flex;
|
grid-column: 2;
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
gap: 0.5ch;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.arrow-details {
|
grid-column: 1/3;
|
||||||
line-height: 0;
|
|
||||||
--size: 11px;
|
|
||||||
height: var(--size);
|
|
||||||
width: var(--size);
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
top: -2px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
transition: transform 0.2s ease-in;
|
|
||||||
width: 100%;
|
|
||||||
fill: var(--color-txt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
summary:hover {
|
|
||||||
color: var(--color-txt);
|
|
||||||
|
|
||||||
.arrow-details svg {
|
|
||||||
fill: var(--color-txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&[open] {
|
|
||||||
.arrow-details svg {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
color: var(--color-txt-light);
|
|
||||||
|
|
||||||
.arrow-details svg {
|
|
||||||
fill: var(--color-txt-light);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media #{$x-small} {
|
|
||||||
summary {
|
|
||||||
@include grid-content();
|
|
||||||
grid-row-gap: 0;
|
|
||||||
|
|
||||||
.summary-inner {
|
|
||||||
grid-column: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grid-column: 1/3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,112 +1,102 @@
|
||||||
.type{
|
.type {
|
||||||
height: calc(var(--h-block)*0.75);
|
height: calc(var(--h-block) * 0.75);
|
||||||
// border-radius: calc(var(--h-block)*0.75/2);
|
// border-radius: calc(var(--h-block)*0.75/2);
|
||||||
border-radius: var(--radius-small);
|
border-radius: var(--radius-small);
|
||||||
|
width: max-content;
|
||||||
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 0 1ch;
|
||||||
|
padding-top: 3px;
|
||||||
|
|
||||||
|
font-size: var(--fs-xsmall);
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
background-color: var(--color-txt);
|
||||||
|
color: var(--color-bg);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
height: calc(var(--h-block) * 0.75);
|
||||||
|
border-radius: var(--radius-small);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 1ch;
|
||||||
|
padding-top: 3px;
|
||||||
|
|
||||||
|
font-size: var(--fs-xsmall);
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
border: var(--border-medium);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
color: var(--color-txt-light);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page__category {
|
||||||
|
height: calc(var(--h-block) * 1);
|
||||||
|
border-radius: var(--radius-small);
|
||||||
|
border: var(--border-medium);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 1.5ch;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
|
font-size: var(--fs-small);
|
||||||
|
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
color: var(--color-txt-light);
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
@media #{$small} {
|
||||||
|
height: calc(var(--h-block) * 0.75);
|
||||||
|
font-size: var(--fs-xsmall);
|
||||||
padding: 0 1ch;
|
padding: 0 1ch;
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
|
}
|
||||||
font-size: var(--fs-xsmall);
|
|
||||||
line-height: 1;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
background-color: var(--color-txt);
|
|
||||||
color: var(--color-bg);
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page__type {
|
||||||
|
height: calc(var(--h-block) * 1);
|
||||||
|
border-radius: var(--radius-small);
|
||||||
|
margin-left: calc(var(--padding-inner) * 0.25);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 1.5ch;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
.category{
|
font-size: var(--fs-small);
|
||||||
height: calc(var(--h-block)*0.75);
|
|
||||||
border-radius: var(--radius-small);
|
|
||||||
|
|
||||||
display: inline-flex;
|
background-color: var(--color-txt);
|
||||||
align-items: center;
|
color: var(--color-bg);
|
||||||
justify-content: center;
|
font-weight: 500;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
@media #{$small} {
|
||||||
|
height: calc(var(--h-block) * 0.75);
|
||||||
|
font-size: var(--fs-xsmall);
|
||||||
padding: 0 1ch;
|
padding: 0 1ch;
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
|
}
|
||||||
font-size: var(--fs-xsmall);
|
|
||||||
line-height: 1;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
border: var(--border-medium);
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-txt-light);
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page__category{
|
|
||||||
|
|
||||||
height: calc(var(--h-block)*1);
|
|
||||||
border-radius: var(--radius-small);
|
|
||||||
border: var(--border-medium);
|
|
||||||
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 1.5ch;
|
|
||||||
padding-top: 5px;
|
|
||||||
|
|
||||||
font-size: var(--fs-small);
|
|
||||||
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
color: var(--color-txt-light);
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
@media #{$small} {
|
|
||||||
height: calc(var(--h-block)*0.75);
|
|
||||||
font-size: var(--fs-xsmall);
|
|
||||||
padding: 0 1ch;
|
|
||||||
padding-top: 3px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.page__type{
|
|
||||||
|
|
||||||
height: calc(var(--h-block)*1);
|
|
||||||
border-radius: var(--radius-small);
|
|
||||||
margin-left: calc(var(--padding-inner)*0.25);
|
|
||||||
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 1.5ch;
|
|
||||||
padding-top: 5px;
|
|
||||||
|
|
||||||
font-size: var(--fs-small);
|
|
||||||
|
|
||||||
background-color: var(--color-txt);
|
|
||||||
color: var(--color-bg);
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
@media #{$small} {
|
|
||||||
height: calc(var(--h-block)*0.75);
|
|
||||||
font-size: var(--fs-xsmall);
|
|
||||||
padding: 0 1ch;
|
|
||||||
padding-top: 3px;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,8 +138,11 @@ img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-button-next, .swiper-button-prev,
|
.swiper-button-next,
|
||||||
body, #site-header, #site-footer {
|
.swiper-button-prev,
|
||||||
|
body,
|
||||||
|
#site-header,
|
||||||
|
#site-footer {
|
||||||
transition: background-color 0.3s ease, color 0.3s ease;
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -741,6 +744,8 @@ button:disabled {
|
||||||
.type {
|
.type {
|
||||||
height: calc(var(--h-block) * 0.75);
|
height: calc(var(--h-block) * 0.75);
|
||||||
border-radius: var(--radius-small);
|
border-radius: var(--radius-small);
|
||||||
|
width: -moz-max-content;
|
||||||
|
width: max-content;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -1951,13 +1956,13 @@ figcaption,
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
.card--package:hover,
|
.card--package:not([data-impact-type=media]):hover,
|
||||||
.card--article-small:hover {
|
.card--article-small:not([data-impact-type=media]):hover {
|
||||||
background-color: var(--grey-950);
|
background-color: var(--grey-950);
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
.card--package:hover::before,
|
.card--package:not([data-impact-type=media]):hover::before,
|
||||||
.card--article-small:hover::before {
|
.card--article-small:not([data-impact-type=media]):hover::before {
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 1080px) {
|
@media screen and (max-width: 1080px) {
|
||||||
|
|
@ -2025,11 +2030,11 @@ figcaption,
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
.card--block:hover {
|
.card--block:not([data-impact-type=media]):hover {
|
||||||
background-color: var(--grey-950);
|
background-color: var(--grey-950);
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
.card--block:hover::before {
|
.card--block:not([data-impact-type=media]):hover::before {
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
.card--block > figure {
|
.card--block > figure {
|
||||||
|
|
@ -2156,11 +2161,11 @@ figcaption,
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
.card--block-small:hover {
|
.card--block-small:not([data-impact-type=media]):hover {
|
||||||
background-color: var(--grey-950);
|
background-color: var(--grey-950);
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
.card--block-small:hover::before {
|
.card--block-small:not([data-impact-type=media]):hover::before {
|
||||||
border-color: var(--color-txt);
|
border-color: var(--color-txt);
|
||||||
}
|
}
|
||||||
.card--block-small .group-top {
|
.card--block-small .group-top {
|
||||||
|
|
@ -2235,7 +2240,7 @@ figcaption,
|
||||||
margin-right: 1ch;
|
margin-right: 1ch;
|
||||||
}
|
}
|
||||||
.card--block-small .date {
|
.card--block-small .date {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2243,6 +2248,9 @@ figcaption,
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
.card--block-small .card--open-graph:not(:last-child) {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
.card--block-small .open-graph__details {
|
.card--block-small .open-graph__details {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
16
site/blueprints/pages/impact-media.yml
Normal file
16
site/blueprints/pages/impact-media.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
title: Impact médiatique
|
||||||
|
|
||||||
|
fields:
|
||||||
|
linkedInvestigation:
|
||||||
|
label: Enquête liée
|
||||||
|
type: pages
|
||||||
|
query: page('enquetes').children.listed
|
||||||
|
multiple: false
|
||||||
|
layout: list
|
||||||
|
text: "{{ page.title }}"
|
||||||
|
info: "{{ page.created }}"
|
||||||
|
entries:
|
||||||
|
label: Articles et reprises
|
||||||
|
type: entries
|
||||||
|
field:
|
||||||
|
type: url
|
||||||
|
|
@ -17,8 +17,9 @@ tabs:
|
||||||
impactsSection:
|
impactsSection:
|
||||||
type: pages
|
type: pages
|
||||||
label: Liste des impacts
|
label: Liste des impacts
|
||||||
template: impact
|
templates:
|
||||||
create: impact
|
- impact
|
||||||
|
- impact-media
|
||||||
layout: list
|
layout: list
|
||||||
text: "{{ page.title }}"
|
text: "{{ page.title }}"
|
||||||
info: "{{ page.category }} — {{ page.created.toDate('d/m/Y') }}"
|
info: "{{ page.category }} — {{ page.created.toDate('d/m/Y') }}"
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ return [
|
||||||
],
|
],
|
||||||
'tobimori.seo.canonicalBase' => 'https://www.index.ngo',
|
'tobimori.seo.canonicalBase' => 'https://www.index.ngo',
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
'og' => true,
|
||||||
|
],
|
||||||
|
|
||||||
'routes' => [
|
'routes' => [
|
||||||
require(__DIR__ . '/routes/newsletter.php'),
|
require(__DIR__ . '/routes/newsletter.php'),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,111 +1,109 @@
|
||||||
<?php
|
<?php
|
||||||
// URL à scraper (remplacez par l'URL souhaitée)
|
/**
|
||||||
$url = 'https://www.lemonde.fr/societe/article/2025/07/16/au-c-ur-des-emeutes-de-nouvelle-caledonie-quand-la-mort-de-banane-abattu-par-le-gign-lance-le-siege-de-saint-louis_6621496_3224.html';
|
* Card Open Graph snippet
|
||||||
|
* Fetches and displays OG data from an external URL with cache.
|
||||||
|
*
|
||||||
|
* @var string $url The URL to scrape OG data from
|
||||||
|
*/
|
||||||
|
|
||||||
// Fonction pour récupérer les données Open Graph
|
if (empty($url)) return;
|
||||||
function getOpenGraphData($url) {
|
|
||||||
$ogData = [
|
|
||||||
'title' => '',
|
|
||||||
'description' => '',
|
|
||||||
'image' => '',
|
|
||||||
'site_name' => '',
|
|
||||||
'url' => $url
|
|
||||||
];
|
|
||||||
|
|
||||||
// Configuration du contexte pour éviter les erreurs SSL
|
$cache = kirby()->cache('og');
|
||||||
$context = stream_context_create([
|
$cacheKey = md5($url);
|
||||||
'http' => [
|
$ogData = $cache->get($cacheKey);
|
||||||
'method' => 'GET',
|
|
||||||
'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
||||||
'timeout' => 10
|
|
||||||
],
|
|
||||||
'ssl' => [
|
|
||||||
'verify_peer' => false,
|
|
||||||
'verify_peer_name' => false
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Récupérer le HTML
|
if ($ogData === null) {
|
||||||
$html = @file_get_contents($url, false, $context);
|
$ogData = [
|
||||||
|
'title' => '',
|
||||||
|
'description' => '',
|
||||||
|
'image' => '',
|
||||||
|
'site_name' => '',
|
||||||
|
'url' => $url,
|
||||||
|
];
|
||||||
|
|
||||||
if ($html === false) {
|
$context = stream_context_create([
|
||||||
return $ogData;
|
'http' => [
|
||||||
}
|
'method' => 'GET',
|
||||||
|
'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||||
|
'timeout' => 10,
|
||||||
|
],
|
||||||
|
'ssl' => [
|
||||||
|
'verify_peer' => false,
|
||||||
|
'verify_peer_name' => false,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
// Parser les meta tags Open Graph
|
$html = @file_get_contents($url, false, $context);
|
||||||
preg_match_all('/<meta\s+property=["\']og:([^"\']+)["\']\s+content=["\']([^"\']+)["\']/i', $html, $matches);
|
|
||||||
|
|
||||||
if (!empty($matches[1])) {
|
if ($html !== false) {
|
||||||
foreach ($matches[1] as $index => $property) {
|
// Parse OG meta tags (both property...content and content...property orders)
|
||||||
$content = $matches[2][$index];
|
preg_match_all('/<meta\s+(?:property=["\']og:([^"\']+)["\']\s+content=["\']([^"\']*)["\']|content=["\']([^"\']*?)["\']\s+property=["\']og:([^"\']+)["\'])/i', $html, $matches);
|
||||||
switch ($property) {
|
|
||||||
case 'title':
|
|
||||||
$ogData['title'] = htmlspecialchars($content);
|
|
||||||
break;
|
|
||||||
case 'description':
|
|
||||||
$ogData['description'] = htmlspecialchars($content);
|
|
||||||
break;
|
|
||||||
case 'image':
|
|
||||||
$ogData['image'] = $content;
|
|
||||||
break;
|
|
||||||
case 'site_name':
|
|
||||||
$ogData['site_name'] = htmlspecialchars($content);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: si pas de og:title, utiliser <title>
|
if (!empty($matches[1])) {
|
||||||
if (empty($ogData['title'])) {
|
foreach ($matches[1] as $index => $property) {
|
||||||
preg_match('/<title>([^<]+)<\/title>/i', $html, $titleMatch);
|
$prop = $property ?: $matches[4][$index];
|
||||||
if (!empty($titleMatch[1])) {
|
$content = $matches[2][$index] ?: $matches[3][$index];
|
||||||
$ogData['title'] = htmlspecialchars($titleMatch[1]);
|
$content = html_entity_decode(trim($content), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||||
}
|
switch ($prop) {
|
||||||
}
|
case 'title':
|
||||||
|
$ogData['title'] = $content;
|
||||||
|
break;
|
||||||
|
case 'description':
|
||||||
|
$ogData['description'] = $content;
|
||||||
|
break;
|
||||||
|
case 'image':
|
||||||
|
$ogData['image'] = $content;
|
||||||
|
break;
|
||||||
|
case 'site_name':
|
||||||
|
$ogData['site_name'] = $content;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback: si pas de site_name, utiliser le domaine
|
// Fallback: use <title> if no og:title
|
||||||
if (empty($ogData['site_name'])) {
|
if (empty($ogData['title'])) {
|
||||||
$parsed = parse_url($url);
|
preg_match('/<title>([^<]+)<\/title>/i', $html, $titleMatch);
|
||||||
$ogData['site_name'] = $parsed['host'] ?? '';
|
if (!empty($titleMatch[1])) {
|
||||||
}
|
$ogData['title'] = html_entity_decode($titleMatch[1], ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $ogData;
|
// Always use domain as site_name
|
||||||
}
|
$parsed = parse_url($url);
|
||||||
|
$ogData['site_name'] = $parsed['host'] ?? '';
|
||||||
|
|
||||||
$ogData = getOpenGraphData($url);
|
$cache->set($cacheKey, $ogData, 360); // 6 hours
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
// Toujours utiliser le domaine de l'URL pour site_name
|
<div class="card--open-graph">
|
||||||
$parsed = parse_url($url);
|
<div class="open-graph__inner">
|
||||||
$ogData['site_name'] = $parsed['host'] ?? '';
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="card--open-graph">
|
<?php if (!empty($ogData['image'])): ?>
|
||||||
<div class="open-graph__inner">
|
<figure>
|
||||||
|
<img src="<?= htmlspecialchars($ogData['image']) ?>" alt="">
|
||||||
|
</figure>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (!empty($ogData['image'])): ?>
|
<div class="content">
|
||||||
<figure>
|
<?php if (!empty($ogData['site_name'])): ?>
|
||||||
<img src="<?= $ogData['image'] ?>" alt="<?= $ogData['title'] ?>">
|
<span class="site-name"><?= htmlspecialchars($ogData['site_name']) ?></span>
|
||||||
</figure>
|
<?php endif ?>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="content">
|
<?php if (!empty($ogData['title'])): ?>
|
||||||
<?php if (!empty($ogData['site_name'])): ?>
|
<h3 class="title">
|
||||||
<span class="site-name"><?= $ogData['site_name'] ?></span>
|
<a href="<?= htmlspecialchars($ogData['url']) ?>" target="_blank">
|
||||||
<?php endif; ?>
|
<?= htmlspecialchars($ogData['title']) ?>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (!empty($ogData['title'])): ?>
|
<?php if (!empty($ogData['description'])): ?>
|
||||||
|
<p class="description"><?= htmlspecialchars($ogData['description']) ?></p>
|
||||||
<h3 class="title">
|
<?php endif ?>
|
||||||
<a href="<?= $ogData['url'] ?>" target="_blank">
|
</div>
|
||||||
<?= $ogData['title'] ?>
|
<a class="link-block" href="<?= htmlspecialchars($ogData['url']) ?>" target="_blank"></a>
|
||||||
</a>
|
</div>
|
||||||
</h3>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if (!empty($ogData['description'])): ?>
|
|
||||||
<p class="description"><?= $ogData['description'] ?></p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<a class="link-block" href="<?= $ogData['url'] ?>" target="_blank"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
||||||
47
site/templates/impact-media.php
Normal file
47
site/templates/impact-media.php
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php snippet('header') ?>
|
||||||
|
|
||||||
|
<main class="main__single">
|
||||||
|
|
||||||
|
<header class="page__header">
|
||||||
|
<p class="page__type">Impact</p>
|
||||||
|
<p class="page__category">Médiatique</p>
|
||||||
|
<h2 class="page__title"><?= $page->title()->esc() ?></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$entries = $page->entries()->toEntries();
|
||||||
|
$investigation = $page->linkedInvestigation()->toPages()->first();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($entries->isNotEmpty()): ?>
|
||||||
|
<div class="page__content">
|
||||||
|
<?php foreach ($entries as $entry): ?>
|
||||||
|
<?php snippet('card-open-graph', ['url' => $entry->value()]) ?>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if ($investigation): ?>
|
||||||
|
<aside class="page__aside" id="related-investigations">
|
||||||
|
<h3 class="aside__title">Enquête liée</h3>
|
||||||
|
|
||||||
|
<article class="card--article-small">
|
||||||
|
<?php if ($cover = $investigation->cover()->toFile()): ?>
|
||||||
|
<figure>
|
||||||
|
<img src="<?= $cover->url() ?>" alt="<?= $investigation->title()->esc() ?>">
|
||||||
|
</figure>
|
||||||
|
<?php endif ?>
|
||||||
|
<div class="content">
|
||||||
|
<p class="type">Enquête</p>
|
||||||
|
<h4 class="title"><a href="<?= $investigation->url() ?>"><?= $investigation->title()->esc() ?></a></h4>
|
||||||
|
</div>
|
||||||
|
<button class="btn--go-to"><a href="<?= $investigation->url() ?>"><?= svg('assets/icons/arrow-left.svg') ?></a></button>
|
||||||
|
<a class="link-block" href="<?= $investigation->url() ?>" aria-hidden="true"></a>
|
||||||
|
</article>
|
||||||
|
</aside>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php snippet('bottom-bar') ?>
|
||||||
|
<?php snippet('footer') ?>
|
||||||
|
|
@ -303,19 +303,6 @@ $dateLocale = substr(is_array($locale) ? reset($locale) : $locale, 0, 5);
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- <div class="card--block-small" data-impact-type="media">
|
|
||||||
|
|
||||||
<p class="category">Médiatique</p>
|
|
||||||
<div class="content">
|
|
||||||
<p>12 articles et reprises</p>
|
|
||||||
<p>1.5M de vues cumulées</p>
|
|
||||||
</div>
|
|
||||||
<details class="open-graph__details">
|
|
||||||
<summary><p class="summary-inner">Détails <span class="arrow-details"><?= svg('assets/icons/arrow-details.svg') ?></span><p></summary>
|
|
||||||
<?php snippet('card-open-graph') ?>
|
|
||||||
</details>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$resourcesParent = site()->find('ressources');
|
$resourcesParent = site()->find('ressources');
|
||||||
|
|
@ -361,6 +348,9 @@ $resources = $resourcesParent ? $resourcesParent->children()->listed()->filter(f
|
||||||
<?php
|
<?php
|
||||||
$impactsParent = site()->find('impacts');
|
$impactsParent = site()->find('impacts');
|
||||||
$impacts = $impactsParent ? $impactsParent->children()->listed()->filter(function($impact) use ($page) {
|
$impacts = $impactsParent ? $impactsParent->children()->listed()->filter(function($impact) use ($page) {
|
||||||
|
if ($impact->intendedTemplate()->name() === 'impact-media') {
|
||||||
|
return $impact->linkedInvestigation()->toPages()->has($page);
|
||||||
|
}
|
||||||
return $impact->linkedInvestigations()->toPages()->has($page);
|
return $impact->linkedInvestigations()->toPages()->has($page);
|
||||||
}) : null;
|
}) : null;
|
||||||
?>
|
?>
|
||||||
|
|
@ -370,6 +360,23 @@ $impacts = $impactsParent ? $impactsParent->children()->listed()->filter(functio
|
||||||
<h3 class="aside__title"><?= t('impacts.title') ?></h3>
|
<h3 class="aside__title"><?= t('impacts.title') ?></h3>
|
||||||
|
|
||||||
<?php foreach ($impacts as $impact): ?>
|
<?php foreach ($impacts as $impact): ?>
|
||||||
|
<?php if ($impact->intendedTemplate()->name() === 'impact-media'): ?>
|
||||||
|
<?php $entries = $impact->entries()->toEntries(); ?>
|
||||||
|
<div class="card--block-small" data-impact-type="media">
|
||||||
|
<p class="type">Médiatique</p>
|
||||||
|
<div class="content">
|
||||||
|
<p><?= $entries->count() ?> article<?= $entries->count() > 1 ? 's' : '' ?> et reprise<?= $entries->count() > 1 ? 's' : '' ?></p>
|
||||||
|
</div>
|
||||||
|
<?php if ($entries->isNotEmpty()): ?>
|
||||||
|
<details class="open-graph__details">
|
||||||
|
<summary><p class="summary-inner">Détails <span class="arrow-details"><?= svg('assets/icons/arrow-details.svg') ?></span></p></summary>
|
||||||
|
<?php foreach ($entries as $entry): ?>
|
||||||
|
<?php snippet('card-open-graph', ['url' => $entry->value()]) ?>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</details>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
<div class="card--block-small has-link">
|
<div class="card--block-small has-link">
|
||||||
<div class="group-top">
|
<div class="group-top">
|
||||||
<p class="type"><?= t('impact.type') ?></p>
|
<p class="type"><?= t('impact.type') ?></p>
|
||||||
|
|
@ -394,6 +401,7 @@ $impacts = $impactsParent ? $impactsParent->children()->listed()->filter(functio
|
||||||
|
|
||||||
<a class="link-block" href="<?= $impact->url() ?>" aria-hidden="true"></a>
|
<a class="link-block" href="<?= $impact->url() ?>" aria-hidden="true"></a>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue