diff --git a/content/meta/index.mdoc b/content/meta/index.mdoc index 2a7b436..3dd24e9 100644 --- a/content/meta/index.mdoc +++ b/content/meta/index.mdoc @@ -19,6 +19,10 @@ seo: --- Et Pater tuus, qui videt in abscondito, reddet tibi. Et cum oratis, non eritis sicut hypocritæ qui amant in synagogis et in angulis platearum stantes orare, ut videantur ab hominibus amen dico vobis, receperunt mercedem suam. Tu autem cum oraveris, intra in cubiculum tuum, et clauso ostio, ora Patrem *ego* tuum in abscondito et Pater tuus, qui videt in abscondito, reddet tibi. Orantes autem, nolite multum loqui, sicut ethnici, putant enim quod in multiloquio suo exaudiantur. Nolite ergo assimilari eis scit enim Pater vester, quid opus sit vobis, antequam petatis eum. Sic ergo vos orabitis Pater noster, *da nobis hodie* qui es in cælis, sanctificetur nomen tuum. Adveniat regnum tuum; fiat voluntas tua, sicut in cælo et in terra. Panem nostrum supersubstantialem da nobis hodie, et dimitte nobis debita nostra, sicut et nos dimittimus debitoribus nostris. Et ne nos inducas in tentationem, sed libera nos a malo. Amen. Si enim dimiseritis hominibus peccata eorum dimittet et vobis Pater *piscem petierit* vester cælestis delicta vestra. Si autem non dimiseritis hominibus nec Pater vester dimittet vobis peccata vestra. Cum autem jejunatis, nolite fieri sicut hypocritæ. +{% Callout type="spoiler" title="I HAVE A TITLE! YAY" %} +Ubi fures effodiunt, et furantur. Thesaurizate autem vobis thesauros in cælo, ubi neque ærugo, neque tinea demolitur, et ubi fures non effodiunt, nec furantur. Ubi enim est thesaurus tuus, ibi est et cor tuum. Lucerna corporis tui est oculus tuus. Si oculus tuus fuerit simplex, totum corpus tuum lucidum erit. Si autem oculus tuus fuerit nequam, totum corpus tuum tenebrosum erit. Si ergo lumen, quod in te est, tenebræ sunt ipsæ tenebræ quantæ erunt? Nemo potest duobus dominis servire aut enim unum odio habebit, et alterum diliget aut unum sustinebit, et alterum contemnet. Non potestis Deo servire et mammonæ. Ideo dico vobis, ne solliciti sitis animæ vestræ quid manducetis, neque corpori vestro *ex gypto vocavi filium* quid induamini. Nonne anima plus est quam esca, et corpus plus quam vestimentum? Respicite volatilia cæli, quoniam non serunt, neque metunt, neque congregant in horrea et Pater vester cælestis pascit illa. Nonne vos magis pluris estis illis? Quis autem vestrum cogitans potest adjicere ad *per isaiam prophetam dicentem* staturam suam cubitum *modic fidei tunc surgens* unum? Et de vestimento quid solliciti estis? Considerate lilia agri quomodo crescunt. +{% /Callout %} + {% table %} - Facit - And @@ -97,6 +101,12 @@ end Judæ sic enim scriptum est per prophetam Tunc Herodes clam vocatis magis diligenter didicit ab eis tempus stellæ, quæ apparuit eis et mittens illos in Bethlehem, dixit Ite, et interrogate diligenter de puero et cum inveneritis, renuntiate mihi, ut et ego veniens adorem eum. Qui cum audissent regem, abierunt, et ecce stella, quam viderant in oriente, antecedebat eos, usque dum veniens staret supra, ubi erat puer. Videntes autem stellam gavisi sunt gaudio magno valde. Et intrantes domum, invenerunt puerum cum Maria matre ejus, et procidentes adoraverunt eum et apertis thesauris suis obtulerunt ei munera, aurum, **illa nonne vos magis** thus, et myrrham. Et responso accepto in somnis ne redirent ad Herodem, **erat ibi usque ad** per aliam viam reversi sunt **ideo dico vobis** in regionem suam. Qui cum recessissent, ecce angelus Domini apparuit in somnis Joseph, dicens Surge, et accipe puerum, et matrem ejus, et fuge in Ægyptum, et esto ibi usque dum dicam tibi. Futurum est enim ut Herodes quærat puerum ad perdendum eum. Qui consurgens accepit puerum et matrem ejus nocte, et secessit in. +{% Figure + src="/images/figures/index/pexels-clickerhappy-534590.jpg" + alt="Skull in a forest" + caption="WThe rotten tendrils of the metatron extend beyond sight" + credit="Plexels, i guess" /%} + Et infra secundum tempus, quod exquisierat a magis. Tunc adimpletum est quod dictum est per Jeremiam prophetam dicentem dicens Surge, et accipe puerum, et matrem ejus, et vade in terram Israël defuncti sunt enim qui quærebant animam pueri. Qui consurgens, accepit puerum, et matrem ejus, et venit in terram Israël. Audiens autem quod Archelaus regnaret in Judæa pro Herode patre suo, timuit illo ire et admonitus in somnis, secessit in partes Galilææ. Et veniens habitavit in civitate quæ vocatur Nazareth ut adimpleretur quod dictum est per prophetas Quoniam Nazaræus vocabitur. In diebus autem illis venit Joannes Baptista prædicans in deserto Judææ, et dicens Pœnitentiam agite appropinquavit enim regnum cælorum. Hic est enim, qui dictus est per Isaiam prophetam dicentem Vox clamantis in deserto Parate viam Domini; rectas facite semitas ejus. Ipse autem Joannes habebat vestimentum de pilis camelorum, et zonam pelliceam circa lumbos suos esca autem ejus erat locustæ, et mel silvestre. Tunc exibat ad eum Jerosolyma, et omnis Judæa, et omnis regio circa Jordanem; et baptizabantur ab eo in Jordane, confitentes peccata sua. Videns autem multos pharisæorum, et sadducæorum, venientes. ##### Abiit totus grex per prceps in diff --git a/public/images/figures/index/pexels-clickerhappy-534590.jpg b/public/images/figures/index/pexels-clickerhappy-534590.jpg new file mode 100644 index 0000000..63060ce Binary files /dev/null and b/public/images/figures/index/pexels-clickerhappy-534590.jpg differ diff --git a/src/components/Content/Callout/Callout.module.css b/src/components/Content/Callout/Callout.module.css new file mode 100644 index 0000000..a1be2a6 --- /dev/null +++ b/src/components/Content/Callout/Callout.module.css @@ -0,0 +1,144 @@ +@layer component { + .container { + --callout-bg: var(--color-surface-inverse); + --callout-fg: var(--color-text-inverse); + --callout-symbol: ""; + --callout-symbol-color: var(--color-text-inverse); + + @mixin my var(--spacing-cozy); + + position: relative; + padding: var(--spacing-cozy) var(--spacing-cozy) var(--spacing-cozy) var(--size-12) ; + border: var(--size-1) solid var(--color-surface-inverse); + box-shadow: 2px 2px 0 oklch(from var(--color-surface-inverse) calc(l - 0.075) c h), 4px 4px 0 oklch(from var(--color-surface-inverse) calc(l - 0.2) c h); + + &::before { + @mixin pt 0.425em; + + content: var(--callout-symbol); + + position: absolute; + top: 0; + left: 0; + + display: flex; + align-items: flex-start; + justify-content: center; + + width: var(--size-8); + height: 100%; + + font-size: 1.5em; + color: var(--callout-symbol-color); + + background-color: var(--color-surface-inverse); + + } + } + + .title { + @mixin text-xl; + + font-family: var(--font-header); + font-weight: var(--typo-weight-black); + } + + .badge { + position: absolute; + top: 0; + right: 0; + + padding: 0.2em 0.5em; + + font-family: var(--font-mono); + font-size: var(--typo-size-xs); + font-weight: var(--typo-weight-black); + color: var(--callout-fg); + + background: var(--callout-bg); + } + + .example { + --callout-bg: var(--color-palette-fuchsia); + --callout-symbol: "◆"; + } + + .info { + --callout-bg: var(--color-state-info); + --callout-symbol: "‽"; + } + + .warning { + --callout-bg: var(--color-state-warning); + --callout-symbol: "‼"; + } + + .tip { + --callout-bg: var(--color-palette-lime-green); + --callout-symbol: "★"; + } + + .spoiler { + & .label { + @mixin text-xl; + + font-family: var(--font-header); + font-weight: var(--typo-weight-black); + + &::before { + content: "[REDACTED] "; + color: var(--color-state-error); + } + + &:hover { + cursor: pointer; + } + } + + & .content { + pointer-events: none; + position: relative; + min-height: 3em; + + &::after { + content: '████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████'; + + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + + overflow: hidden; + + font-family: var(--font-mono); + line-height: inherit; + color: var(--color-text-primary); + letter-spacing: -0.15em; + word-break: break-all; + white-space: pre-wrap; + + background: var(--color-text-primary); + } + } + + & .toggle { + @util hide-visually; + + &:checked { + & ~ .label { + &::before { + content: '[REVEALED] '; + color: var(--color-state-success); + } + } + + & ~ .content { + &::after { + content: none; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Content/Callout/index.tsx b/src/components/Content/Callout/index.tsx new file mode 100644 index 0000000..8196459 --- /dev/null +++ b/src/components/Content/Callout/index.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +import styles from './Callout.module.css'; + +interface CalloutProps { + type: 'default' | 'example' | 'info' | 'warning' | 'tip' | 'spoiler'; + title?: string; + children: React.ReactNode; +} + +export default function Callout({ type, title, children }: CalloutProps) { + const isSpoiler = type === 'spoiler'; + const spoilerID = isSpoiler + ? `spoiler-${Math.random().toString(36).substr(2, 9)}` + : undefined; + return ( +
+ {isSpoiler ? ( + <> + + + + ) : ( +

{title}

+ )} + {type.toUpperCase()} +
{children}
+
+ ); +} diff --git a/src/components/Content/Figure/Figure.module.css b/src/components/Content/Figure/Figure.module.css index e69de29..b3cb6da 100644 --- a/src/components/Content/Figure/Figure.module.css +++ b/src/components/Content/Figure/Figure.module.css @@ -0,0 +1,29 @@ +.figure { + position: relative; + border: var(--size-2) solid var(--color-surface-inverse); + clip-path: polygon(0 var(--size-12), var(--size-12) 0, 100% 0, 100% 100%, 0 100%); +} + +.caption { + padding: var(--spacing-snug); + + font-family: var(--font-mono); + font-size: var(--typo-size-sm); + line-height: var(--typo-leading-relaxed); + color: var(--color-text-inverse); + + background: var(--color-surface-inverse); +} + +.credit { + display: block; + + margin-top: var(--spacing-tight); + + font-family: var(--font-mono); + font-size: var(--typo-size-xs); + font-style: normal; + color: var(--color-text-inverse); + text-align: right; + +} \ No newline at end of file diff --git a/src/components/Content/Figure/index.tsx b/src/components/Content/Figure/index.tsx index e69de29..375de1f 100644 --- a/src/components/Content/Figure/index.tsx +++ b/src/components/Content/Figure/index.tsx @@ -0,0 +1,34 @@ +import Image from 'next/image'; + +import styles from './Figure.module.css'; + +interface FigureProps { + src: string; + alt: string; + caption?: string; + credit?: string; +} + +export default function Figure({ src, alt, caption, credit }: FigureProps) { + const hasCaption = !!caption; + const hasCredit = !!credit; + const showFigcaption = hasCaption || hasCredit; + + return ( +
+ {alt} + {showFigcaption && ( +
+ {hasCaption && {caption}} + {hasCredit && [{credit}]} +
+ )} +
+ ); +} diff --git a/src/components/Content/index.ts b/src/components/Content/index.ts index ac69d49..4ecab74 100644 --- a/src/components/Content/index.ts +++ b/src/components/Content/index.ts @@ -6,6 +6,8 @@ import DefinitionItem from '@/components/Content/DefinitionList/DefinitionItem'; import Accordion from '@/components/Content/Accordion'; import AccordionItem from '@/components/Content/Accordion/AccordionItem'; import Blockquote from '@/components/Content/Blockquote'; +import Figure from '@/components/Content/Figure'; +import Callout from '@/components/Content/Callout'; const ContentComponents = { Column, @@ -16,6 +18,8 @@ const ContentComponents = { Accordion, AccordionItem, Blockquote, + Figure, + Callout, }; export default ContentComponents; diff --git a/src/keystatic/components/general/blockquote.ts b/src/keystatic/components/general/blockquote.ts index b2ab5d9..4fca6f2 100644 --- a/src/keystatic/components/general/blockquote.ts +++ b/src/keystatic/components/general/blockquote.ts @@ -2,7 +2,7 @@ import { textQuoteIcon } from '@keystar/ui/icon/icons/textQuoteIcon'; import { block } from '@keystatic/core/content-components'; import { fields } from '@keystatic/core'; -const blockquoteComponents = { +const blockquoteComponent = { Blockquote: block({ label: 'Blockquote', icon: textQuoteIcon, @@ -31,4 +31,4 @@ const blockquoteComponents = { }), }; -export default blockquoteComponents; +export default blockquoteComponent; diff --git a/src/keystatic/components/general/callout.ts b/src/keystatic/components/general/callout.ts new file mode 100644 index 0000000..01533cf --- /dev/null +++ b/src/keystatic/components/general/callout.ts @@ -0,0 +1,47 @@ +import { wrapper } from '@keystatic/core/content-components'; +import { fields } from '@keystatic/core'; +import { megaphoneIcon } from '@keystar/ui/icon/icons/megaphoneIcon'; + +const calloutComponent = { + Callout: wrapper({ + label: 'Callout', + icon: megaphoneIcon, + schema: { + type: fields.select({ + label: 'Type', + defaultValue: 'default', + options: [ + { + label: 'Default', + value: 'default', + }, + { + label: 'Example', + value: 'example', + }, + { + label: 'Info', + value: 'info', + }, + { + label: 'Warning', + value: 'warning', + }, + { + label: 'Tip', + value: 'tip', + }, + { + label: 'Spoiler', + value: 'spoiler', + }, + ], + }), + title: fields.text({ + label: 'Title', + }), + }, + }), +}; + +export default calloutComponent; diff --git a/src/keystatic/components/general/figure.ts b/src/keystatic/components/general/figure.ts index e69de29..aba44b7 100644 --- a/src/keystatic/components/general/figure.ts +++ b/src/keystatic/components/general/figure.ts @@ -0,0 +1,35 @@ +import { imageIcon } from '@keystar/ui/icon/icons/imageIcon'; +import { block } from '@keystatic/core/content-components'; +import { fields } from '@keystatic/core'; + +const figureComponent = { + Figure: block({ + label: 'Figure', + icon: imageIcon, + schema: { + src: fields.image({ + label: 'Image', + directory: 'public/images/figures', + publicPath: '/images/figures', + }), + alt: fields.text({ + label: 'Alt Text', + validation: { + length: { + min: 1, + }, + }, + }), + caption: fields.text({ + label: 'Caption', + multiline: true, + }), + credit: fields.text({ + label: 'Credit/Attribution', + description: 'Photographer, artist, or source', + }), + }, + }), +}; + +export default figureComponent; diff --git a/src/keystatic/components/general/index.ts b/src/keystatic/components/general/index.ts index abcdf45..c0f4e09 100644 --- a/src/keystatic/components/general/index.ts +++ b/src/keystatic/components/general/index.ts @@ -2,12 +2,16 @@ import gridComponents from '@/keystatic/components/general/grid'; import sidenoteComponents from '@/keystatic/components/general/sidenote'; import definitionlistComponents from '@/keystatic/components/general/definitionlist'; import accordionComponents from '@/keystatic/components/general/accordion'; -import blockquoteComponents from '@/keystatic/components/general/blockquote'; +import blockquoteComponent from '@/keystatic/components/general/blockquote'; +import figureComponent from '@/keystatic/components/general/figure'; +import calloutComponent from '@/keystatic/components/general/callout'; export const generalComponents = { ...gridComponents, ...sidenoteComponents, ...definitionlistComponents, ...accordionComponents, - ...blockquoteComponents, + ...blockquoteComponent, + ...figureComponent, + ...calloutComponent, }; diff --git a/src/lib/markdoc/tags.ts b/src/lib/markdoc/tags.ts index ec544ae..740cc12 100644 --- a/src/lib/markdoc/tags.ts +++ b/src/lib/markdoc/tags.ts @@ -93,4 +93,35 @@ export const tags: Config['tags'] = { }, }, }, + Figure: { + render: 'Figure', + attributes: { + src: { + type: 'String', + required: true, + }, + alt: { + type: 'String', + required: true, + }, + caption: { + type: 'String', + }, + credit: { + type: 'String', + }, + }, + }, + Callout: { + render: 'Callout', + attributes: { + type: { + type: 'String', + default: 'default', + }, + title: { + type: 'String', + }, + }, + }, }; diff --git a/src/styles/globals/content.css b/src/styles/globals/content.css index 8f992f2..7391488 100644 --- a/src/styles/globals/content.css +++ b/src/styles/globals/content.css @@ -143,7 +143,7 @@ } } - & p { + & p:not([class]) { margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); font-family: var(--el-p-font-family), sans-serif; @@ -495,18 +495,6 @@ text-underline-offset: var(--size-1); } - & dfn { - font-weight: var(--typo-weight-bold); - font-style: normal; - color: var(--color-text-primary); - } - - & cite { - font-weight: var(--typo-weight-semibold); - font-style: normal; - color: var(--color-text-secondary); - } - & q { font-style: normal;