@janga/norna 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -16
- package/bin/norna-cli.mjs +12 -7
- package/docs/README.md +10 -11
- package/docs/commands.md +8 -8
- package/docs/configuration.md +13 -145
- package/docs/content.md +17 -15
- package/docs/design/command-organization.md +55 -55
- package/docs/design/site-examples-structure.md +2 -2
- package/docs/engine-development.md +5 -5
- package/docs/getting-started.md +19 -26
- package/docs/images-and-metadata.md +1 -1
- package/docs/local-development.md +2 -2
- package/docs/publishing.md +1 -1
- package/docs/routes.md +2 -2
- package/docs/site-structure.md +8 -7
- package/docs/theme.md +149 -7
- package/docs/typography.md +47 -28
- package/examples/dog-gallery/.astro/collections/site.schema.json +802 -0
- package/examples/dog-gallery/.astro/collections/theme.schema.json +714 -0
- package/examples/dog-gallery/.astro/content-assets.mjs +4 -0
- package/examples/dog-gallery/.astro/content-modules.mjs +1 -0
- package/examples/dog-gallery/.astro/content.d.ts +175 -0
- package/examples/dog-gallery/.astro/data-store.json +1 -0
- package/examples/dog-gallery/.astro/dev-local.json +8 -0
- package/examples/dog-gallery/.astro/dev.json +13 -0
- package/examples/dog-gallery/.astro/dev.log +49 -0
- package/examples/dog-gallery/.astro/settings.json +5 -0
- package/examples/dog-gallery/.astro/types.d.ts +2 -0
- package/examples/dog-gallery/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +1 -0
- package/examples/dog-gallery/dist/_astro/SitePage.BFHZm5UG.css +1 -0
- package/examples/dog-gallery/dist/dog-care/index.html +15 -0
- package/examples/dog-gallery/dist/favicon.svg +7 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-960.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-3939.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-2400.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1600.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-2576.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1277.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-768.webp +0 -0
- package/examples/dog-gallery/dist/index.html +43 -0
- package/examples/dog-gallery/dist/robots.txt +2 -0
- package/examples/dog-gallery/node_modules/.vite/deps/_metadata.json +74 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro-D_GIpJIE.js +434 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro-D_GIpJIE.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/audit-DM9Hkl5B.js +1534 -0
- package/examples/dog-gallery/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/highlight-DnZ1ULOL.js +48 -0
- package/examples/dog-gallery/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/icons-RyebKi45.js +42 -0
- package/examples/dog-gallery/node_modules/.vite/deps/icons-RyebKi45.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/package.json +3 -0
- package/examples/dog-gallery/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/examples/dog-gallery/node_modules/.vite/deps/settings-DaU-gNnK.js +190 -0
- package/examples/dog-gallery/node_modules/.vite/deps/settings-DaU-gNnK.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/toolbar-63PA619H.js +458 -0
- package/examples/dog-gallery/node_modules/.vite/deps/toolbar-63PA619H.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/ui-library--bkcNSYz.js +1016 -0
- package/examples/dog-gallery/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/window-jPkpKVcy.js +32 -0
- package/examples/dog-gallery/node_modules/.vite/deps/window-jPkpKVcy.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/xray-BXCHpEJP.js +111 -0
- package/examples/dog-gallery/node_modules/.vite/deps/xray-BXCHpEJP.js.map +1 -0
- package/examples/dog-gallery/site/config.mjs +12 -42
- package/examples/dog-gallery/site/content.md +27 -5
- package/examples/dog-gallery/site/routes/dog-care/route-content.md +17 -3
- package/examples/dog-gallery/site/theme.md +85 -26
- package/fixtures/basic/site/config.mjs +2 -22
- package/fixtures/basic/site/content.md +1 -1
- package/fixtures/basic/site/theme.md +7 -3
- package/package.json +3 -3
- package/scripts/check-config.mjs +3 -3
- package/scripts/deploy-site.mjs +3 -3
- package/scripts/init-site.mjs +10 -8
- package/scripts/lib/frontmatter-yaml.mjs +85 -0
- package/scripts/lib/presentation.mjs +10 -11
- package/scripts/lib/project-config.mjs +91 -45
- package/scripts/lib/site-content.mjs +20 -2
- package/scripts/lib/theme-config.mjs +34 -0
- package/scripts/lib/typography.mjs +100 -20
- package/scripts/show-typography.mjs +58 -154
- package/scripts/sync-content-sections.mjs +6 -6
- package/scripts/test-content-check.mjs +3 -4
- package/scripts/test-engine-commands.mjs +2 -2
- package/scripts/test-package-check.mjs +17 -16
- package/scripts/test-temporary-visibility.mjs +2 -3
- package/src/components/SitePage.astro +2 -3
- package/src/components/SiteSection.astro +39 -5
- package/src/content.config.ts +60 -2
- package/src/layouts/BaseLayout.astro +17 -0
- package/src/styles/global.css +54 -50
- package/starters/basic/README.md +10 -15
- package/starters/basic/package.json +2 -2
- package/starters/basic/site/config.mjs +3 -24
- package/starters/basic/site/content.md +40 -7
- package/starters/basic/site/theme.md +110 -17
- package/starters/project/.github/workflows/deploy.yml +65 -0
- package/starters/project/README.md +72 -0
- package/starters/project/package-lock.json +4296 -0
- package/starters/project/package.json +35 -0
- package/starters/project/site/config.mjs +43 -0
- package/starters/project/site/content.md +88 -0
- package/starters/project/site/public/robots.txt +2 -0
- package/starters/project/site/routes/guide/route-content.md +58 -0
- package/starters/project/site/theme.md +15 -0
|
@@ -32,6 +32,9 @@ interface Props {
|
|
|
32
32
|
|
|
33
33
|
const { section, pagePresentation, headingLevel, priorityGalleryImage = false } = Astro.props;
|
|
34
34
|
const HeadingTag = headingLevel === 1 ? 'h1' : 'h2';
|
|
35
|
+
// Sections are authored with Markdown ## headings even when the first one renders as HTML h1.
|
|
36
|
+
const sectionHeadingVisualLevel = 'h2';
|
|
37
|
+
type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4';
|
|
35
38
|
const headingSizeValues: Record<TextSize, ResponsiveValue<string>> = {
|
|
36
39
|
small: {
|
|
37
40
|
desktop: 'clamp(1.1rem, 1.02rem + 0.35vw, 1.35rem)',
|
|
@@ -97,10 +100,26 @@ const textColor = sectionOverride?.textColor
|
|
|
97
100
|
?? pagePresentation.textColor;
|
|
98
101
|
const resolvedTypography = resolveTypographyOverride(pagePresentation.typography, sectionOverride?.typography);
|
|
99
102
|
const typography = resolvedTypography.values;
|
|
100
|
-
const
|
|
103
|
+
const heading = typography.headings[sectionHeadingVisualLevel] as {
|
|
104
|
+
align: ResponsiveValue<TextAlign>;
|
|
105
|
+
size: TextSize;
|
|
106
|
+
lineHeight: number;
|
|
107
|
+
spacing: string;
|
|
108
|
+
};
|
|
109
|
+
const markdownHeadingLevels = ['h3', 'h4'] as const;
|
|
110
|
+
const markdownHeadings = Object.fromEntries(markdownHeadingLevels.map((level) => [
|
|
111
|
+
level,
|
|
112
|
+
typography.headings[level] as {
|
|
113
|
+
align: ResponsiveValue<TextAlign>;
|
|
114
|
+
size: TextSize;
|
|
115
|
+
lineHeight: number;
|
|
116
|
+
spacing: string;
|
|
117
|
+
},
|
|
118
|
+
]));
|
|
119
|
+
const headingAlign = heading.align;
|
|
101
120
|
const bodyAlign = typography.body.align as ResponsiveValue<TextAlign>;
|
|
102
121
|
const captionAlign = typography.caption.align as ResponsiveValue<TextAlign>;
|
|
103
|
-
const headingFontSize = getSizeValue(headingSizeValues,
|
|
122
|
+
const headingFontSize = getSizeValue(headingSizeValues, heading.size);
|
|
104
123
|
const bodyFontSize = getSizeValue(bodySizeValues, typography.body.size as TextSize);
|
|
105
124
|
const captionFontSize = getSizeValue(captionSizeValues, typography.caption.size as TextSize);
|
|
106
125
|
const justifyByAlign: Record<TextAlign, string> = {
|
|
@@ -118,6 +137,19 @@ const getAlignedTextWidth = (
|
|
|
118
137
|
const headingWidth = getAlignedTextWidth(headingAlign, '760px');
|
|
119
138
|
const bodyWidth = getAlignedTextWidth(bodyAlign, 'var(--text-width)');
|
|
120
139
|
const hasGallery = section.gallery.length > 0;
|
|
140
|
+
const markdownHeadingStyle = (level: 'h3' | 'h4') => {
|
|
141
|
+
const headingConfig = markdownHeadings[level];
|
|
142
|
+
const fontSize = getSizeValue(headingSizeValues, headingConfig.size);
|
|
143
|
+
|
|
144
|
+
return [
|
|
145
|
+
`--section-markdown-${level}-align-desktop: ${headingConfig.align.desktop}`,
|
|
146
|
+
`--section-markdown-${level}-align-mobile: ${headingConfig.align.mobile}`,
|
|
147
|
+
`--section-markdown-${level}-font-size-desktop: ${fontSize.desktop}`,
|
|
148
|
+
`--section-markdown-${level}-font-size-mobile: ${fontSize.mobile}`,
|
|
149
|
+
`--section-markdown-${level}-line-height: ${headingConfig.lineHeight}`,
|
|
150
|
+
`--section-markdown-${level}-spacing: ${headingConfig.spacing}`,
|
|
151
|
+
];
|
|
152
|
+
};
|
|
121
153
|
const sectionStyle = [
|
|
122
154
|
`--section-background-color: ${backgroundColor}`,
|
|
123
155
|
`--section-text-color: ${textColor}`,
|
|
@@ -125,10 +157,12 @@ const sectionStyle = [
|
|
|
125
157
|
`--section-heading-align-mobile: ${headingAlign.mobile}`,
|
|
126
158
|
`--section-heading-font-size-desktop: ${headingFontSize.desktop}`,
|
|
127
159
|
`--section-heading-font-size-mobile: ${headingFontSize.mobile}`,
|
|
128
|
-
`--section-heading-line-height: ${
|
|
129
|
-
`--section-heading-spacing: ${
|
|
160
|
+
`--section-heading-line-height: ${heading.lineHeight}`,
|
|
161
|
+
`--section-heading-spacing: ${heading.spacing}`,
|
|
130
162
|
`--section-heading-width-desktop: ${headingWidth.desktop}`,
|
|
131
163
|
`--section-heading-width-mobile: ${headingWidth.mobile}`,
|
|
164
|
+
...markdownHeadingStyle('h3'),
|
|
165
|
+
...markdownHeadingStyle('h4'),
|
|
132
166
|
`--section-body-align-desktop: ${bodyAlign.desktop}`,
|
|
133
167
|
`--section-body-align-mobile: ${bodyAlign.mobile}`,
|
|
134
168
|
`--section-body-font-size-desktop: ${bodyFontSize.desktop}`,
|
|
@@ -150,7 +184,7 @@ const sectionStyle = [
|
|
|
150
184
|
|
|
151
185
|
<section
|
|
152
186
|
id={section.id}
|
|
153
|
-
class
|
|
187
|
+
class="site-section"
|
|
154
188
|
data-section-title={section.title}
|
|
155
189
|
style={sectionStyle}
|
|
156
190
|
>
|
package/src/content.config.ts
CHANGED
|
@@ -25,6 +25,12 @@ const cssLength = z.string().regex(
|
|
|
25
25
|
/^(?:0|(?:\d+(?:\.\d+)?|\.\d+)(?:px|rem|em|ch|lh))$/,
|
|
26
26
|
'Use a CSS length such as "0", "0.8em", "1rem", or "12px".',
|
|
27
27
|
);
|
|
28
|
+
const visualCssLengthUnit = String.raw`(?:px|rem|em|vw|vh|vmin|vmax|ch|%)`;
|
|
29
|
+
const visualCssLengthValue = String.raw`(?:\d+(?:\.\d+)?|\.\d+)${visualCssLengthUnit}`;
|
|
30
|
+
const visualCssLength = z.string().regex(
|
|
31
|
+
new RegExp(`^(?:0|${visualCssLengthValue}|clamp\\(\\s*${visualCssLengthValue}\\s*,\\s*${visualCssLengthValue}\\s*,\\s*${visualCssLengthValue}\\s*\\))$`),
|
|
32
|
+
'Use a CSS length such as "0", "900px", "56rem", "90%", or "clamp(1rem, 4vw, 3rem)".',
|
|
33
|
+
);
|
|
28
34
|
const inlineStyleName = z.string().regex(/^[a-z][a-z0-9-]*$/);
|
|
29
35
|
const dateOnly = z.string()
|
|
30
36
|
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Use YYYY-MM-DD format.')
|
|
@@ -55,6 +61,12 @@ const headingPresentationOverride = z.object({
|
|
|
55
61
|
...commonTextPresentationOverride,
|
|
56
62
|
spacing: cssLength.optional(),
|
|
57
63
|
}).strict();
|
|
64
|
+
const headingLevelsPresentationOverride = z.object({
|
|
65
|
+
h1: headingPresentationOverride.optional(),
|
|
66
|
+
h2: headingPresentationOverride.optional(),
|
|
67
|
+
h3: headingPresentationOverride.optional(),
|
|
68
|
+
h4: headingPresentationOverride.optional(),
|
|
69
|
+
}).strict();
|
|
58
70
|
const bodyPresentationOverride = z.object({
|
|
59
71
|
...commonTextPresentationOverride,
|
|
60
72
|
paragraphSpacing: cssLength.optional(),
|
|
@@ -64,7 +76,7 @@ const captionPresentationOverride = z.object({
|
|
|
64
76
|
spacing: cssLength.optional(),
|
|
65
77
|
}).strict();
|
|
66
78
|
const typographyOverrides = z.object({
|
|
67
|
-
|
|
79
|
+
headings: headingLevelsPresentationOverride.optional(),
|
|
68
80
|
body: bodyPresentationOverride.optional(),
|
|
69
81
|
caption: captionPresentationOverride.optional(),
|
|
70
82
|
}).strict();
|
|
@@ -75,6 +87,50 @@ const typography = z.object({
|
|
|
75
87
|
(value) => value.preset !== undefined || value.overrides !== undefined,
|
|
76
88
|
'Specify preset, overrides, or both.',
|
|
77
89
|
);
|
|
90
|
+
const themeTypography = z.object({
|
|
91
|
+
fontFamily: z.string()
|
|
92
|
+
.min(1)
|
|
93
|
+
.refine((value) => !/[\n\r;{}]/.test(value), 'Do not use semicolons, braces, or line breaks.').optional(),
|
|
94
|
+
preset: typographyPreset.optional(),
|
|
95
|
+
overrides: typographyOverrides.optional(),
|
|
96
|
+
}).strict().refine(
|
|
97
|
+
(value) => value.fontFamily !== undefined || value.preset !== undefined || value.overrides !== undefined,
|
|
98
|
+
'Specify fontFamily, preset, overrides, or both.',
|
|
99
|
+
);
|
|
100
|
+
const responsiveCssLength = z.union([
|
|
101
|
+
visualCssLength,
|
|
102
|
+
z.object({
|
|
103
|
+
desktop: visualCssLength,
|
|
104
|
+
mobile: visualCssLength,
|
|
105
|
+
}).strict(),
|
|
106
|
+
]);
|
|
107
|
+
const responsivePercent = z.union([
|
|
108
|
+
z.number().positive().max(100),
|
|
109
|
+
z.object({
|
|
110
|
+
desktop: z.number().positive().max(100),
|
|
111
|
+
mobile: z.number().positive().max(100),
|
|
112
|
+
}).strict(),
|
|
113
|
+
]);
|
|
114
|
+
const themeLayoutSpacing = z.object({
|
|
115
|
+
bodyToImages: responsiveCssLength.optional(),
|
|
116
|
+
finalSectionBottom: responsiveCssLength.optional(),
|
|
117
|
+
firstSectionTop: responsiveCssLength.optional(),
|
|
118
|
+
imageGap: responsiveCssLength.optional(),
|
|
119
|
+
sectionGap: responsiveCssLength.optional(),
|
|
120
|
+
sectionHeadingToBody: responsiveCssLength.optional(),
|
|
121
|
+
subheadingRuleTop: responsiveCssLength.optional(),
|
|
122
|
+
subheadingTop: responsiveCssLength.optional(),
|
|
123
|
+
}).strict();
|
|
124
|
+
const themeLayout = z.object({
|
|
125
|
+
pageWidth: visualCssLength.optional(),
|
|
126
|
+
gutter: responsiveCssLength.optional(),
|
|
127
|
+
spacing: themeLayoutSpacing.optional(),
|
|
128
|
+
}).strict();
|
|
129
|
+
const themeGallery = z.object({
|
|
130
|
+
width: visualCssLength.optional(),
|
|
131
|
+
maxAvailableWidthPercent: responsivePercent.optional(),
|
|
132
|
+
maxAvailableHeightPercent: responsivePercent.optional(),
|
|
133
|
+
}).strict();
|
|
78
134
|
const sectionPresentationOverride = z.object({
|
|
79
135
|
backgroundColor: colorValue.optional(),
|
|
80
136
|
textColor: colorValue.optional(),
|
|
@@ -86,7 +142,6 @@ const themePresentation = z.object({
|
|
|
86
142
|
inlineStyles: z.record(inlineStyleName, z.object({
|
|
87
143
|
color: colorValue,
|
|
88
144
|
}).strict()).optional(),
|
|
89
|
-
typography: typography.optional(),
|
|
90
145
|
}).strict();
|
|
91
146
|
const pagePresentation = z.object({
|
|
92
147
|
backgroundColor: colorValue.optional(),
|
|
@@ -141,6 +196,9 @@ const siteSchema = z.object({
|
|
|
141
196
|
|
|
142
197
|
const themeSchema = z.object({
|
|
143
198
|
navigation: themeNavigation.optional(),
|
|
199
|
+
layout: themeLayout.optional(),
|
|
200
|
+
gallery: themeGallery.optional(),
|
|
201
|
+
typography: themeTypography.optional(),
|
|
144
202
|
presentation: themePresentation.optional(),
|
|
145
203
|
frame: frame.optional(),
|
|
146
204
|
}).strict();
|
|
@@ -29,12 +29,29 @@ const iconLinks = getIconLinks();
|
|
|
29
29
|
const scrollBehavior = projectConfig.navigation.smoothScroll.enabled ? 'smooth' : 'auto';
|
|
30
30
|
const formatPercent = (value: number) => `${value}%`;
|
|
31
31
|
const formatViewportHeightPercent = (value: number) => `${value}svh`;
|
|
32
|
+
const layoutSpacing = projectConfig.layout.spacing;
|
|
32
33
|
const documentStyle = [
|
|
33
34
|
`scroll-behavior: ${scrollBehavior}`,
|
|
34
35
|
`--font-sans: ${projectConfig.typography.fontFamily}`,
|
|
35
36
|
`--page-width: ${projectConfig.layout.pageWidth}`,
|
|
36
37
|
`--content-gutter-desktop: ${projectConfig.layout.gutter.desktop}`,
|
|
37
38
|
`--content-gutter-mobile: ${projectConfig.layout.gutter.mobile}`,
|
|
39
|
+
`--space-nav-to-first-section-desktop: ${layoutSpacing.firstSectionTop.desktop}`,
|
|
40
|
+
`--space-nav-to-first-section-mobile: ${layoutSpacing.firstSectionTop.mobile}`,
|
|
41
|
+
`--space-section-title-to-body-desktop: ${layoutSpacing.sectionHeadingToBody.desktop}`,
|
|
42
|
+
`--space-section-title-to-body-mobile: ${layoutSpacing.sectionHeadingToBody.mobile}`,
|
|
43
|
+
`--space-section-body-to-gallery-desktop: ${layoutSpacing.bodyToImages.desktop}`,
|
|
44
|
+
`--space-section-body-to-gallery-mobile: ${layoutSpacing.bodyToImages.mobile}`,
|
|
45
|
+
`--space-gallery-item-desktop: ${layoutSpacing.imageGap.desktop}`,
|
|
46
|
+
`--space-gallery-item-mobile: ${layoutSpacing.imageGap.mobile}`,
|
|
47
|
+
`--space-section-to-section-desktop: ${layoutSpacing.sectionGap.desktop}`,
|
|
48
|
+
`--space-section-to-section-mobile: ${layoutSpacing.sectionGap.mobile}`,
|
|
49
|
+
`--space-final-section-bottom-desktop: ${layoutSpacing.finalSectionBottom.desktop}`,
|
|
50
|
+
`--space-final-section-bottom-mobile: ${layoutSpacing.finalSectionBottom.mobile}`,
|
|
51
|
+
`--space-subheading-top-desktop: ${layoutSpacing.subheadingTop.desktop}`,
|
|
52
|
+
`--space-subheading-top-mobile: ${layoutSpacing.subheadingTop.mobile}`,
|
|
53
|
+
`--space-subheading-rule-top-desktop: ${layoutSpacing.subheadingRuleTop.desktop}`,
|
|
54
|
+
`--space-subheading-rule-top-mobile: ${layoutSpacing.subheadingRuleTop.mobile}`,
|
|
38
55
|
`--gallery-width: ${projectConfig.gallery.width}`,
|
|
39
56
|
`--gallery-max-available-width-desktop: ${formatPercent(projectConfig.gallery.maxAvailableWidthPercent.desktop)}`,
|
|
40
57
|
`--gallery-max-available-width-mobile: ${formatPercent(projectConfig.gallery.maxAvailableWidthPercent.mobile)}`,
|
package/src/styles/global.css
CHANGED
|
@@ -28,20 +28,30 @@
|
|
|
28
28
|
--gallery-max-image-height: var(--gallery-max-image-height-desktop);
|
|
29
29
|
--nav-top-safety-inset: 0px;
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
--space-nav-to-first-section:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
--space-section-title-to-body:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--space-section-body-to-gallery:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
--space-gallery-item:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
--space-section-to-section:
|
|
31
|
+
--space-nav-to-first-section-desktop: clamp(1.875rem, 3vw, 2.75rem);
|
|
32
|
+
--space-nav-to-first-section-mobile: 1.375rem;
|
|
33
|
+
--space-nav-to-first-section: var(--space-nav-to-first-section-desktop);
|
|
34
|
+
--space-section-title-to-body-desktop: clamp(0.5625rem, 1.25vw, 0.75rem);
|
|
35
|
+
--space-section-title-to-body-mobile: 0.4375rem;
|
|
36
|
+
--space-section-title-to-body: var(--space-section-title-to-body-desktop);
|
|
37
|
+
--space-section-body-to-gallery-desktop: clamp(1.25rem, 2.5vw, 2rem);
|
|
38
|
+
--space-section-body-to-gallery-mobile: 1.25rem;
|
|
39
|
+
--space-section-body-to-gallery: var(--space-section-body-to-gallery-desktop);
|
|
40
|
+
--space-gallery-item-desktop: clamp(1.5rem, 3.5vw, 2.75rem);
|
|
41
|
+
--space-gallery-item-mobile: 2.75rem;
|
|
42
|
+
--space-gallery-item: var(--space-gallery-item-desktop);
|
|
43
|
+
--space-section-to-section-desktop: clamp(2.55rem, 4.2vw, 3.9rem);
|
|
44
|
+
--space-section-to-section-mobile: 2.25rem;
|
|
45
|
+
--space-section-to-section: var(--space-section-to-section-desktop);
|
|
46
|
+
--space-final-section-bottom-desktop: var(--space-section-to-section-desktop);
|
|
47
|
+
--space-final-section-bottom-mobile: var(--space-section-to-section-mobile);
|
|
48
|
+
--space-final-section-bottom: var(--space-final-section-bottom-desktop);
|
|
49
|
+
--space-subheading-top-desktop: 2rem;
|
|
50
|
+
--space-subheading-top-mobile: 1.6rem;
|
|
51
|
+
--space-subheading-top: var(--space-subheading-top-desktop);
|
|
52
|
+
--space-subheading-rule-top-desktop: 1rem;
|
|
53
|
+
--space-subheading-rule-top-mobile: 0.8rem;
|
|
54
|
+
--space-subheading-rule-top: var(--space-subheading-rule-top-desktop);
|
|
45
55
|
|
|
46
56
|
--content-gutter-desktop: clamp(1.25rem, 4vw, 3rem);
|
|
47
57
|
--content-gutter-mobile: 1rem;
|
|
@@ -316,7 +326,7 @@ a {
|
|
|
316
326
|
}
|
|
317
327
|
|
|
318
328
|
.site-section:last-child {
|
|
319
|
-
padding-bottom: var(--space-section-
|
|
329
|
+
padding-bottom: var(--space-final-section-bottom);
|
|
320
330
|
}
|
|
321
331
|
|
|
322
332
|
.section-card {
|
|
@@ -331,15 +341,15 @@ a {
|
|
|
331
341
|
text-align: var(--section-heading-align-desktop, center);
|
|
332
342
|
}
|
|
333
343
|
|
|
334
|
-
h1,
|
|
335
|
-
h2,
|
|
344
|
+
.section-header h1,
|
|
345
|
+
.section-header h2,
|
|
336
346
|
p,
|
|
337
347
|
ul {
|
|
338
348
|
margin-top: 0;
|
|
339
349
|
}
|
|
340
350
|
|
|
341
|
-
h1,
|
|
342
|
-
h2 {
|
|
351
|
+
.section-header h1,
|
|
352
|
+
.section-header h2 {
|
|
343
353
|
margin-bottom: 0;
|
|
344
354
|
color: inherit;
|
|
345
355
|
font-size: var(--section-heading-font-size-desktop, clamp(1.35rem, 1.1rem + 0.9vw, 2rem));
|
|
@@ -350,11 +360,6 @@ h2 {
|
|
|
350
360
|
overflow-wrap: anywhere;
|
|
351
361
|
}
|
|
352
362
|
|
|
353
|
-
.site-section-primary h1 {
|
|
354
|
-
font-size: var(--section-heading-font-size-desktop, clamp(1.6rem, 1.22rem + 1.45vw, 2.75rem));
|
|
355
|
-
font-weight: 700;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
363
|
.section-body {
|
|
359
364
|
width: 100%;
|
|
360
365
|
margin: 0 auto;
|
|
@@ -389,23 +394,25 @@ h2 {
|
|
|
389
394
|
}
|
|
390
395
|
|
|
391
396
|
.section-markdown h3 {
|
|
392
|
-
margin:
|
|
397
|
+
margin: var(--space-subheading-top) 0 var(--section-markdown-h3-spacing, 0.9rem);
|
|
393
398
|
border-top: 1px solid var(--color-soft);
|
|
394
|
-
padding-top:
|
|
399
|
+
padding-top: var(--space-subheading-rule-top);
|
|
395
400
|
font-family: var(--font-sans);
|
|
396
|
-
font-size: 0.82rem;
|
|
397
|
-
letter-spacing: 0
|
|
398
|
-
line-height: 1.35;
|
|
401
|
+
font-size: var(--section-markdown-h3-font-size-desktop, 0.82rem);
|
|
402
|
+
letter-spacing: 0;
|
|
403
|
+
line-height: var(--section-markdown-h3-line-height, 1.35);
|
|
404
|
+
text-align: var(--section-markdown-h3-align-desktop, left);
|
|
399
405
|
text-transform: uppercase;
|
|
400
406
|
}
|
|
401
407
|
|
|
402
408
|
.section-markdown h4 {
|
|
403
|
-
margin: 0 0 0.85rem;
|
|
409
|
+
margin: 0 0 var(--section-markdown-h4-spacing, 0.85rem);
|
|
404
410
|
color: inherit;
|
|
405
|
-
font-size: clamp(0.96rem, 0.94rem + 0.08vw, 1rem);
|
|
411
|
+
font-size: var(--section-markdown-h4-font-size-desktop, clamp(0.96rem, 0.94rem + 0.08vw, 1rem));
|
|
406
412
|
font-weight: 400;
|
|
407
|
-
letter-spacing: 0
|
|
408
|
-
line-height: 1.5;
|
|
413
|
+
letter-spacing: 0;
|
|
414
|
+
line-height: var(--section-markdown-h4-line-height, 1.5);
|
|
415
|
+
text-align: var(--section-markdown-h4-align-desktop, left);
|
|
409
416
|
}
|
|
410
417
|
|
|
411
418
|
.section-markdown ul,
|
|
@@ -639,11 +646,14 @@ h2 {
|
|
|
639
646
|
|
|
640
647
|
@media (max-width: 700px) {
|
|
641
648
|
:root {
|
|
642
|
-
--space-nav-to-first-section:
|
|
643
|
-
--space-section-title-to-body:
|
|
644
|
-
--space-section-body-to-gallery:
|
|
645
|
-
--space-gallery-item:
|
|
646
|
-
--space-section-to-section:
|
|
649
|
+
--space-nav-to-first-section: var(--space-nav-to-first-section-mobile);
|
|
650
|
+
--space-section-title-to-body: var(--space-section-title-to-body-mobile);
|
|
651
|
+
--space-section-body-to-gallery: var(--space-section-body-to-gallery-mobile);
|
|
652
|
+
--space-gallery-item: var(--space-gallery-item-mobile);
|
|
653
|
+
--space-section-to-section: var(--space-section-to-section-mobile);
|
|
654
|
+
--space-final-section-bottom: var(--space-final-section-bottom-mobile);
|
|
655
|
+
--space-subheading-top: var(--space-subheading-top-mobile);
|
|
656
|
+
--space-subheading-rule-top: var(--space-subheading-rule-top-mobile);
|
|
647
657
|
--content-gutter: var(--content-gutter-mobile);
|
|
648
658
|
--gallery-max-available-width: var(--gallery-max-available-width-mobile);
|
|
649
659
|
--gallery-max-image-height: var(--gallery-max-image-height-mobile);
|
|
@@ -780,21 +790,14 @@ h2 {
|
|
|
780
790
|
line-height: 1.72;
|
|
781
791
|
}
|
|
782
792
|
|
|
783
|
-
h1,
|
|
784
|
-
h2 {
|
|
793
|
+
.section-header h1,
|
|
794
|
+
.section-header h2 {
|
|
785
795
|
font-size: var(
|
|
786
796
|
--section-heading-font-size-mobile,
|
|
787
797
|
var(--section-heading-font-size-desktop, clamp(1.3rem, 1.05rem + 1.35vw, 1.75rem))
|
|
788
798
|
);
|
|
789
799
|
}
|
|
790
800
|
|
|
791
|
-
.site-section-primary h1 {
|
|
792
|
-
font-size: var(
|
|
793
|
-
--section-heading-font-size-mobile,
|
|
794
|
-
var(--section-heading-font-size-desktop, clamp(1.5rem, 1.12rem + 2vw, 2.25rem))
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
801
|
.section-header {
|
|
799
802
|
width: min(100%, var(--section-heading-width-mobile, var(--section-heading-width-desktop, 760px)));
|
|
800
803
|
text-align: var(--section-heading-align-mobile, var(--section-heading-align-desktop, center));
|
|
@@ -819,12 +822,13 @@ h2 {
|
|
|
819
822
|
}
|
|
820
823
|
|
|
821
824
|
.section-markdown h3 {
|
|
822
|
-
|
|
823
|
-
|
|
825
|
+
font-size: var(--section-markdown-h3-font-size-mobile, var(--section-markdown-h3-font-size-desktop, 0.82rem));
|
|
826
|
+
text-align: var(--section-markdown-h3-align-mobile, var(--section-markdown-h3-align-desktop, left));
|
|
824
827
|
}
|
|
825
828
|
|
|
826
829
|
.section-markdown h4 {
|
|
827
|
-
|
|
830
|
+
font-size: var(--section-markdown-h4-font-size-mobile, var(--section-markdown-h4-font-size-desktop, clamp(0.96rem, 0.94rem + 0.08vw, 1rem)));
|
|
831
|
+
text-align: var(--section-markdown-h4-align-mobile, var(--section-markdown-h4-align-desktop, left));
|
|
828
832
|
}
|
|
829
833
|
|
|
830
834
|
.section-markdown ul,
|
package/starters/basic/README.md
CHANGED
|
@@ -6,7 +6,7 @@ This is a minimal site repository starter for `@janga/norna`.
|
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
8
|
npm install
|
|
9
|
-
npm run
|
|
9
|
+
npm run dev
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
If the standard local port is blocked, start with:
|
|
@@ -15,9 +15,9 @@ If the standard local port is blocked, start with:
|
|
|
15
15
|
npm run dev -- --kill
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Edit site-wide
|
|
19
|
-
overrides in `site/content.md`, technical settings such as URL
|
|
20
|
-
|
|
18
|
+
Edit site-wide visual defaults in `site/theme.md`, homepage content and section
|
|
19
|
+
overrides in `site/content.md`, technical settings such as URL and locale
|
|
20
|
+
labels in `site/config.mjs`, source images under
|
|
21
21
|
`site/images/<section-id>/`, and static public files under `site/public/`.
|
|
22
22
|
|
|
23
23
|
Use `site.basePath: '/'` for a custom domain or root-hosted site. For a GitHub
|
|
@@ -32,14 +32,9 @@ site: {
|
|
|
32
32
|
|
|
33
33
|
In GitHub repository settings, configure Pages to build from GitHub Actions.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`gallery.maxAvailableHeightPercent`.
|
|
39
|
-
|
|
40
|
-
The site font is configured with `typography.fontFamily` in `site/config.mjs`.
|
|
41
|
-
Site-wide text presentation is configured with typography presets and overrides
|
|
42
|
-
in `site/theme.md`; page and section overrides live in `site/content.md`.
|
|
35
|
+
Page width, side gutters, vertical spacing, image width, image height limits,
|
|
36
|
+
font, colors, and site-wide typography are configured in `site/theme.md`. Page
|
|
37
|
+
and section presentation overrides live in `site/content.md`.
|
|
43
38
|
|
|
44
39
|
Commit `package-lock.json` after the first install so GitHub Actions can use
|
|
45
40
|
`npm ci`.
|
|
@@ -54,9 +49,9 @@ npm run norna:typography:show
|
|
|
54
49
|
npm run norna:build
|
|
55
50
|
```
|
|
56
51
|
|
|
57
|
-
This keeps
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
This keeps Norna commands separate from repository-specific build or publishing
|
|
53
|
+
commands in projects that embed a Norna site inside a larger GitHub project.
|
|
54
|
+
This pure starter also keeps `npm run build` as an alias for
|
|
60
55
|
`npm run norna:build`.
|
|
61
56
|
|
|
62
57
|
Use `npm run norna:engine:version` to inspect the installed engine and
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"norna:config:check": "norna config:check",
|
|
15
15
|
"norna:content:check": "norna content:check",
|
|
16
16
|
"norna:sync": "norna content:sync",
|
|
17
|
-
"norna:typography:presets": "norna typography
|
|
18
|
-
"norna:typography:show": "norna typography
|
|
17
|
+
"norna:typography:presets": "norna typography presets",
|
|
18
|
+
"norna:typography:show": "norna typography show",
|
|
19
19
|
"norna:public": "norna site:public",
|
|
20
20
|
"norna:images": "norna images",
|
|
21
21
|
"norna:build": "norna build",
|
|
@@ -3,27 +3,6 @@ export default {
|
|
|
3
3
|
url: 'https://example.com/',
|
|
4
4
|
basePath: '/',
|
|
5
5
|
},
|
|
6
|
-
layout: {
|
|
7
|
-
pageWidth: '1180px',
|
|
8
|
-
gutter: {
|
|
9
|
-
desktop: 'clamp(1.25rem, 4vw, 3rem)',
|
|
10
|
-
mobile: '1rem',
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
gallery: {
|
|
14
|
-
width: '900px',
|
|
15
|
-
maxAvailableWidthPercent: {
|
|
16
|
-
desktop: 100,
|
|
17
|
-
mobile: 100,
|
|
18
|
-
},
|
|
19
|
-
maxAvailableHeightPercent: {
|
|
20
|
-
desktop: 74,
|
|
21
|
-
mobile: 68,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
typography: {
|
|
25
|
-
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif",
|
|
26
|
-
},
|
|
27
6
|
navigation: {
|
|
28
7
|
smoothScroll: {
|
|
29
8
|
enabled: true,
|
|
@@ -37,11 +16,11 @@ export default {
|
|
|
37
16
|
labels: {
|
|
38
17
|
skipToContent: 'Skip to content',
|
|
39
18
|
sectionNavigation: 'Sections',
|
|
40
|
-
gallery: '
|
|
19
|
+
gallery: 'Images',
|
|
41
20
|
},
|
|
42
21
|
},
|
|
43
22
|
footer: {
|
|
44
|
-
copyrightMessage: '(c) Example
|
|
23
|
+
copyrightMessage: '(c) Example Owner.',
|
|
45
24
|
buildInfo: {
|
|
46
25
|
enabled: true,
|
|
47
26
|
text: 'Built',
|
|
@@ -54,7 +33,7 @@ export default {
|
|
|
54
33
|
},
|
|
55
34
|
},
|
|
56
35
|
github: {
|
|
57
|
-
repo: 'owner/example-
|
|
36
|
+
repo: 'owner/example-site',
|
|
58
37
|
branch: 'main',
|
|
59
38
|
pagesWorkflow: 'Deploy to GitHub Pages',
|
|
60
39
|
},
|
|
@@ -1,23 +1,56 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Example
|
|
2
|
+
title: Example Site
|
|
3
3
|
description: Minimal norna starter site.
|
|
4
4
|
sections:
|
|
5
5
|
- id: intro
|
|
6
6
|
presentation:
|
|
7
7
|
typography:
|
|
8
8
|
preset: statement
|
|
9
|
-
gallery: []
|
|
10
9
|
- id: work
|
|
11
|
-
|
|
10
|
+
- id: lorem1
|
|
11
|
+
- id: lorem2
|
|
12
|
+
- id: lorem3
|
|
13
|
+
|
|
12
14
|
---
|
|
13
15
|
|
|
14
16
|
## Intro {#intro}
|
|
15
|
-
|
|
16
17
|
This is a minimal starter site for norna. Since this site doesn't have any
|
|
17
18
|
routes defined, the navigation menu will be a sticky bar with anchor links for
|
|
18
19
|
ease of use on phones etc. [Highlighted inline text]{.highlight} when a short
|
|
19
20
|
phrase needs emphasis
|
|
20
|
-
|
|
21
21
|
## Work {#work}
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
Add image rows in frontmatter and matching source images under images/work/.
|
|
23
|
+
## What is Lorem Ipsum? {#lorem1}
|
|
24
|
+
Lorem Ipsum is simply dummy text of the printing and typesetting
|
|
25
|
+
industry. Lorem Ipsum has been the industry's standard dummy text ever
|
|
26
|
+
since 1966, when designers at Letraset and James Mosley, the librarian
|
|
27
|
+
at St Bride Printing Library in London, took a 1914 Cicero translation
|
|
28
|
+
and scrambled it to make dummy text for Letraset's Body Type
|
|
29
|
+
sheets. It has survived not only many decades, but also the leap into
|
|
30
|
+
electronic typesetting, remaining essentially unchanged. It was
|
|
31
|
+
popularised thanks to these sheets and more recently with desktop
|
|
32
|
+
publishing software like Aldus PageMaker and Microsoft Word including
|
|
33
|
+
versions of Lorem Ipsum.
|
|
34
|
+
## Why do we use it? {#lorem2}
|
|
35
|
+
It is a long established fact that a reader will be distracted by the
|
|
36
|
+
readable content of a page when looking at its layout. The point of
|
|
37
|
+
using Lorem Ipsum is that it has a more-or-less normal distribution of
|
|
38
|
+
letters, as opposed to using 'Content here, content here', making it
|
|
39
|
+
look like readable English. Many desktop publishing packages and web
|
|
40
|
+
page editors now use Lorem Ipsum as their default model text, and a
|
|
41
|
+
search for 'lorem ipsum' will uncover many web sites still in their
|
|
42
|
+
infancy. Various versions have evolved over the years, sometimes by
|
|
43
|
+
accident, sometimes on purpose (injected humour and the like).
|
|
44
|
+
## Where does it come from? {#lorem3}
|
|
45
|
+
Contrary to popular belief, Lorem Ipsum is not simply random text. It
|
|
46
|
+
has roots in a piece of classical Latin literature from 45 BC, making
|
|
47
|
+
it over 2000 years old. Richard McClintock, a Latin professor at
|
|
48
|
+
Hampden-Sydney College in Virginia, looked up one of the more obscure
|
|
49
|
+
Latin words, consectetur, from a Lorem Ipsum passage, and going
|
|
50
|
+
through the cites of the word in classical literature, discovered the
|
|
51
|
+
undoubtable source. Lorem Ipsum comes from sections 1.10.32 and
|
|
52
|
+
1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and
|
|
53
|
+
Evil) by Cicero, written in 45 BC. This book is a treatise on the
|
|
54
|
+
theory of ethics, very popular during the Renaissance. The first line
|
|
55
|
+
of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in
|
|
56
|
+
section 1.10.32
|