@xexr/blog-platform 1.1.7 → 1.2.0
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/CHANGELOG.md +6 -1
- package/README.md +21 -0
- package/dist/app/api/blog/publish/route.test.ts +55 -0
- package/dist/app/api/blog/publish/route.ts +7 -2
- package/dist/app/blog/[slug]/page.tsx +41 -28
- package/dist/components/ArticleVideo.tsx +136 -0
- package/dist/{index-DsXjuPn4.d.mts → index-CmjKzrH-.d.mts} +28 -1
- package/dist/{index-DsXjuPn4.d.ts → index-CmjKzrH-.d.ts} +28 -1
- package/dist/index.d.mts +52 -6
- package/dist/index.d.ts +52 -6
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -14
- package/dist/index.mjs.map +1 -1
- package/dist/lib/storage/drizzle.ts +9 -0
- package/dist/lib/structured-data.ts +52 -0
- package/dist/lib/video.ts +163 -0
- package/dist/{sitemap-B64QGT4l.d.ts → sitemap-CEjqxRaQ.d.ts} +1 -1
- package/dist/{sitemap-Dy7Q4ATM.d.mts → sitemap-D1eInRA1.d.mts} +1 -1
- package/dist/sitemap.d.mts +2 -2
- package/dist/sitemap.d.ts +2 -2
- package/dist/types/contracts.ts +35 -0
- package/dist/types/index.d.mts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.ts +1 -0
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as PublishedArticle, b as PublishedSite, d as PublishedNewsletterSettings, e as PublishedArticleCta, c as PublishedAuthor, f as PublishResult, P as PublishedTopic, g as PublishedSeriesContext } from './index-
|
|
2
|
-
export { h as PublishPayload, i as PublishedAuthorSocialLinks } from './index-
|
|
1
|
+
import { a as PublishedArticle, b as PublishedSite, d as PublishedNewsletterSettings, e as PublishedArticleCta, c as PublishedAuthor, f as PublishResult, P as PublishedTopic, g as PublishedSeriesContext } from './index-CmjKzrH-.js';
|
|
2
|
+
export { h as PublishPayload, i as PublishedArticleVideo, j as PublishedAuthorSocialLinks } from './index-CmjKzrH-.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { CSSProperties, ReactElement } from 'react';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -10,8 +10,8 @@ export { RelatedArticleCandidate, RelatedFeaturedArticlesOptions, getRelatedFeat
|
|
|
10
10
|
import { NextRequest, NextResponse } from 'next/server.js';
|
|
11
11
|
import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
|
|
12
12
|
import { LibSQLDatabase } from 'drizzle-orm/libsql';
|
|
13
|
-
import { C as CanonicalUrlOptions } from './sitemap-
|
|
14
|
-
export { B as BlogSitemapConfig, N as NextjsSitemapEntry, S as SitemapChangeFreq, a as SitemapData, b as SitemapEntry, c as SitemapOptions, d as createBlogSitemapRoute, e as createDynamicBlogSitemap, g as generateBlogSitemapEntries, f as generateCanonicalUrl, h as generateCanonicalUrlFromSlug, i as generateSitemap, j as generateSitemapIndex, k as getBaseUrl, l as isValidCanonicalUrl, n as normalizeDomain, m as normalizeSlug, s as sitemapToXml, u as updateArticleCanonicalUrl, v as validateSitemap } from './sitemap-
|
|
13
|
+
import { C as CanonicalUrlOptions } from './sitemap-CEjqxRaQ.js';
|
|
14
|
+
export { B as BlogSitemapConfig, N as NextjsSitemapEntry, S as SitemapChangeFreq, a as SitemapData, b as SitemapEntry, c as SitemapOptions, d as createBlogSitemapRoute, e as createDynamicBlogSitemap, g as generateBlogSitemapEntries, f as generateCanonicalUrl, h as generateCanonicalUrlFromSlug, i as generateSitemap, j as generateSitemapIndex, k as getBaseUrl, l as isValidCanonicalUrl, n as normalizeDomain, m as normalizeSlug, s as sitemapToXml, u as updateArticleCanonicalUrl, v as validateSitemap } from './sitemap-CEjqxRaQ.js';
|
|
15
15
|
|
|
16
16
|
interface BlogTheme {
|
|
17
17
|
accentColor?: string;
|
|
@@ -452,6 +452,34 @@ declare function getAllSeries(articles: PublishedArticle[]): PublishedSeriesCont
|
|
|
452
452
|
declare function getSeriesArchive(articles: PublishedArticle[], seriesSlug: string): SeriesArchive | null;
|
|
453
453
|
declare function getArticleSeriesNavigation(article: PublishedArticle): PublishedSeriesContext | null;
|
|
454
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Helpers for article videos (YouTube only).
|
|
457
|
+
*
|
|
458
|
+
* Every URL built here goes through `isYouTubeVideoId` first, so a stored id
|
|
459
|
+
* can never inject markup or a different host into an embed.
|
|
460
|
+
*/
|
|
461
|
+
declare const ARTICLE_VIDEO_TITLE_MAX_LENGTH = 200;
|
|
462
|
+
declare const ARTICLE_VIDEO_DESCRIPTION_MAX_LENGTH = 5000;
|
|
463
|
+
declare function isYouTubeVideoId(value: unknown): value is string;
|
|
464
|
+
declare function isIsoDuration(value: unknown): value is string;
|
|
465
|
+
/**
|
|
466
|
+
* Extract a YouTube video id from a bare id or a YouTube URL
|
|
467
|
+
* (watch, youtu.be, embed, nocookie embed, shorts, live).
|
|
468
|
+
*/
|
|
469
|
+
declare function parseYouTubeVideoId(input: string): string | null;
|
|
470
|
+
/**
|
|
471
|
+
* Validate an untrusted `video` value from a publish payload.
|
|
472
|
+
* Returns a list of human-readable errors; empty when valid.
|
|
473
|
+
*/
|
|
474
|
+
declare function validatePublishedArticleVideo(value: unknown): string[];
|
|
475
|
+
/** Privacy-enhanced player URL, loaded only after the reader presses play. */
|
|
476
|
+
declare function buildYouTubeEmbedUrl(id: string): string;
|
|
477
|
+
/** Canonical player URL for structured data. */
|
|
478
|
+
declare function buildYouTubeStructuredDataEmbedUrl(id: string): string;
|
|
479
|
+
declare function buildYouTubeWatchUrl(id: string): string;
|
|
480
|
+
/** Thumbnail URL for structured data only; the page never requests it. */
|
|
481
|
+
declare function buildYouTubeThumbnailUrl(id: string): string;
|
|
482
|
+
|
|
455
483
|
interface BlogTopicsIndexPageProps {
|
|
456
484
|
articles: PublishedArticle[];
|
|
457
485
|
basePath?: string;
|
|
@@ -2048,6 +2076,20 @@ interface BlogPostingSchema extends BaseStructuredData {
|
|
|
2048
2076
|
"@type": "Thing";
|
|
2049
2077
|
name: string;
|
|
2050
2078
|
}[];
|
|
2079
|
+
video?: VideoObjectSchema;
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* VideoObject schema for an article's embedded video
|
|
2083
|
+
* @see https://schema.org/VideoObject
|
|
2084
|
+
*/
|
|
2085
|
+
interface VideoObjectSchema {
|
|
2086
|
+
"@type": "VideoObject";
|
|
2087
|
+
name: string;
|
|
2088
|
+
description: string;
|
|
2089
|
+
thumbnailUrl: string[];
|
|
2090
|
+
uploadDate: string;
|
|
2091
|
+
duration?: string;
|
|
2092
|
+
embedUrl: string;
|
|
2051
2093
|
}
|
|
2052
2094
|
/**
|
|
2053
2095
|
* WebSite schema for the blog home page
|
|
@@ -2103,6 +2145,10 @@ interface StructuredDataOptions {
|
|
|
2103
2145
|
* Generate comprehensive structured data for a blog article
|
|
2104
2146
|
*/
|
|
2105
2147
|
declare function generateArticleStructuredData(article: PublishedArticle, options?: StructuredDataOptions): BlogPostingSchema;
|
|
2148
|
+
/**
|
|
2149
|
+
* Generate the VideoObject for an article's video, if it has a valid one
|
|
2150
|
+
*/
|
|
2151
|
+
declare function generateVideoStructuredData(article: PublishedArticle): VideoObjectSchema | undefined;
|
|
2106
2152
|
/**
|
|
2107
2153
|
* Generate structured data for an author
|
|
2108
2154
|
*/
|
|
@@ -2283,5 +2329,5 @@ declare function OPTIONS(request: NextRequest): Promise<NextResponse>;
|
|
|
2283
2329
|
|
|
2284
2330
|
declare const PACKAGE_VERSION: string;
|
|
2285
2331
|
|
|
2286
|
-
export { ApiKeyAuth, BLOG_PLATFORM_SCHEMA_VERSION, BLOG_PLATFORM_TABLE_NAMES, ArticlePage as BlogArticlePage, AuthorPage as BlogAuthorPage, BlogAuthorsIndexPage, BlogHomePage, BlogPlatformSchemaError, BlogSeriesArchivePage, BlogSeriesArchiveRoutePage, BlogSeriesIndexPage, BlogSeriesPage, BlogTopicArchivePage, BlogTopicsIndexPage, Button, CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, InMemoryStorage, NEWSLETTER_SUCCESS_MESSAGE, NewsletterSignup, NoAuth, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PublishResult, PublishedArticle, PublishedAuthor, PublishedNewsletterSettings, PublishedSite, PublishedTopic, SeriesNavigation, Pagination as ShadcnPagination, StructuredDataError, UninitializedAuth, autoConfigureRateLimit, blogPlatformDrizzleSchema, bpArticles, bpMetadata, bpOperations, buildAuthorPath, buildBlogPath, buildSeriesPath, buttonVariants, checkDrizzleAdapterSchema, checkRateLimit, cn, POST as configHandler, OPTIONS$1 as configOptionsHandler, configureRateLimit, createRateLimitErrorResponse, createStructuredDataScript, createTokenFingerprint, enforceRateLimit, ensureDrizzleAdapterSchema, extractKeywordsFromArticle, extractTableOfContents, extractTokenFromHeader, formatArticleDateMeta, generateArticleMetadata, generateArticleStructuredData, generateAuthorPageMetadata, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBreadcrumbStructuredData, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSeriesArchiveMetadata, generateSeriesIndexMetadata, generateSiteMetadata, generateWebSiteStructuredData, getAllSeries, getAllTopics, getArticlePrimaryTopic, getArticleSeriesNavigation, getAuthConfig, getAuthorArchive, getAuthorsFromArticles, getBlogThemeStyle, getDrizzleAdapterSql, getPathPrefixFromBlogUrl, getRateLimitHeaders, getSeriesArchive, getStorage, getTopicArchive, GET$1 as indexNowKeyRoute, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, loadAuthorArchive, metadataToHtml, normalizeBlogBasePath, POST$2 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST$1 as unpublishHandler, usePagination, validateMetadata, validateStructuredData, GET$2 as versionHandler };
|
|
2287
|
-
export type { AuthConfig, AuthResult, AuthorArchive, AuthorArchiveOptions, BlogPlatformConfig, BlogPlatformSchemaCheckResult, BlogPlatformStorage, BlogPlatformTableName, BlogPostingSchema, BlogTheme, BreadcrumbListSchema, GeneratedMetadata, LinkTag, MetaTag, MetadataOptions, NewsletterSignupProps, OrganizationSchema, PersonSchema, RateLimitConfig, RateLimitResult, SeriesArchive, StructuredDataOptions, TopicArchive, WebSiteSchema };
|
|
2332
|
+
export { ARTICLE_VIDEO_DESCRIPTION_MAX_LENGTH, ARTICLE_VIDEO_TITLE_MAX_LENGTH, ApiKeyAuth, BLOG_PLATFORM_SCHEMA_VERSION, BLOG_PLATFORM_TABLE_NAMES, ArticlePage as BlogArticlePage, AuthorPage as BlogAuthorPage, BlogAuthorsIndexPage, BlogHomePage, BlogPlatformSchemaError, BlogSeriesArchivePage, BlogSeriesArchiveRoutePage, BlogSeriesIndexPage, BlogSeriesPage, BlogTopicArchivePage, BlogTopicsIndexPage, Button, CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, InMemoryStorage, NEWSLETTER_SUCCESS_MESSAGE, NewsletterSignup, NoAuth, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PublishResult, PublishedArticle, PublishedAuthor, PublishedNewsletterSettings, PublishedSite, PublishedTopic, SeriesNavigation, Pagination as ShadcnPagination, StructuredDataError, UninitializedAuth, autoConfigureRateLimit, blogPlatformDrizzleSchema, bpArticles, bpMetadata, bpOperations, buildAuthorPath, buildBlogPath, buildSeriesPath, buildYouTubeEmbedUrl, buildYouTubeStructuredDataEmbedUrl, buildYouTubeThumbnailUrl, buildYouTubeWatchUrl, buttonVariants, checkDrizzleAdapterSchema, checkRateLimit, cn, POST as configHandler, OPTIONS$1 as configOptionsHandler, configureRateLimit, createRateLimitErrorResponse, createStructuredDataScript, createTokenFingerprint, enforceRateLimit, ensureDrizzleAdapterSchema, extractKeywordsFromArticle, extractTableOfContents, extractTokenFromHeader, formatArticleDateMeta, generateArticleMetadata, generateArticleStructuredData, generateAuthorPageMetadata, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBreadcrumbStructuredData, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSeriesArchiveMetadata, generateSeriesIndexMetadata, generateSiteMetadata, generateVideoStructuredData, generateWebSiteStructuredData, getAllSeries, getAllTopics, getArticlePrimaryTopic, getArticleSeriesNavigation, getAuthConfig, getAuthorArchive, getAuthorsFromArticles, getBlogThemeStyle, getDrizzleAdapterSql, getPathPrefixFromBlogUrl, getRateLimitHeaders, getSeriesArchive, getStorage, getTopicArchive, GET$1 as indexNowKeyRoute, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, isIsoDuration, isYouTubeVideoId, loadAuthorArchive, metadataToHtml, normalizeBlogBasePath, parseYouTubeVideoId, POST$2 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST$1 as unpublishHandler, usePagination, validateMetadata, validatePublishedArticleVideo, validateStructuredData, GET$2 as versionHandler };
|
|
2333
|
+
export type { AuthConfig, AuthResult, AuthorArchive, AuthorArchiveOptions, BlogPlatformConfig, BlogPlatformSchemaCheckResult, BlogPlatformStorage, BlogPlatformTableName, BlogPostingSchema, BlogTheme, BreadcrumbListSchema, GeneratedMetadata, LinkTag, MetaTag, MetadataOptions, NewsletterSignupProps, OrganizationSchema, PersonSchema, RateLimitConfig, RateLimitResult, SeriesArchive, StructuredDataOptions, TopicArchive, VideoObjectSchema, WebSiteSchema };
|