@eox/pages-theme-eox 2.0.0-alpha.5 → 2.0.0-alpha.7

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.
@@ -19,7 +19,7 @@ export default {
19
19
  const yaml = frontmatterMatch[1];
20
20
 
21
21
  // 1. Match inline array or string style author
22
- const authorMatch = yaml.match(/author:\s*(.*?)\r?\n/);
22
+ const authorMatch = yaml.match(/author:[ \t]+(.*?)\r?\n/);
23
23
  if (authorMatch) {
24
24
  const val = authorMatch[1].trim();
25
25
  if (val.startsWith("[") && val.endsWith("]")) {
@@ -30,7 +30,7 @@ export default {
30
30
  const clean = a.trim().replace(/['"]/g, "").toLowerCase();
31
31
  if (clean) allAuthors.add(clean);
32
32
  });
33
- } else if (val) {
33
+ } else if (val && !val.startsWith("-")) {
34
34
  const clean = val.replace(/['"]/g, "").toLowerCase();
35
35
  if (clean) allAuthors.add(clean);
36
36
  }
package/src/posts.data.js CHANGED
@@ -62,6 +62,44 @@ function getExcerpt(src, maxLength = 200) {
62
62
  return text;
63
63
  }
64
64
 
65
+ function resolvePostUrl(page) {
66
+ if (!page.url) return "";
67
+ const cleanUrls = global.VITEPRESS_CONFIG?.cleanUrls ?? true;
68
+
69
+ const relFile = page.url.replace(/^\//, "").replace(/\.html$/, "") + ".md";
70
+
71
+ // 1. Check VitePress rewrites map first if available
72
+ const rewritten = global.VITEPRESS_CONFIG?.rewrites?.map?.[relFile];
73
+ if (rewritten) {
74
+ return (
75
+ "/" +
76
+ rewritten
77
+ .replace(/(^|\/)index\.md$/, "$1")
78
+ .replace(/\.md$/, cleanUrls ? "" : ".html")
79
+ );
80
+ }
81
+
82
+ // 2. If it is in _posts/, compute fallback rewrite based on frontmatter date and slug
83
+ if (page.url.startsWith("/_posts/")) {
84
+ const baseName = page.url.replace(/^\/_posts\//, "").replace(/\.html$/, "");
85
+ const slug = baseName
86
+ .toLowerCase()
87
+ .replace(/[^a-z0-9]+/g, "-")
88
+ .replace(/^-+|-+$/g, "");
89
+
90
+ const dateStr = String(page.frontmatter?.date || "");
91
+ const dateMatch = dateStr.match(/^(\d{4})-(\d{2})/);
92
+ if (dateMatch) {
93
+ const [, year, month] = dateMatch;
94
+ return `/${year}/${month}/${slug}${cleanUrls ? "" : ".html"}`;
95
+ } else {
96
+ return `/blog/${slug}${cleanUrls ? "" : ".html"}`;
97
+ }
98
+ }
99
+
100
+ return page.url;
101
+ }
102
+
65
103
  export default createContentLoader("_posts/*.md", {
66
104
  includeSrc: true,
67
105
  transform(rawData) {
@@ -78,7 +116,7 @@ export default createContentLoader("_posts/*.md", {
78
116
 
79
117
  return {
80
118
  title: page.frontmatter.title || "",
81
- url: page.url,
119
+ url: resolvePostUrl(page),
82
120
  date: page.frontmatter.date || "",
83
121
  authors,
84
122
  tags: page.frontmatter.tags || [],
package/src/style.css CHANGED
@@ -92,6 +92,81 @@ body {
92
92
  margin-block-end: 0 !important;
93
93
  }
94
94
 
95
+ /* When a section follows a title (title plus section combination), eliminate start padding */
96
+ :is(
97
+ h1,
98
+ h2,
99
+ h3,
100
+ h4,
101
+ h5,
102
+ h6,
103
+ header,
104
+ .section-header-group,
105
+ [class*="section-title"]
106
+ )
107
+ + section,
108
+ :is(
109
+ h1,
110
+ h2,
111
+ h3,
112
+ h4,
113
+ h5,
114
+ h6,
115
+ header,
116
+ .section-header-group,
117
+ [class*="section-title"]
118
+ )
119
+ + :not(section, hr)
120
+ + section,
121
+ :is(
122
+ h1,
123
+ h2,
124
+ h3,
125
+ h4,
126
+ h5,
127
+ h6,
128
+ header,
129
+ .section-header-group,
130
+ [class*="section-title"]
131
+ )
132
+ + :not(section, hr)
133
+ + :not(section, hr)
134
+ + section,
135
+ :is(
136
+ h1,
137
+ h2,
138
+ h3,
139
+ h4,
140
+ h5,
141
+ h6,
142
+ header,
143
+ .section-header-group,
144
+ [class*="section-title"]
145
+ )
146
+ + :not(section, hr)
147
+ + :not(section, hr)
148
+ + :not(section, hr)
149
+ + section,
150
+ :is(
151
+ h1,
152
+ h2,
153
+ h3,
154
+ h4,
155
+ h5,
156
+ h6,
157
+ header,
158
+ .section-header-group,
159
+ [class*="section-title"]
160
+ )
161
+ + :not(section, hr)
162
+ + :not(section, hr)
163
+ + :not(section, hr)
164
+ + :not(section, hr)
165
+ + section {
166
+ padding-block-start: 0 !important;
167
+ padding-top: 0 !important;
168
+ }
169
+
95
170
  .VPHome .vp-doc a {
96
171
  font-weight: 400;
97
172
  color: inherit;
@@ -565,3 +640,68 @@ eox-feedback-button {
565
640
  white-space: nowrap !important;
566
641
  border-width: 0 !important;
567
642
  }
643
+
644
+ /* ==========================================================================
645
+ Links in text hover underline
646
+ ========================================================================== */
647
+
648
+ a.link {
649
+ text-decoration: none;
650
+ }
651
+
652
+ :is(p, li, blockquote, figcaption, td, th, dd, dt, .card-body-text)
653
+ a:not(
654
+ .button,
655
+ [role="button"],
656
+ .chip,
657
+ .badge,
658
+ .circle,
659
+ .header-anchor,
660
+ .card-cover-link,
661
+ .grid-link,
662
+ .sidebar-tag,
663
+ .post-tag,
664
+ .clickable-chip,
665
+ .tag-link,
666
+ .social-link-btn,
667
+ .custom-cta-button,
668
+ :has(> img:only-child),
669
+ :has(> svg:only-child)
670
+ ):hover,
671
+ a.link:hover,
672
+ .vp-doc
673
+ a:not(
674
+ .button,
675
+ [role="button"],
676
+ .header-anchor,
677
+ .card-cover-link,
678
+ .grid-link,
679
+ .sidebar-tag,
680
+ .post-tag,
681
+ .clickable-chip,
682
+ .tag-link,
683
+ .social-link-btn,
684
+ .custom-cta-button,
685
+ :has(> img:only-child),
686
+ :has(> svg:only-child)
687
+ ):hover {
688
+ text-decoration: underline;
689
+ text-underline-offset: 2px;
690
+ }
691
+
692
+ /* Ensure navigation bars, dropdown menus, sidebars, and outline links do not get hover underline unless explicitly marked .link */
693
+ :is(
694
+ nav,
695
+ menu,
696
+ dialog,
697
+ .top-nav,
698
+ .social-links,
699
+ .VPSidebar,
700
+ .VPDocAsideOutline,
701
+ .VPLocalSearchBox
702
+ )
703
+ a:not(.link):hover,
704
+ menu a:hover,
705
+ menu li a:hover {
706
+ text-decoration: none !important;
707
+ }
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { resolveLlms } from "./llms/index.js";
3
4
 
4
5
  function copyThemePages() {
5
6
  try {
@@ -93,6 +94,7 @@ function getBlogRewrites() {
93
94
  */
94
95
  export const generate = (brandConfig) => {
95
96
  copyThemePages();
97
+ const llmsResult = resolveLlms(brandConfig.llms, brandConfig);
96
98
  const config = {
97
99
  appearance: false,
98
100
  cleanUrls: true,
@@ -191,6 +193,9 @@ export const generate = (brandConfig) => {
191
193
  themeConfig: {
192
194
  outline: "deep",
193
195
  siteTitle: false,
196
+ llms: {
197
+ copyButtons: llmsResult.copyButtons,
198
+ },
194
199
  theme: {
195
200
  primaryColor: brandConfig.theme?.primary_color,
196
201
  secondaryColor:
@@ -212,7 +217,7 @@ export const generate = (brandConfig) => {
212
217
  ></span>`,
213
218
  copyright:
214
219
  brandConfig.theme?.footer?.copyright ||
215
- 'Copyright © 2014-present <a href="https://eox.at" target="_blank">EOX IT Services GmbH</a>',
220
+ 'Copyright © 2008-present <a href="https://eox.at" target="_blank">EOX IT Services GmbH</a>',
216
221
  },
217
222
  },
218
223
  title: brandConfig.meta?.title,
@@ -223,6 +228,7 @@ export const generate = (brandConfig) => {
223
228
  optimizeDeps: {
224
229
  exclude: ["@eox/pages-theme-eox"],
225
230
  },
231
+ plugins: [...llmsResult.plugins],
226
232
  },
227
233
  vue: {
228
234
  template: {