From fd25811bcde1cb21d5f58f5e6a8f70272be3ea1b Mon Sep 17 00:00:00 2001 From: Aliaksandr Zahatski Date: Sat, 10 Feb 2024 13:51:32 +0100 Subject: [PATCH 1/4] update links --- README.md | 8 ++++---- pub/index.pod6 | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 14f2b63..8d74368 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Podlite-web -A minimal, lightweight starter for creating blogs/sites using nexjs and pod6 markup language! +A minimal, lightweight starter for creating blogs/sites using nexjs and [Podlite](https://podlite.org/) markup language! ## QUICK GUIDE @@ -115,13 +115,13 @@ Useful links ------------ * ["Start your own blog/site with Podlite for Web"](https://zahatski.com/2022/8/23/1/start-you-own-blog-site-with-podlite-for-web) - how-to article -* [Pod6 - An easy-to-use markup language for documenting Raku modules and programs](https://docs.raku.org/language/pod) +* [Podlite is a lightweight block-based markup language designed for flexibility and ease of use.](https://podlite.org) -* Specification of pod6: [Synopsis 26](https://github.com/perl6/specs/blob/master/S26-documentation.pod) +* Specification of Podlite: [podlite.org/specification](https://podlite.org/specification) * Online editor: [https://pod6.in](https://pod6.in) -* [Podlite](https://github.com/zag/podlite-desktop) - open-source desktop pod6 editor for Windows, Linux, and Mac. +* [Podlite Desktop](https://github.com/podlite/podlite-desktop) - open-source desktop Podlite editor for Windows, Linux, and Mac. ## License diff --git a/pub/index.pod6 b/pub/index.pod6 index 9d4b48c..40b242d 100644 --- a/pub/index.pod6 +++ b/pub/index.pod6 @@ -9,7 +9,7 @@ =head1 👋 Welcome ! =head2 This is demo page of L! -podlite-web - a minimal, lightweight starter for creating static blogs/sites using nexjs and L markup language! +podlite-web - a minimal, lightweight starter for creating static blogs/sites using nexjs and L markup language! =for Toc :title @@ -103,12 +103,12 @@ This is a logo of L project. =Image logo.png This is a logo of L project. -You can try Pod6 here: L. +You can try Podlite here: L. Source of this page you can found L =begin para :id -© All rights reserved. 2022. L. I> +© All rights reserved. 2022-2024. L. I> =end para =end pod \ No newline at end of file From c4db4db66c62c8fbe9cbd55c5610b5316ec3ca61 Mon Sep 17 00:00:00 2001 From: Aliaksandr Zahatski Date: Sat, 10 Feb 2024 13:58:24 +0100 Subject: [PATCH 2/4] tidy --- .prettierrc | 10 +- src/components/service.tsx | 211 +++++++++++++++++++--------------- src/constants.ts | 49 ++++---- src/node-utils.ts | 212 +++++++++++++++++----------------- src/pages/[...slug].tsx | 25 ++-- src/pages/_app.tsx | 70 ++++++------ src/pages/index.tsx | 63 +++++----- src/shared.ts | 227 ++++++++++++++++++------------------- src/utils.tsx | 175 ++++++++++++++-------------- src/utils/redirects.ts | 12 +- src/utils/rss.tsx | 26 ++--- src/utils/sitemap.ts | 28 +++-- 12 files changed, 566 insertions(+), 542 deletions(-) diff --git a/.prettierrc b/.prettierrc index 33d2cfa..a00737e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,10 @@ { - "arrowParens": "avoid", - "semi": false + "arrowParens": "avoid", + "semi": false, + "singleQuote": true, + "trailingComma": "all", + "endOfLine": "lf", + "tabWidth": 2, + "jsxBracketSameLine": false, + "printWidth": 120 } diff --git a/src/components/service.tsx b/src/components/service.tsx index 2c7adf0..6f80a39 100644 --- a/src/components/service.tsx +++ b/src/components/service.tsx @@ -1,114 +1,145 @@ -import { contentData, ContentRecord, getArticlesGroupedByYearMonth, getPostComponent, getSiteInfo } from 'src/utils'; -import moment from 'moment'; +import { contentData, ContentRecord, getArticlesGroupedByYearMonth, getPostComponent, getSiteInfo } from 'src/utils' +import moment from 'moment' import 'moment/min/locales.min' import styles from './service.module.css' import Link from 'next/link' -import { DataFeedContent } from 'bin/makeDataSource'; -import { getTextContentFromNode } from '@podlite/schema'; -export const TestComponent = ({id,children})=>{ - var style = { "--count-columns ": children.length } as React.CSSProperties; - return
-
- - {children.map((i,c)=>
{i}
)} +import { DataFeedContent } from 'bin/makeDataSource' +import { getTextContentFromNode } from '@podlite/schema' +export const TestComponent = ({ id, children }) => { + var style = { '--count-columns ': children.length } as React.CSSProperties + return ( +
+
+ {children.map((i, c) => ( +
+ {i} +
+ ))} +
-
+ ) } -export const Contents = ({locale='en'})=>{ -moment.locale(locale) -const groupedByYearMonth = getArticlesGroupedByYearMonth() +export const Contents = ({ locale = 'en' }) => { + moment.locale(locale) + const groupedByYearMonth = getArticlesGroupedByYearMonth() -const res:JSX.Element[] = [] -for ( const year of Object.keys(groupedByYearMonth).sort((a,b)=> parseInt(b,10)-parseInt(a,10)) ) { - const months:DataFeedContent["all"] = groupedByYearMonth[year] - let isYearAlreadyPut = false; - for ( const month of Object.keys(months).sort((a,b)=> parseInt(b,10)-parseInt(a,10)) ) { - const monthRecord = <> -

{ !isYearAlreadyPut && } - -

- { months[month].map(({publishUrl,title,pubdate, node })=>( + const res: JSX.Element[] = [] + for (const year of Object.keys(groupedByYearMonth).sort((a, b) => parseInt(b, 10) - parseInt(a, 10))) { + const months: DataFeedContent['all'] = groupedByYearMonth[year] + let isYearAlreadyPut = false + for (const month of Object.keys(months).sort((a, b) => parseInt(b, 10) - parseInt(a, 10))) { + const monthRecord = ( + <> +

+ {!isYearAlreadyPut && } + +

+ {months[month].map(({ publishUrl, title, pubdate, node }) => ( - -

{title || getTextContentFromNode(node)}

-
- -
+ +

{title || getTextContentFromNode(node)}

+
+ +
- )) - } + ))} - isYearAlreadyPut=true; - res.push(monthRecord) + ) + isYearAlreadyPut = true + res.push(monthRecord) } - -} -return
{res}
+ } + return
{res}
} -export const Article = ({title, node, shortUrl, key,publishUrl, pubdate})=>{ - const [ _ , domain = '' ] = getSiteInfo().url.split(/\/\//) - return ( -
-

{title}

- {getPostComponent(node)} - -
-)} +export const Article = ({ title, node, shortUrl, key, publishUrl, pubdate }) => { + const [_, domain = ''] = getSiteInfo().url.split(/\/\//) + return ( + + ) +} -export const Page = ({title, node, shortUrl, key,publishUrl, pubdate})=>( +export const Page = ({ title, node, shortUrl, key, publishUrl, pubdate }) => ( <>
-

{title}

- {getPostComponent(node)} +
+

{title}

+
+ {getPostComponent(node)}
- - <> -
 ↑ 
- <> + + <> +
+  ↑  +
+ <>
) -export const ArticlesWithNavigation = ({articles, prev, next }:{articles:any[],prev?:any, next?:any})=>{ +export const ArticlesWithNavigation = ({ articles, prev, next }: { articles: any[]; prev?: any; next?: any }) => { const makeLink = (title, url) => {title} - return (<> - { - articles.map(({publishUrl, ...args}:any)=>Article({key:publishUrl, publishUrl, ...args})) - } - - { prev && makeLink(prev.title || getTextContentFromNode(prev.node), prev.publishUrl)} - {
{prev ? makeLink("←", prev.publishUrl) : }↑{next ? makeLink("→", next.publishUrl) : }
} - { next && makeLink(next.title || getTextContentFromNode(next.node), next.publishUrl) } -
- -)} + return ( + <> + {articles.map(({ publishUrl, ...args }: any) => Article({ key: publishUrl, publishUrl, ...args }))} + + {prev && makeLink(prev.title || getTextContentFromNode(prev.node), prev.publishUrl)} + { +
+ {prev ? makeLink('←', prev.publishUrl) : } + ↑ + {next ? makeLink('→', next.publishUrl) : } +
+ } + {next && makeLink(next.title || getTextContentFromNode(next.node), next.publishUrl)} +
+ + ) +} +export const LastArticles = ({ count = 1, id, children }) => { + const source = () => contentData().filter(({ type = '' }: any) => type !== 'page') + const articles = source().reverse().slice(0, count) + const lastArticleUrl = articles[articles.length - 1].publishUrl + const articleIndex = source().findIndex(({ publishUrl }) => publishUrl === lastArticleUrl) + const prev = source()[articleIndex - 1] + return ( + <> + + + ) +} -export const LastArticles = ({count=1, id,children})=>{ - const source =()=>contentData().filter(({type=''}:any)=>type !== 'page') - const articles = source().reverse().slice(0,count) - const lastArticleUrl = articles[articles.length-1].publishUrl - const articleIndex =source().findIndex(({publishUrl})=>publishUrl===lastArticleUrl) - const prev = source()[articleIndex - 1] - return ( - <> - - - ) - } - - export const HeaderCol = ({id,children}:{id?:any,children:any})=>{ - var style = { "--count-columns ": children.length } as React.CSSProperties; - return
-
- - {children.map((i,c)=>( -
{i}
- ))} -
-
- } - -export default TestComponent \ No newline at end of file +export const HeaderCol = ({ id, children }: { id?: any; children: any }) => { + var style = { '--count-columns ': children.length } as React.CSSProperties + return ( +
+
+ {children.map((i, c) => ( +
+ {i} +
+ ))} +
+
+ ) +} + +export default TestComponent diff --git a/src/constants.ts b/src/constants.ts index 239f619..339422f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,34 +1,33 @@ -import { PodNode } from "@podlite/schema" -import path from "path" +import { PodNode } from '@podlite/schema' +import path from 'path' // export const POSTS_PATH = path.join(process.cwd(), "/data") -export const POSTS_PATH = process.env.POSTS_PATH || path.join(process.cwd(), "/pub") -export const INDEX_PATH = process.env.INDEX_PATH || "index.pod6" - -export const DATA_PATH = path.join(process.cwd(), "/built/data.json") -export const IMAGE_LIB = path.join(process.cwd(), "/built/images.ts") -export const COMPONENTS_LIB = path.join(process.cwd(),"/built/components.ts") -export const STYLES_LIB = path.join(process.cwd(),"/built/styles.css") +export const POSTS_PATH = process.env.POSTS_PATH || path.join(process.cwd(), '/pub') +export const INDEX_PATH = process.env.INDEX_PATH || 'index.pod6' +export const DATA_PATH = path.join(process.cwd(), '/built/data.json') +export const IMAGE_LIB = path.join(process.cwd(), '/built/images.ts') +export const COMPONENTS_LIB = path.join(process.cwd(), '/built/components.ts') +export const STYLES_LIB = path.join(process.cwd(), '/built/styles.css') export const PAGES_FILE_PATH = path.join(process.cwd()) -export const ASSETS_PATH = path.join(process.cwd(), "/public/assets") -export const PUBLIC_PATH = path.join(process.cwd(), "/public") +export const ASSETS_PATH = path.join(process.cwd(), '/public/assets') +export const PUBLIC_PATH = path.join(process.cwd(), '/public') export type SiteInfo = { - postsPerPage: 4 - favicon: string - url: "http://example.com" - title: "Example" - globalStyles?: string - node: PodNode - redirects:{ - source : string, - destination: string, - statusCode: number, - }[] - } - + postsPerPage: 4 + favicon: string + url: 'http://example.com' + title: 'Example' + globalStyles?: string + node: PodNode + redirects: { + source: string + destination: string + statusCode: number + }[] +} + export const defaultIndexPage = ` =begin pod = :favicon<./favicon.png> @@ -43,4 +42,4 @@ Hey, this is a test page! Powered by podlite. =end pod -` \ No newline at end of file +` diff --git a/src/node-utils.ts b/src/node-utils.ts index d05dbaf..6cde920 100644 --- a/src/node-utils.ts +++ b/src/node-utils.ts @@ -1,121 +1,123 @@ -import { getFromTree, getTextContentFromNode, makeAttrs, makeInterator, PodNode, Text} from "@podlite/schema" -import * as fs from "fs" -import { getAllArticles, isExistsPubdate, makeAstFromSrc, pubRecord, publishRecord } from "./shared" +import { getFromTree, getTextContentFromNode, makeAttrs, makeInterator, PodNode, Text } from '@podlite/schema' +import * as fs from 'fs' +import { getAllArticles, isExistsPubdate, makeAstFromSrc, pubRecord, publishRecord } from './shared' -const glob = require("glob") +const glob = require('glob') export const getPathToOpen = (filepath, parentDocPath) => { - const isRemoteReg = new RegExp(/^(https?|ftp):/) - const isRemote = isRemoteReg.test(filepath) - if (isRemote) { - return { isRemote, path: filepath } - } - const path = require("path") - const docDirPath = path.dirname(parentDocPath) - return { - isRemote, - path: path.isAbsolute(filepath) - ? filepath - : path.normalize(path.join(docDirPath, filepath)), - } + const isRemoteReg = new RegExp(/^(https?|ftp):/) + const isRemote = isRemoteReg.test(filepath) + if (isRemote) { + return { isRemote, path: filepath } + } + const path = require('path') + const docDirPath = path.dirname(parentDocPath) + return { + isRemote, + path: path.isAbsolute(filepath) ? filepath : path.normalize(path.join(docDirPath, filepath)), + } } -export const makeLinksMap = (records:publishRecord[]):{[link:string]:string} => { - const linksMap = { ...Object.fromEntries(records.map(({publishUrl='',file})=>[ getPathToOpen(file, './').path, publishUrl]))} - return linksMap +export const makeLinksMap = (records: publishRecord[]): { [link: string]: string } => { + const linksMap = { + ...Object.fromEntries(records.map(({ publishUrl = '', file }) => [getPathToOpen(file, './').path, publishUrl])), + } + return linksMap } -export const convertFileLinksToUrl = (records:publishRecord[], additinalMap = {}):publishRecord[] => { - const linksMap = { ...additinalMap, ...makeLinksMap(records)} - const processed = records.map( - item=>{ - const converter = makeInterator({ - 'L<>': (node, ctx, interator) => { - const {content,meta} = node - const link = meta ? meta : getTextContentFromNode(content) - const r = link.match(/file:\s*(?(.+))\s*$/) - const convertFileToUrl = (filePath) => { - const {isRemote, path } = getPathToOpen(filePath, item.file) - return isRemote ? null : linksMap[path] - } - const newLink = r?.groups?.path ? convertFileToUrl(r.groups.path) : link - const newContent:Text = { - type: 'text', - value: newLink - } - const updated = meta ? { meta : newLink} : {content:newContent} +export const convertFileLinksToUrl = (records: publishRecord[], additinalMap = {}): publishRecord[] => { + const linksMap = { ...additinalMap, ...makeLinksMap(records) } + const processed = records.map(item => { + const converter = makeInterator({ + 'L<>': (node, ctx, interator) => { + const { content, meta } = node + const link = meta ? meta : getTextContentFromNode(content) + const r = link.match(/file:\s*(?(.+))\s*$/) + const convertFileToUrl = filePath => { + const { isRemote, path } = getPathToOpen(filePath, item.file) + return isRemote ? null : linksMap[path] + } + const newLink = r?.groups?.path ? convertFileToUrl(r.groups.path) : link + const newContent: Text = { + type: 'text', + value: newLink, + } + const updated = meta ? { meta: newLink } : { content: newContent } - return {...node, ...updated} - }, - }) - const res = converter(item.node, {}) - if (item.description) { - const description = converter(item.description, {}) - return { ...item, node:res , description} - } - return { ...item, node:res } + return { ...node, ...updated } + }, }) - return processed -} - - -export function parseFiles(path:string) { - let count = 0 -const allFiles = glob - .sync(path) - .map((f: any) => { - count++ - const testData = fs.readFileSync(f).toString() - const asAst = makeAstFromSrc(testData) - // now check if tree contains block with :pubdate attribute - // '* :pubdate' - if (!isExistsPubdate(asAst)) { - return + const res = converter(item.node, {}) + if (item.description) { + const description = converter(item.description, {}) + return { ...item, node: res, description } } - // extract notes + return { ...item, node: res } + }) + return processed +} - const notes: pubRecord[] = getFromTree(asAst, "para") - .filter(n => makeAttrs(n, {}).exists("pubdate")) - .map((n: PodNode) => { - const a_pubdate = makeAttrs(n, {}).getFirstValue("pubdate") - // Due to cover some cases whan new Date fail on safari, i.e. - // new Date("2022-05-07 10:00:00").getFullYear() -> NaN - // convert to ISO 8601 "2022-05-07 10:00:00" -> "2022-05-07T10:00:00" - const pubdate = a_pubdate.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/) ? a_pubdate.replace(" ","T") : a_pubdate +export function parseFiles(path: string) { + let count = 0 + const allFiles = glob + .sync(path) + .map((f: any) => { + count++ + const testData = fs.readFileSync(f).toString() + const asAst = makeAstFromSrc(testData) + // now check if tree contains block with :pubdate attribute + // '* :pubdate' + if (!isExistsPubdate(asAst)) { + return + } + // extract notes - return { - pubdate, - type: "note", - node: n, - description: n, - file: f, - } - }) + const notes: pubRecord[] = getFromTree(asAst, 'para') + .filter(n => makeAttrs(n, {}).exists('pubdate')) + .map((n: PodNode) => { + const a_pubdate = makeAttrs(n, {}).getFirstValue('pubdate') + // Due to cover some cases whan new Date fail on safari, i.e. + // new Date("2022-05-07 10:00:00").getFullYear() -> NaN + // convert to ISO 8601 "2022-05-07 10:00:00" -> "2022-05-07T10:00:00" + const pubdate = a_pubdate.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/) + ? a_pubdate.replace(' ', 'T') + : a_pubdate + return { + pubdate, + type: 'note', + node: n, + description: n, + file: f, + } + }) - const articles:pubRecord[] = getAllArticles([asAst]).map(({...all})=>({...all, file:f})) - // note get full posts - const pages: pubRecord[] = getFromTree(asAst, "pod") - .filter(n => makeAttrs(n, {}).exists("pubdate")) - .map((n: PodNode) => { - const a_pubdate = makeAttrs(n, {}).getFirstValue("pubdate") - // Due to cover some cases whan new Date fail on safari, i.e. - // new Date("2022-05-07 10:00:00").getFullYear() -> NaN - // convert to ISO 8601 "2022-05-07 10:00:00" -> "2022-05-07T10:00:00" - const pubdate = a_pubdate.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/) ? a_pubdate.replace(" ","T") : a_pubdate - return { - pubdate, - type: "page", - node: n, - file: f, - } + const articles: pubRecord[] = getAllArticles([asAst]).map(({ ...all }) => ({ ...all, file: f })) + // note get full posts + const pages: pubRecord[] = getFromTree(asAst, 'pod') + .filter(n => makeAttrs(n, {}).exists('pubdate')) + .map((n: PodNode) => { + const a_pubdate = makeAttrs(n, {}).getFirstValue('pubdate') + // Due to cover some cases whan new Date fail on safari, i.e. + // new Date("2022-05-07 10:00:00").getFullYear() -> NaN + // convert to ISO 8601 "2022-05-07 10:00:00" -> "2022-05-07T10:00:00" + const pubdate = a_pubdate.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/) + ? a_pubdate.replace(' ', 'T') + : a_pubdate + return { + pubdate, + type: 'page', + node: n, + file: f, + } + }) + // console.warn( + // ` pages: ${pages.length} articles: ${articles.length}, notes: ${notes.length} from ${f}` + // ) + return [...pages, ...articles, ...notes].map(item => { + return { ...item, file: f } }) - // console.warn( - // ` pages: ${pages.length} articles: ${articles.length}, notes: ${notes.length} from ${f}` - // ) - return [...pages, ...articles, ...notes].map(item => { - return { ...item, file: f } }) - }).flat() - .filter(Boolean) + .flat() + .filter(Boolean) return allFiles -} \ No newline at end of file +} diff --git a/src/pages/[...slug].tsx b/src/pages/[...slug].tsx index 4309f11..f56cd8d 100644 --- a/src/pages/[...slug].tsx +++ b/src/pages/[...slug].tsx @@ -1,25 +1,24 @@ -import { ArticlesWithNavigation, Page } from "@Components/service" -import { contentData, getPostComponent } from "../utils" +import { ArticlesWithNavigation, Page } from '@Components/service' +import { contentData, getPostComponent } from '../utils' export default function AnyPage({ slug }) { - - const checkSlug = (slug) => ({ publishUrl }) => { - const url = "/" + slug.join("/") - return publishUrl === url - } + const checkSlug = + slug => + ({ publishUrl }) => { + const url = '/' + slug.join('/') + return publishUrl === url + } const item: any = contentData().find(checkSlug(slug)) - const allData = item.type !== 'page' ? contentData().filter(({type=''}:any)=>type !== 'page') : contentData() + const allData = item.type !== 'page' ? contentData().filter(({ type = '' }: any) => type !== 'page') : contentData() const articleIndex = allData.findIndex(checkSlug(slug)) const prev = allData[articleIndex - 1] - const current:any = allData[articleIndex] + const current: any = allData[articleIndex] const next = allData[articleIndex + 1] // wrap all elements and add line link info return ( <>
- { item.type === 'page' ? - Page(item) : - } + {item.type === 'page' ? Page(item) : }
) @@ -27,7 +26,7 @@ export default function AnyPage({ slug }) { export async function getStaticPaths() { const paths = contentData().map(({ publishUrl }) => { - const slug = publishUrl.split("/").slice(1) + const slug = publishUrl.split('/').slice(1) return { params: { slug, diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index e49765a..0425d38 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,47 +1,45 @@ -import "../../built/styles.css" -import * as img from "../../built/images" -import Head from "next/head" -import type { AppProps } from "next/app" -import { contentData, getSiteInfo } from "../utils" -import { getFromTree, getTextContentFromNode,Image } from "@podlite/schema" +import '../../built/styles.css' +import * as img from '../../built/images' +import Head from 'next/head' +import type { AppProps } from 'next/app' +import { contentData, getSiteInfo } from '../utils' +import { getFromTree, getTextContentFromNode, Image } from '@podlite/schema' function MyApp({ Component, pageProps }: AppProps) { - const {slug = []} = pageProps - const checkSlug = (slug) => ({ publishUrl }) => { - const url = "/" + slug.join("/") - return publishUrl.match(url) - } - const item: any = contentData().find(checkSlug(slug)) - const {title:siteTitle, url } = getSiteInfo() - const title = `${item?.title || ''} ${siteTitle}` - const [image] = getFromTree(item?.node, {type:"image"}) as Array - const metaImage = image?.src || null - const description = getTextContentFromNode(item?.description || []) || title - const resultUrl = url || '' - return <> - - + const { slug = [] } = pageProps + const checkSlug = + slug => + ({ publishUrl }) => { + const url = '/' + slug.join('/') + return publishUrl.match(url) + } + const item: any = contentData().find(checkSlug(slug)) + const { title: siteTitle, url } = getSiteInfo() + const title = `${item?.title || ''} ${siteTitle}` + const [image] = getFromTree(item?.node, { type: 'image' }) as Array + const metaImage = image?.src || null + const description = getTextContentFromNode(item?.description || []) || title + const resultUrl = url || '' + return ( + <> + + - { metaImage && img[metaImage] && - <> - - - - } + {metaImage && img[metaImage] && ( + <> + + + + )} - - - - + + + + ) } export default MyApp diff --git a/src/pages/index.tsx b/src/pages/index.tsx index c0b2f92..629905a 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,39 +1,36 @@ -import { PodNode } from "@podlite/schema" -import Head from "next/head" -import { generateRedirects } from "src/utils/redirects" -import { DataFeedContent } from "../../bin/makeDataSource" -import { getData, getPostComponent } from "../utils" -import { writeRss } from "../utils/rss" -import { generateSitemap } from "../utils/sitemap" +import { PodNode } from '@podlite/schema' +import Head from 'next/head' +import { generateRedirects } from 'src/utils/redirects' +import { DataFeedContent } from '../../bin/makeDataSource' +import { getData, getPostComponent } from '../utils' +import { writeRss } from '../utils/rss' +import { generateSitemap } from '../utils/sitemap' -const Home = ({title, node}:IndexProps) => { - const faviconFile = getData().siteInfo.favicon - return ( -
- - {title} - - - -
- {getPostComponent(node)} -
-
- ) - } +const Home = ({ title, node }: IndexProps) => { + const faviconFile = getData().siteInfo.favicon + return ( +
+ + {title} + + + +
{getPostComponent(node)}
+
+ ) +} interface SiteProps extends Partial {} -interface IndexProps { - url?:string, - title:string, - node:PodNode, +interface IndexProps { + url?: string + title: string + node: PodNode } -export async function getStaticProps():Promise<{ props :IndexProps}> { - writeRss() - generateSitemap() - generateRedirects() - const { title , node }:IndexProps = getData().siteInfo - return {props:{ title, node }} - +export async function getStaticProps(): Promise<{ props: IndexProps }> { + writeRss() + generateSitemap() + generateRedirects() + const { title, node }: IndexProps = getData().siteInfo + return { props: { title, node } } } export default Home diff --git a/src/shared.ts b/src/shared.ts index 9772cd3..5461e5c 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -1,57 +1,56 @@ -import { getFromTree, makeAttrs, makeInterator, PodliteDocument, PodNode } from "@podlite/schema" -import { podlite as podlite_core } from "podlite" +import { getFromTree, makeAttrs, makeInterator, PodliteDocument, PodNode } from '@podlite/schema' +import { podlite as podlite_core } from 'podlite' // now we add base60 letters -const translit = require("iso_9") -const base60 = require("newbase60") +const translit = require('iso_9') +const base60 = require('newbase60') export type pubRecord = { - type: string - pubdate: string - node: PodNode - description?: PodNode - file: string - } + type: string + pubdate: string + node: PodNode + description?: PodNode + file: string +} export type publishRecord = pubRecord & { - title: string | undefined - publishUrl: string - sources: string[] - } + title: string | undefined + publishUrl: string + sources: string[] +} export const makeAstFromSrc = (src: string) => { - let podlite = podlite_core({ importPlugins: true }).use({}) - let tree = podlite.parse(src) - const asAst = podlite.toAstResult(tree).interator as PodliteDocument - return asAst + let podlite = podlite_core({ importPlugins: true }).use({}) + let tree = podlite.parse(src) + const asAst = podlite.toAstResult(tree).interator as PodliteDocument + return asAst } export function isExistsPubdate(node: PodNode) { - let isShouldBePublished = false - const rules = { - ":block": (node, ctx, interator) => { - const config = makeAttrs(node, ctx) - if (config.exists("pubdate")) { - isShouldBePublished = true - return - } - if (Array.isArray(node.content)) { - interator(node.content) - } - }, - } - const transformer = makeInterator(rules) - const res = transformer(node, {}) - return isShouldBePublished + let isShouldBePublished = false + const rules = { + ':block': (node, ctx, interator) => { + const config = makeAttrs(node, ctx) + if (config.exists('pubdate')) { + isShouldBePublished = true + return + } + if (Array.isArray(node.content)) { + interator(node.content) + } + }, } + const transformer = makeInterator(rules) + const res = transformer(node, {}) + return isShouldBePublished +} export function getAllArticles(array) { - let articles: Omit[] = [] + let articles: Omit[] = [] const getArticles = array => { // collect alias - const aliases = array.filter(i => i.type == "alias") + const aliases = array.filter(i => i.type == 'alias') // at first collect all levels - const levels = - array.filter(node => node.level && node.name === "head") || [] + const levels = array.filter(node => node.level && node.name === 'head') || [] const nodesWithPubdate = levels.filter(node => { - return makeAttrs(node, {}).exists("pubdate") + return makeAttrs(node, {}).exists('pubdate') }) if (nodesWithPubdate.length > 0) { const nodePublished = nodesWithPubdate[0] @@ -61,19 +60,14 @@ export function getAllArticles(array) { .filter(node => node.level <= nodePublished.level) // stop then found the same or lower level .shift() - let lastIndexOfArticleNode = !nextHeader - ? array.length - : array.indexOf(nextHeader) - const articleContent = array.slice( - array.indexOf(nodePublished) + 1, - lastIndexOfArticleNode - ) + let lastIndexOfArticleNode = !nextHeader ? array.length : array.indexOf(nextHeader) + const articleContent = array.slice(array.indexOf(nodePublished) + 1, lastIndexOfArticleNode) if (articleContent.length) { - const description = getFromTree(articleContent, "para")[0] - const pubdate = makeAttrs(nodePublished, {}).getFirstValue("pubdate") + const description = getFromTree(articleContent, 'para')[0] + const pubdate = makeAttrs(nodePublished, {}).getFirstValue('pubdate') articles.push({ pubdate, - type: "page", + type: 'page', node: articleContent, description, }) @@ -89,72 +83,69 @@ export function getAllArticles(array) { return articles } export const addUrl = (items: publishRecord[]) => { - const withSxd: (publishRecord & { - number?: number - sxd: string - sequence?: number - slug?: string - })[] = items.map(i => { - const { file: f } = i - const attrs = i - const pubDate = new Date(i.pubdate) - const sxd = base60.DateToSxg(pubDate) - const type = i.type === "note" ? "n" : "a" - // make short name from title - //console.error(`process ${f}`) - let words: string[] = (attrs.title || "").split(/\s/) - let res = [] - while ([...res, words[0]].join(" ").length < 120) { - //@ts-ignore - res.push(words.shift()) - } - let shortTitle = res.join(" ") - // translit only cyrillic - const translit2 = /[а-яА-ЯЁё]/.test(shortTitle) - ? translit(shortTitle, 5) - : shortTitle - // console.log({title:attrs.TITLE, shortTitle, translit2}) - // make url clean - const slug = ((translit2.replace(/`/, "") || "").replace(/\W+/g, "-") || "") - .replace(/(^[-]+|[-]+$)/g, "") - .toLowerCase() - - return { ...attrs, type, sxd, slug, file: f } - }) - - // get count of each type on corresponding date - withSxd.reduce((acc, item) => { - const { sxd, type } = item - acc[sxd] = acc[sxd] || {} - acc[sxd][type] = acc[sxd][type] || 0 - acc[sxd][type]++ - item.number = acc[sxd][type] - return acc - }, {}) - // sequence - index of record at all in that day - withSxd.reduce((acc, item) => { - const { sxd } = item - acc[sxd] = acc[sxd] || 0 - acc[sxd]++ - item.sequence = acc[sxd] - return acc - }, {}) - - return withSxd.map(item => { - const { type, number, sxd, slug, pubdate, sequence } = item - const shortUrl = `/${type}${sxd}${number}` - // /2019/12/34/a1/WriteAt-my-opensource-startup-on-Perl-6-Pod - const date = new Date(pubdate) - const month = date.getMonth() + 1 - const year = date.getFullYear() - const day = date.getDate() - // !!!!! publishUrl may exists - const publishUrl = `/${year}/${month}/${day}/${sequence}/${slug}`.replace(/\/$/,'') - const sources = [ - shortUrl, - // `/${year}/${month}/${day}/${sequence}`, - ] - return { ...item, shortUrl, publishUrl, sources } - }) - } - \ No newline at end of file + const withSxd: (publishRecord & { + number?: number + sxd: string + sequence?: number + slug?: string + })[] = items.map(i => { + const { file: f } = i + const attrs = i + const pubDate = new Date(i.pubdate) + const sxd = base60.DateToSxg(pubDate) + const type = i.type === 'note' ? 'n' : 'a' + // make short name from title + //console.error(`process ${f}`) + let words: string[] = (attrs.title || '').split(/\s/) + let res = [] + while ([...res, words[0]].join(' ').length < 120) { + //@ts-ignore + res.push(words.shift()) + } + let shortTitle = res.join(' ') + // translit only cyrillic + const translit2 = /[а-яА-ЯЁё]/.test(shortTitle) ? translit(shortTitle, 5) : shortTitle + // console.log({title:attrs.TITLE, shortTitle, translit2}) + // make url clean + const slug = ((translit2.replace(/`/, '') || '').replace(/\W+/g, '-') || '') + .replace(/(^[-]+|[-]+$)/g, '') + .toLowerCase() + + return { ...attrs, type, sxd, slug, file: f } + }) + + // get count of each type on corresponding date + withSxd.reduce((acc, item) => { + const { sxd, type } = item + acc[sxd] = acc[sxd] || {} + acc[sxd][type] = acc[sxd][type] || 0 + acc[sxd][type]++ + item.number = acc[sxd][type] + return acc + }, {}) + // sequence - index of record at all in that day + withSxd.reduce((acc, item) => { + const { sxd } = item + acc[sxd] = acc[sxd] || 0 + acc[sxd]++ + item.sequence = acc[sxd] + return acc + }, {}) + + return withSxd.map(item => { + const { type, number, sxd, slug, pubdate, sequence } = item + const shortUrl = `/${type}${sxd}${number}` + // /2019/12/34/a1/WriteAt-my-opensource-startup-on-Perl-6-Pod + const date = new Date(pubdate) + const month = date.getMonth() + 1 + const year = date.getFullYear() + const day = date.getDate() + // !!!!! publishUrl may exists + const publishUrl = `/${year}/${month}/${day}/${sequence}/${slug}`.replace(/\/$/, '') + const sources = [ + shortUrl, + // `/${year}/${month}/${day}/${sequence}`, + ] + return { ...item, shortUrl, publishUrl, sources } + }) +} diff --git a/src/utils.tsx b/src/utils.tsx index 269a715..fcfea4c 100644 --- a/src/utils.tsx +++ b/src/utils.tsx @@ -1,13 +1,13 @@ -import React from "react" -import { PodNode, Rules, getTextContentFromNode, makeAttrs, setFn} from "@podlite/schema" -import ReactDOMServer from "react-dom/server" -import Podlite from "@podlite/to-jsx" -import d from "../built/data.json" -import * as img from "../built/images" -import * as components from "../built/components" -import { DataFeedContent } from "../bin/makeDataSource" +import React from 'react' +import { PodNode, Rules, getTextContentFromNode, makeAttrs, setFn } from '@podlite/schema' +import ReactDOMServer from 'react-dom/server' +import Podlite from '@podlite/to-jsx' +import d from '../built/data.json' +import * as img from '../built/images' +import * as components from '../built/components' +import { DataFeedContent } from '../bin/makeDataSource' import Link from 'next/link' -import { DATA_PATH } from "./constants" +import { DATA_PATH } from './constants' // POSTS_PATH is useful when you want to get the path to a specific file type pubRecord = { type: string @@ -30,7 +30,6 @@ export type DataFeed = { } } - export type FeedContent = publishRecord & { number?: number sxd: string @@ -39,10 +38,7 @@ export type FeedContent = publishRecord & { sources?: string[] shortUrl?: string } -export type ContentRecord = Pick< - FeedContent, - "publishUrl" | "title" | "node" | "sources" | "shortUrl" -> +export type ContentRecord = Pick export function getData(): DataFeedContent { //@ts-ignore return d as DataFeedContent @@ -50,15 +46,15 @@ export function getData(): DataFeedContent { // return JSON.parse(data) } -export function getSiteInfo():DataFeedContent["siteInfo"] { - return getData().siteInfo +export function getSiteInfo(): DataFeedContent['siteInfo'] { + return getData().siteInfo } export function pageNames() { const data = getData() return data.all.map(post => post.publishUrl) } -export function contentData(): DataFeedContent["all"] { +export function contentData(): DataFeedContent['all'] { const data = getData() return data.all.map(({ publishUrl, title, node, sources, pubdate, ...args }) => ({ ...args, @@ -67,7 +63,7 @@ export function contentData(): DataFeedContent["all"] { node, sources, pubdate, - shortUrl: sources[0] + shortUrl: sources[0], })) } export function mapPathToImage(path: string): string | undefined { @@ -75,39 +71,43 @@ export function mapPathToImage(path: string): string | undefined { return data[path] } export function getArticlesGroupedByYearMonth() { - //filter out pages - const source =contentData().filter(({type=''})=>type !== 'page').reverse(); - - const groupedByYearMonth = source.reduce((acc:{[year:number]:{ - [month:number]:DataFeedContent["all"] - }}, rest ) => { - const year = new Date(rest.pubdate).getFullYear() - const month = new Date(rest.pubdate).getMonth() - const { [year]:months={}, ...other } = acc - const { [month]:monthRecords=[], ...otherMonth } = months - return { - ...other, - [year]: { - ...otherMonth, - [month]: [ ...monthRecords, rest ] - } + //filter out pages + const source = contentData() + .filter(({ type = '' }) => type !== 'page') + .reverse() + + const groupedByYearMonth = source.reduce( + ( + acc: { + [year: number]: { + [month: number]: DataFeedContent['all'] } - - }, {}) - return groupedByYearMonth + }, + rest, + ) => { + const year = new Date(rest.pubdate).getFullYear() + const month = new Date(rest.pubdate).getMonth() + const { [year]: months = {}, ...other } = acc + const { [month]: monthRecords = [], ...otherMonth } = months + return { + ...other, + [year]: { + ...otherMonth, + [month]: [...monthRecords, rest], + }, + } + }, + {}, + ) + return groupedByYearMonth } export function getPostComponent(podNode: PodNode) { const plugins = (makeComponent): Partial => { - const mkComponent = - src => (writer, processor) => (node, ctx, interator) => { - // check if node.content defined - return makeComponent( - src, - node, - "content" in node ? interator(node.content, { ...ctx }) : [] - ) - } + const mkComponent = src => (writer, processor) => (node, ctx, interator) => { + // check if node.content defined + return makeComponent(src, node, 'content' in node ? interator(node.content, { ...ctx }) : []) + } return { //process only content nodes @@ -122,37 +122,36 @@ export function getPostComponent(podNode: PodNode) { TITLE: () => () => null, //@ts-ignore DESCRIPTION: () => () => null, - "L<>": setFn(( node, ctx ) => { + 'L<>': setFn((node, ctx) => { let { meta } = node - if ( meta === null) { - meta = getTextContentFromNode(node) + if (meta === null) { + meta = getTextContentFromNode(node) } - const text_content = getTextContentFromNode(node); + const text_content = getTextContentFromNode(node) //TODO: fix links to anchors - return mkComponent(({children, key })=>({text_content} - {/* {Array.isArray(children) ? children[0] : children} */} - )) - }), + return mkComponent(({ children, key }) => ( + + {text_content} + {/* {Array.isArray(children) ? children[0] : children} */} + + )) + }), React: () => (node, ctx, interator) => { const conf = makeAttrs(node, ctx) - const componentName = conf.getFirstValue("component") - const variables = Object.keys(conf.asHash()).filter((name)=>name !== "component") + const componentName = conf.getFirstValue('component') + const variables = Object.keys(conf.asHash()).filter(name => name !== 'component') // prepare simple key value pairs const props = variables.reduce((acc, name) => { - acc[name] = conf.getFirstValue(name) - return acc + acc[name] = conf.getFirstValue(name) + return acc }, {}) if (components[componentName]) { - return makeComponent( - components[componentName], - {...props}, - interator(node.content, ctx) - ) + return makeComponent(components[componentName], { ...props }, interator(node.content, ctx)) } else { return ( -
- {" "} - Not found:{" "} +
+ {' '} + Not found:{' '}
{componentName}
@@ -165,35 +164,41 @@ export function getPostComponent(podNode: PodNode) { const node = { interator: podNode, errors: {}, - toString: () => "", - valueOf: () => "", + toString: () => '', + valueOf: () => '', indexingTerms: {}, annotations: {}, defenitions: {}, } // wrap all elements and add line link info const wrapFunction = (node: PodNode, children, ctx) => { - if (typeof node !== "string" && "type" in node && node.type == "image") { + if (typeof node !== 'string' && 'type' in node && node.type == 'image') { const imageName = node.src const linkTo = ctx.link if (imageName && img[imageName]) { - const placeholder = !node.src.endsWith("gif") ? "blur" : "empty" - const Comp = ()=> { - if (node.src.endsWith("mp4")) { - return ( -
- {" "} - -
- ) - } else { - return - } + const placeholder = !node.src.endsWith('gif') ? 'blur' : 'empty' + const Comp = () => { + if (node.src.endsWith('mp4')) { + return ( +
+ {' '} + +
+ ) + } else { + return + } } - return linkTo ? : + return linkTo ? ( + + + + ) : ( + + ) } else { return ( <> diff --git a/src/utils/redirects.ts b/src/utils/redirects.ts index eab0f56..2f439c8 100644 --- a/src/utils/redirects.ts +++ b/src/utils/redirects.ts @@ -1,9 +1,9 @@ -import { PUBLIC_PATH } from "../constants"; -import * as fs from "fs" -import { getSiteInfo } from "../utils"; +import { PUBLIC_PATH } from '../constants' +import * as fs from 'fs' +import { getSiteInfo } from '../utils' export function generateRedirects() { - const {redirects} = getSiteInfo() - - fs.writeFileSync(`${PUBLIC_PATH}/vercel.json`, JSON.stringify({redirects,"cleanUrls": true},null,2)); + const { redirects } = getSiteInfo() + + fs.writeFileSync(`${PUBLIC_PATH}/vercel.json`, JSON.stringify({ redirects, cleanUrls: true }, null, 2)) } diff --git a/src/utils/rss.tsx b/src/utils/rss.tsx index 5837ab5..11894e3 100644 --- a/src/utils/rss.tsx +++ b/src/utils/rss.tsx @@ -1,7 +1,7 @@ -import { DataFeedContent } from "../../bin/makeDataSource" -import { DATA_PATH, PUBLIC_PATH } from "../constants" -import * as fs from "fs" -import { convertPodNodeToHtml as convertPodNodeToHtml, getData } from "../utils" +import { DataFeedContent } from '../../bin/makeDataSource' +import { DATA_PATH, PUBLIC_PATH } from '../constants' +import * as fs from 'fs' +import { convertPodNodeToHtml as convertPodNodeToHtml, getData } from '../utils' export function getRssForData(data: DataFeedContent) { const conf = data.siteInfo @@ -10,9 +10,7 @@ export function getRssForData(data: DataFeedContent) { ${conf.title} - + ${conf.url} ${conf.title} ru @@ -27,21 +25,21 @@ ${pages

${convertPodNodeToHtml(post.description || '')}

]]> - ` + `, ) - .join("\n")} + .join('\n')}
` } export function writeRss() { -// const dataFeed: DataFeedContent = JSON.parse( -// fs.readFileSync(DATA_PATH).toString() -// ) + // const dataFeed: DataFeedContent = JSON.parse( + // fs.readFileSync(DATA_PATH).toString() + // ) const dataFeed = getData() const pages = dataFeed.all .filter(a => a.pubdate) - .filter( page => page.description) + .filter(page => page.description) .sort((a, b) => { //@ts-ignore return new Date(a.pubdate) - new Date(b.pubdate) @@ -49,5 +47,5 @@ export function writeRss() { .reverse() .splice(0, 10) const rss = getRssForData({ ...dataFeed, all: pages }) - fs.writeFileSync(`${PUBLIC_PATH}/rss.xml`, rss); + fs.writeFileSync(`${PUBLIC_PATH}/rss.xml`, rss) } diff --git a/src/utils/sitemap.ts b/src/utils/sitemap.ts index 57fa163..5f70caf 100644 --- a/src/utils/sitemap.ts +++ b/src/utils/sitemap.ts @@ -1,28 +1,26 @@ -import { PUBLIC_PATH } from "../constants"; -import * as fs from "fs" -import { contentData, ContentRecord, getData } from "../utils"; +import { PUBLIC_PATH } from '../constants' +import * as fs from 'fs' +import { contentData, ContentRecord, getData } from '../utils' export function generateSitemap() { - const siteUrl = getData().siteInfo.url - function addPage(page:ContentRecord) { - const path = page.publishUrl - const route = path === "/index" ? "" : path; - return ` + const siteUrl = getData().siteInfo.url + function addPage(page: ContentRecord) { + const path = page.publishUrl + const route = path === '/index' ? '' : path + return ` ${`${siteUrl}${route}`} ${new Date().toISOString()} monthly 1.0 - `; - } + ` + } const pages = contentData() const sitemap = ` -${pages.map(addPage).join("\n")} -`; +${pages.map(addPage).join('\n')} +` - fs.writeFileSync(`${PUBLIC_PATH}/sitemap.xml`, sitemap); + fs.writeFileSync(`${PUBLIC_PATH}/sitemap.xml`, sitemap) } - - From cf23428d176bbbd1cd5de9afe8bf3fad802b9300 Mon Sep 17 00:00:00 2001 From: Aliaksandr Zahatski Date: Mon, 12 Feb 2024 09:12:03 +0100 Subject: [PATCH 3/4] update deps, tidy --- .vscode/settings.json | 4 +- CHANGELOG.pod6 | 2 + README.md | 54 +++---- bin/makeDataSource.ts | 303 +++++++++++++++++-------------------- decs.d.ts | 28 ++-- jest.config.js | 32 ++-- jest.tsconfig.json | 26 ++-- next.config.js | 64 ++++---- package.json | 10 +- t/index.component.spec.tsx | 20 +-- tsconfig.json | 26 +--- yarn.lock | 115 +++++++------- 12 files changed, 328 insertions(+), 356 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 55712c1..25fa621 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "typescript.tsdk": "node_modules/typescript/lib" -} \ No newline at end of file + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/CHANGELOG.pod6 b/CHANGELOG.pod6 index 9b6cfca..4bc078b 100644 --- a/CHANGELOG.pod6 +++ b/CHANGELOG.pod6 @@ -1,6 +1,8 @@ =TITLE CHANGES =head1 Upcoming +=head1 0.1.13 + =item * update dependencies =head1 0.1.12 =item * fix build error =head1 0.1.11 diff --git a/README.md b/README.md index 8d74368..bb8411c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ A minimal, lightweight starter for creating blogs/sites using nexjs and [Podlite ## QUICK GUIDE - ### using yarn It is recommended to install Yarn through the npm package manager, which comes bundled with Node.js when you install it on your system. @@ -14,25 +13,29 @@ Once you have npm installed you can run the following both to install and upgrad ```sh npm install --global yarn ``` -and then: + +and then: + ```sh yarn && yarn dev ``` -* open link [http://localhost:3000](http://localhost:3000) after -Here is demo page from `pub` directory. +- open link [http://localhost:3000](http://localhost:3000) after + +Here is demo page from `pub` directory. ![Podlite-Web demo page Screenshot](./assets/demopage1.png) ![Podlite-Web demo page Screenshot](./assets/demopage2.png) -You can edit pub/*.pod6 files and see changes after save. +You can edit pub/\*.pod6 files and see changes after save. -All features like `=Diagram`, `=Image` , `=Toc` for [Podlite editor](https://github.com/podlite/podlite-desktop) is available for podlite-web too: +All features like `=Diagram`, `=Image` , `=Toc` for [Podlite editor](https://github.com/podlite/podlite-desktop) is available for podlite-web too: ![Podlite editor Screenshot](./assets/podlite-editor.png) ### using Docker -* make `index.pod6` with the following content: +- make `index.pod6` with the following content: + ``` =begin pod =TITLE Personal blog @@ -40,26 +43,27 @@ All features like `=Diagram`, `=Image` , `=Toc` for [Podlite editor](https://gi 🚧 Web site is under construction. 🚧 =end pod ``` + run the command: ```sh docker run -it --rm -v ${PWD}:/app/pub -p 3000:3000 podlite/podlite-web dev ``` -* open link [http://localhost:3000](http://localhost:3000) -* after edit `index.pod6` web page will reload automatically - +- open link [http://localhost:3000](http://localhost:3000) +- after edit `index.pod6` web page will reload automatically #### Export to zipped static site + ```sh docker run --rm -v ${PWD}:/app/pub podlite/podlite-web export-zip > site.zip ``` #### Advance configuration -* using `https://example.com` as domain name -* customize Time Zone -* change default `index.pod6` path to subdirectory +- using `https://example.com` as domain name +- customize Time Zone +- change default `index.pod6` path to subdirectory ```sh cd examples/01-minimal @@ -72,18 +76,20 @@ podlite/podlite-web export-zip > site.zip ## Run examples ### Run minimal site + ```sh POSTS_PATH='examples/01-minimal' yarn dev ``` ### Make links between pages + ```sh POSTS_PATH='examples/02-pages' yarn dev ``` ### Blog with standalone pages and Notes from Diary -This example contains integration with ```React``` components, customize styles and publish notes from Diary document. +This example contains integration with `React` components, customize styles and publish notes from Diary document. ```sh POSTS_PATH='examples/03-blog' yarn dev @@ -101,7 +107,7 @@ yarn `yarn dev` will spin up the demosite from `pub` directory and watch changes to the files. -### Export to zip +### Export to zip ```sh yarn export-zip > file.zip @@ -111,19 +117,15 @@ Explore `examples` dir for get more pod6 insights. thank you! -Useful links ------------- +## Useful links -* ["Start your own blog/site with Podlite for Web"](https://zahatski.com/2022/8/23/1/start-you-own-blog-site-with-podlite-for-web) - how-to article -* [Podlite is a lightweight block-based markup language designed for flexibility and ease of use.](https://podlite.org) - -* Specification of Podlite: [podlite.org/specification](https://podlite.org/specification) - -* Online editor: [https://pod6.in](https://pod6.in) - -* [Podlite Desktop](https://github.com/podlite/podlite-desktop) - open-source desktop Podlite editor for Windows, Linux, and Mac. +- ["Start your own blog/site with Podlite for Web"](https://zahatski.com/2022/8/23/1/start-you-own-blog-site-with-podlite-for-web) - how-to article +- [Podlite is a lightweight block-based markup language designed for flexibility and ease of use.](https://podlite.org) +- Specification of Podlite: [podlite.org/specification](https://podlite.org/specification) +- Online editor: [https://pod6.in](https://pod6.in) +- [Podlite Desktop](https://github.com/podlite/podlite-desktop) - open-source desktop Podlite editor for Windows, Linux, and Mac. ## License This project is licensed under the terms of the -[MIT license](/LICENSE). \ No newline at end of file +[MIT license](/LICENSE). diff --git a/bin/makeDataSource.ts b/bin/makeDataSource.ts index 9627fc4..564b20c 100644 --- a/bin/makeDataSource.ts +++ b/bin/makeDataSource.ts @@ -1,5 +1,5 @@ -import * as fs from "fs" -import * as CRC32 from "crc-32" +import * as fs from 'fs' +import * as CRC32 from 'crc-32' import { POSTS_PATH, DATA_PATH, @@ -12,7 +12,7 @@ import { STYLES_LIB, SiteInfo, INDEX_PATH, -} from "../src/constants" +} from '../src/constants' import { getFromTree, getTextContentFromNode, @@ -20,13 +20,13 @@ import { makeInterator, PodliteDocument, PodNode, -} from "@podlite/schema" -import { convertFileLinksToUrl, makeLinksMap, parseFiles } from "../src/node-utils" -import { addUrl, makeAstFromSrc } from "../src/shared" +} from '@podlite/schema' +import { convertFileLinksToUrl, makeLinksMap, parseFiles } from '../src/node-utils' +import { addUrl, makeAstFromSrc } from '../src/shared' const version = require('../package.json').version -const pathFs = require("path") -const glob = require("glob") +const pathFs = require('path') +const glob = require('glob') type pubRecord = { type: string @@ -36,18 +36,17 @@ type pubRecord = { file: string } type publishRecord = pubRecord & { - title: string | undefined - publishUrl: string - sources: string[] - } - + title: string | undefined + publishUrl: string + sources: string[] +} export function isExistsPubdate(node: PodNode) { let isShouldBePublished = false const rules = { - ":block": (node, ctx, interator) => { + ':block': (node, ctx, interator) => { const config = makeAttrs(node, ctx) - if (config.exists("pubdate")) { + if (config.exists('pubdate')) { isShouldBePublished = true return } @@ -83,11 +82,11 @@ allFiles.flat().map((record: pubRecord) => { })(record.node, {}) // prepare publishUrl const conf = makeAttrs(record.node, {}) - const publishUrl = conf.exists("puburl") - ? conf.getFirstValue("puburl") - // check old publishUrl attribute - : conf.exists("publishUrl") - ? conf.getFirstValue("publishUrl") + const publishUrl = conf.exists('puburl') + ? conf.getFirstValue('puburl') + : // check old publishUrl attribute + conf.exists('publishUrl') + ? conf.getFirstValue('publishUrl') : undefined nodes.push({ ...record, title, publishUrl, sources: [], description }) }) @@ -110,16 +109,12 @@ let notPages = allItemForPublish .filter(a => !!a.pubdate) .filter(a => !isDateInFuture(a.pubdate)) -let Pages = allItemForPublish - .filter(a => a.publishUrl) - .filter(a => !(a.pubdate && isDateInFuture(a.pubdate))) +let Pages = allItemForPublish.filter(a => a.publishUrl).filter(a => !(a.pubdate && isDateInFuture(a.pubdate))) const notPagesWithPublishAttrs = addUrl(notPages) // save additional info -const nextPublishTime = ( - allItemForPublish.filter(a => isDateInFuture(a.pubdate))[0] || {} -).pubdate +const nextPublishTime = (allItemForPublish.filter(a => isDateInFuture(a.pubdate))[0] || {}).pubdate // process images const getPathToOpen = (filepath, parentDocPath) => { const isRemoteReg = new RegExp(/^(https?|ftp):/) @@ -127,25 +122,21 @@ const getPathToOpen = (filepath, parentDocPath) => { if (isRemote) { return { isRemote, path: filepath } } - const path = require("path") + const path = require('path') const docDirPath = path.dirname(parentDocPath) return { isRemote, - path: path.isAbsolute(filepath) - ? filepath - : path.normalize(path.join(docDirPath, filepath)), + path: path.isAbsolute(filepath) ? filepath : path.normalize(path.join(docDirPath, filepath)), } } const imagesMap = new Map() const componensMap = new Map() -const processNode = (node: PodNode, file:string) => { +const processNode = (node: PodNode, file: string) => { const rules = { // process JSX useReact: (node, ctx, interator) => { const text = getTextContentFromNode(node) - const importMatchResult = text.match( - /^\s*(?\S+)\s*from\s*['"](?\S+)['"]/ - ) + const importMatchResult = text.match(/^\s*(?\S+)\s*from\s*['"](?\S+)['"]/) if (importMatchResult) { //@ts-ignore const { component, source } = ( @@ -157,44 +148,38 @@ const processNode = (node: PodNode, file:string) => { // save absolute Component path and Component name const notDefaultImport = component.match(/{(.*)}/) if (notDefaultImport) { - const components = notDefaultImport[1].split(/\s*,\s*/) - // check if already exists - if (componensMap.has(path)) { - const savedComponents = componensMap.get(path) - const onlyUnique = (value, index, self) => self.indexOf(value) === index; - const newComponents = [...savedComponents, ...components].filter(onlyUnique) - componensMap.set(path, newComponents ) - } else { - componensMap.set(path, components ) - } + const components = notDefaultImport[1].split(/\s*,\s*/) + // check if already exists + if (componensMap.has(path)) { + const savedComponents = componensMap.get(path) + const onlyUnique = (value, index, self) => self.indexOf(value) === index + const newComponents = [...savedComponents, ...components].filter(onlyUnique) + componensMap.set(path, newComponents) + } else { + componensMap.set(path, components) + } } else { - componensMap.set(path, component) - + componensMap.set(path, component) } } else { - console.warn(`can't parse =React body. Expected =React Component from './somefile.tsx', but got: ${text}`) + console.warn(`can't parse =React body. Expected =React Component from './somefile.tsx', but got: ${text}`) } return }, React: (node, ctx, interator) => { - const text = getTextContentFromNode(node) - const doc:PodliteDocument = makeAstFromSrc(text) - return { ...node, content: [interator( doc.content, ctx )] } - }, - ":image": node => { + const text = getTextContentFromNode(node) + const doc: PodliteDocument = makeAstFromSrc(text) + return { ...node, content: [interator(doc.content, ctx)] } + }, + ':image': node => { // process copy files to assets - const pathMod = require("path") + const pathMod = require('path') // '../assets/' const { path } = getPathToOpen(node.src, file) const { name, ext, dir } = pathMod.parse(path) - const variable_name ='i'+ path - .split("/") - .slice(1) - .join("_") - .replace(/\W+/g, "_") - .toLowerCase() + const variable_name = 'i' + path.split('/').slice(1).join('_').replace(/\W+/g, '_').toLowerCase() const newFileName = `${variable_name}${ext}` - const dstFilename = ASSETS_PATH + "/" + newFileName + const dstFilename = ASSETS_PATH + '/' + newFileName imagesMap.set(path, variable_name) return { ...node, src: variable_name } @@ -202,9 +187,8 @@ const processNode = (node: PodNode, file:string) => { } return makeInterator(rules)(node, {}) } -const allRecords = convertFileLinksToUrl([...notPagesWithPublishAttrs, ...Pages]).map(item => { - - const node = processNode(item.node, item.file) +const allRecords = convertFileLinksToUrl([...notPagesWithPublishAttrs, ...Pages]).map(item => { + const node = processNode(item.node, item.file) // process images inside description let extra = {} as { description?: PodNode } if (item.description) { @@ -214,93 +198,95 @@ const allRecords = convertFileLinksToUrl([...notPagesWithPublishAttrs, ...Pages return { ...item, node, ...extra } }) -const getStateVersion = (allREcords:typeof allRecords):string => { - return CRC32.str(allREcords.reduce((prev,current)=>{ +const getStateVersion = (allREcords: typeof allRecords): string => { + return ( + CRC32.str( + allREcords.reduce((prev, current) => { return prev + CRC32.str(getTextContentFromNode(current.node)) - }, "")) + "+v" + version + }, ''), + ) + + '+v' + + version + ) } -const controlJson = { - stateVersion: getStateVersion(allRecords), - nextPublishTime: nextPublishTime } - - - +const controlJson = { + stateVersion: getStateVersion(allRecords), + nextPublishTime: nextPublishTime, +} // try to get index.from already exists records const indexFilePath = `${POSTS_PATH}/${INDEX_PATH}` const collectlinksMap = makeLinksMap(allRecords) const indexPageData = (() => { - - if ( fs.existsSync(indexFilePath) ) { - return fs.readFileSync(indexFilePath, "utf8") - } else { - console.warn(`${indexFilePath} not found. Continue using default template`) - return defaultIndexPage - } - })() - const indexPageTree = convertFileLinksToUrl( - [{ - node: processNode( makeAstFromSrc (indexPageData ), indexFilePath), - publishUrl: "/", - file: indexFilePath, - type: "page", - pubdate:'', - description:'', - title:'', - sources:[] - }], - collectlinksMap - )[0].node - // collect site metadata like TITLE, SUBTITLE and attributes from pod - const [pod] = getFromTree(indexPageTree, "pod") - const attr = makeAttrs(pod, {}) - const pageAttr = Object.fromEntries( - Object.keys(attr.asHash()).map(k => [k, attr.getFirstValue(k)]) - ) - const {postsPerPage, favicon, puburl, url, globalStyles } = pageAttr - - // process favicon file - - const faviconPath = favicon ? pathFs.join(pathFs.dirname(indexFilePath),favicon) : 'src/favicon.png' - const { base, ext } = pathFs.parse(faviconPath) - const faviconFileName = `favicon${ext}` - fs.copyFileSync(faviconPath, `${PUBLIC_PATH}/${faviconFileName}`) - - - let title - let subtitle - let author - - const pageNode = makeInterator({ - TITLE: (node, ctx, interator) => { - title = getTextContentFromNode(node) - }, - SUBTITLE: (node, ctx, interator) => { - subtitle = getTextContentFromNode(node) - }, - AUTHOR: (node, ctx, interator) => { - const attr = makeAttrs(node, ctx) - author = Object.fromEntries( - Object.keys(attr.asHash()).map(k => [k, attr.getFirstValue(k)]) - ) + if (fs.existsSync(indexFilePath)) { + return fs.readFileSync(indexFilePath, 'utf8') + } else { + console.warn(`${indexFilePath} not found. Continue using default template`) + return defaultIndexPage + } +})() +const indexPageTree = convertFileLinksToUrl( + [ + { + node: processNode(makeAstFromSrc(indexPageData), indexFilePath), + publishUrl: '/', + file: indexFilePath, + type: 'page', + pubdate: '', + description: '', + title: '', + sources: [], }, - })(indexPageTree, {}) - - let redirects:SiteInfo['redirects'] = [] - notPagesWithPublishAttrs.map(item=>{ - const {publishUrl, sources } = item - sources.forEach( src => { - redirects.push({source: src, destination: publishUrl, "statusCode": 308}) //permanent redirect - }) + ], + collectlinksMap, +)[0].node +// collect site metadata like TITLE, SUBTITLE and attributes from pod +const [pod] = getFromTree(indexPageTree, 'pod') +const attr = makeAttrs(pod, {}) +const pageAttr = Object.fromEntries(Object.keys(attr.asHash()).map(k => [k, attr.getFirstValue(k)])) +const { postsPerPage, favicon, puburl, url, globalStyles } = pageAttr + +// process favicon file + +const faviconPath = favicon ? pathFs.join(pathFs.dirname(indexFilePath), favicon) : 'src/favicon.png' +const { base, ext } = pathFs.parse(faviconPath) +const faviconFileName = `favicon${ext}` +fs.copyFileSync(faviconPath, `${PUBLIC_PATH}/${faviconFileName}`) + +let title +let subtitle +let author + +const pageNode = makeInterator({ + TITLE: (node, ctx, interator) => { + title = getTextContentFromNode(node) + }, + SUBTITLE: (node, ctx, interator) => { + subtitle = getTextContentFromNode(node) + }, + AUTHOR: (node, ctx, interator) => { + const attr = makeAttrs(node, ctx) + author = Object.fromEntries(Object.keys(attr.asHash()).map(k => [k, attr.getFirstValue(k)])) + }, +})(indexPageTree, {}) + +let redirects: SiteInfo['redirects'] = [] +notPagesWithPublishAttrs.map(item => { + const { publishUrl, sources } = item + sources.forEach(src => { + redirects.push({ source: src, destination: publishUrl, statusCode: 308 }) //permanent redirect }) - const siteData:SiteInfo = { - postsPerPage, favicon: faviconFileName, url:process.env.SITE_URL||url||puburl, - node:pageNode, - title, - globalStyles, - redirects - } +}) +const siteData: SiteInfo = { + postsPerPage, + favicon: faviconFileName, + url: process.env.SITE_URL || url || puburl, + node: pageNode, + title, + globalStyles, + redirects, +} export type DataFeedContent = typeof dataJson const dataJson = { @@ -313,24 +299,24 @@ const dataJson = { fs.writeFileSync(DATA_PATH, JSON.stringify(dataJson, null, 2)) // process GlobalStyles - let stylesContent = ''; - if ( siteData.globalStyles ) { - const pathFs = require("path") - const docDirPath = pathFs.dirname(STYLES_LIB) - const path = pathFs.relative(docDirPath, pathFs.join(pathFs.dirname(indexFilePath),siteData.globalStyles) ) - stylesContent += ` +let stylesContent = '' +if (siteData.globalStyles) { + const pathFs = require('path') + const docDirPath = pathFs.dirname(STYLES_LIB) + const path = pathFs.relative(docDirPath, pathFs.join(pathFs.dirname(indexFilePath), siteData.globalStyles)) + stylesContent += ` @import '${path}'; ` - } else { - const path = '@Styles/default' - stylesContent += ` +} else { + const path = '@Styles/default' + stylesContent += ` @import '${path}'; ` - } - fs.writeFileSync(STYLES_LIB, stylesContent, "utf8") +} +fs.writeFileSync(STYLES_LIB, stylesContent, 'utf8') // process Images -let libFileContent = "" +let libFileContent = '' for (const key of imagesMap.keys()) { const variable_name = imagesMap.get(key) if (!fs.existsSync(key)) { @@ -343,13 +329,13 @@ export { ${variable_name} } libFileContent += ` export default {} ` -fs.writeFileSync(IMAGE_LIB, libFileContent, "utf8") +fs.writeFileSync(IMAGE_LIB, libFileContent, 'utf8') // process Components -let componensFileContent = "" +let componensFileContent = '' for (const key of componensMap.keys()) { const componentName = componensMap.get(key) - componensFileContent += `import ${ Array.isArray(componentName) ? `{ ${componentName} }` : componentName } from "${key}" + componensFileContent += `import ${Array.isArray(componentName) ? `{ ${componentName} }` : componentName} from "${key}" export { ${componentName} } ` } @@ -357,12 +343,9 @@ componensFileContent += ` export default {} ` -fs.writeFileSync(COMPONENTS_LIB, componensFileContent, "utf8") +fs.writeFileSync(COMPONENTS_LIB, componensFileContent, 'utf8') // save control.json -fs.writeFileSync( - `${PUBLIC_PATH}/control.json`, - JSON.stringify(controlJson, null, 2) -) +fs.writeFileSync(`${PUBLIC_PATH}/control.json`, JSON.stringify(controlJson, null, 2)) console.warn(`Processed ${allFiles.length} files`) diff --git a/decs.d.ts b/decs.d.ts index 360c07e..31f498a 100644 --- a/decs.d.ts +++ b/decs.d.ts @@ -1,16 +1,16 @@ -declare module "*.scss" { - const css: { [key: string]: string }; - export default css; +declare module '*.scss' { + const css: { [key: string]: string } + export default css } -declare module "*.sass" { - const css: { [key: string]: string }; - export default css; +declare module '*.sass' { + const css: { [key: string]: string } + export default css } -declare module "react-markup"; -declare module "*.webp"; -declare module "*.png"; -declare module "*.jpg"; -declare module "*.jpeg"; -declare module "*.mp4"; -declare module "*.css"; -declare module "*.gif"; +declare module 'react-markup' +declare module '*.webp' +declare module '*.png' +declare module '*.jpg' +declare module '*.jpeg' +declare module '*.mp4' +declare module '*.css' +declare module '*.gif' diff --git a/jest.config.js b/jest.config.js index 08b3fd1..5c275e5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,22 +1,14 @@ module.exports = { - moduleDirectories: [ - 'node_modules' - ], - "modulePaths": [ - "", - ], - "snapshotSerializers": [ - "jest-serializer-html" - ], - transform: { - "\\.(t|j)sx?$": "ts-jest", + moduleDirectories: ['node_modules'], + modulePaths: [''], + snapshotSerializers: ['jest-serializer-html'], + transform: { + '\\.(t|j)sx?$': 'ts-jest', + }, + globals: { + 'ts-jest': { + tsconfig: '/jest.tsconfig.json', }, - globals: { - "ts-jest": { - "tsconfig": '/jest.tsconfig.json' - } - }, - transformIgnorePatterns: [ - "[/\\\\]node_modules[/\\\\](?!entity-decode/).+\\.js$" - ], - } \ No newline at end of file + }, + transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\](?!entity-decode/).+\\.js$'], +} diff --git a/jest.tsconfig.json b/jest.tsconfig.json index 241a5f0..91cf7f8 100644 --- a/jest.tsconfig.json +++ b/jest.tsconfig.json @@ -1,14 +1,14 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "lib": ["dom", "esnext"], - "module": "esnext", - "target": "es5", - "jsx": "react", - "esModuleInterop": true, - "downlevelIteration": true, - "allowJs": true, - "allowSyntheticDefaultImports": true - }, - "references": [ ] - } \ No newline at end of file + "extends": "./tsconfig.json", + "compilerOptions": { + "lib": ["dom", "esnext"], + "module": "esnext", + "target": "es5", + "jsx": "react", + "esModuleInterop": true, + "downlevelIteration": true, + "allowJs": true, + "allowSyntheticDefaultImports": true + }, + "references": [] +} diff --git a/next.config.js b/next.config.js index 7dab397..ed6b767 100644 --- a/next.config.js +++ b/next.config.js @@ -1,23 +1,24 @@ // const isDev = process.env.NODE_ENV !== "production"; -const path = require("path"); -const withPlugins = require("next-compose-plugins"); -const optimizedImages = require("next-optimized-images"); +const path = require('path') +const withPlugins = require('next-compose-plugins') +const optimizedImages = require('next-optimized-images') module.exports = withPlugins([ - [optimizedImages, - { - // assetPrefix: isDev ? "" : `/`, - handleImages: ["jpeg", "jpg", "png", "svg"], - // optimizeImages: { - /* config for next-optimized-images */ - mozjpeg: { - quality: 70, - }, - optipng: { - optimizationLevel: 3, - }, - optimizeImagesInDev: true, - // } - }, + [ + optimizedImages, + { + // assetPrefix: isDev ? "" : `/`, + handleImages: ['jpeg', 'jpg', 'png', 'svg'], + // optimizeImages: { + /* config for next-optimized-images */ + mozjpeg: { + quality: 70, + }, + optipng: { + optimizationLevel: 3, + }, + optimizeImagesInDev: true, + // } + }, ], { images: { @@ -25,19 +26,18 @@ module.exports = withPlugins([ }, reactStrictMode: true, // esModule: true, - webpack: (config) => { - const assetRegex = new RegExp(`.(png|jpe?g|gif|woff|woff2|ico|svg|mp4)$`); - config.resolve.alias["@Components"] = path.resolve("./src/components"), - config.resolve.alias["@Styles"] = path.resolve("./src/styles"), - config.module.rules.push({ - test: assetRegex, - type: "asset/resource", - generator: { - filename: "./static/assets/[name]-[contenthash].[ext]", - }, - }); - return config; + webpack: config => { + const assetRegex = new RegExp(`.(png|jpe?g|gif|woff|woff2|ico|svg|mp4)$`) + ;(config.resolve.alias['@Components'] = path.resolve('./src/components')), + (config.resolve.alias['@Styles'] = path.resolve('./src/styles')), + config.module.rules.push({ + test: assetRegex, + type: 'asset/resource', + generator: { + filename: './static/assets/[name]-[contenthash].[ext]', + }, + }) + return config }, }, -]); - +]) diff --git a/package.json b/package.json index f297123..2c7401d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "podlite-web", "description": "A minimal, lightweight starter for creating static blogs/sites using nexjs and Podlite markup language", - "version": "0.1.12", + "version": "0.1.13", "private": true, "scripts": { "next_dev": "next dev", @@ -16,7 +16,7 @@ "clean": "rimraf 'built/!(.gitignore)' 'public/assets/!(.gitignore)' .next out 'public/!(.gitignore)' site", "process": "yarn clean && mkdir -p built && ts-node -P tsconfig-node.json bin/makeDataSource.ts", "dev": "npx nodemon --watch ./examples --watch ./pub -e pod6 --exec 'yarn clean && yarn process && next dev'", - "format": "prettier --write 'src/**/*.{ts,tsx}'" + "format": "npx prettier --write '**/*.{js,jsx,ts,tsx,json,md,mjs}'" }, "dependencies": { "next": "12.0.10", @@ -24,8 +24,8 @@ "react-dom": "17.0.2" }, "devDependencies": { - "@podlite/schema": "^0.0.12", - "@podlite/to-jsx": "^0.0.16", + "@podlite/schema": "^0.0.14", + "@podlite/to-jsx": "^0.0.18", "@types/jest": "^27.5.1", "@types/node": "17.0.17", "@types/react": "17.0.39", @@ -42,7 +42,7 @@ "next-images": "^1.8.4", "next-optimized-images": "^2.6.2", "nodemon": "^2.0.16", - "podlite": "^0.0.25", + "podlite": "^0.0.27", "prettier": "^2.5.1", "react-modal": "^3.14.4", "rimraf": "^3.0.2", diff --git a/t/index.component.spec.tsx b/t/index.component.spec.tsx index c463656..c62c25d 100644 --- a/t/index.component.spec.tsx +++ b/t/index.component.spec.tsx @@ -1,25 +1,25 @@ -import makeInterator from "@podlite/schema/lib/ast-inerator" -import React from "react" -import { addUrl } from "../src/shared" -import { convertFileLinksToUrl, parseFiles } from "../src/node-utils" -import { getTextContentFromNode } from "@podlite/schema" +import makeInterator from '@podlite/schema/lib/ast-inerator' +import React from 'react' +import { addUrl } from '../src/shared' +import { convertFileLinksToUrl, parseFiles } from '../src/node-utils' +import { getTextContentFromNode } from '@podlite/schema' -it("parseFiles", () => { - const arr = parseFiles("./t/test-linking/*.pod6") +it('parseFiles', () => { + const arr = parseFiles('./t/test-linking/*.pod6') // console.log(JSON.stringify(arr, null, 2)); expect(arr.length).toEqual(2) // console.log(parseToHtml(nodes)); // expect(parseToHtml(pod)).toMatchInlineSnapshot( // expect(true).toEqual(true) }) -it("collect links", () => { - const arr = parseFiles("./t/test-linking/*.pod6") +it('collect links', () => { + const arr = parseFiles('./t/test-linking/*.pod6') const converted = convertFileLinksToUrl(addUrl(arr)) const res = converted .map(({ node }) => { let links: any[] = [] makeInterator({ - "L<>": ({ content, meta }) => { + 'L<>': ({ content, meta }) => { links = [...links, meta ? meta : getTextContentFromNode(content)] }, })(node, {}) diff --git a/tsconfig.json b/tsconfig.json index 2dc63bc..5bd3321 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,11 +8,7 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "noEmit": true, "moduleResolution": "node", @@ -23,21 +19,11 @@ "downlevelIteration": true, "allowSyntheticDefaultImports": true, "paths": { - "@Components/*": [ - "src/components/*" - ], - "@Styles/*": [ - "src/styles/*" - ], - "src/*": ["src/*"] + "@Components/*": ["src/components/*"], + "@Styles/*": ["src/styles/*"], + "src/*": ["src/*"] } }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx" - ], - "exclude": [ - "node_modules" - ] + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index f40e15a..1caf68f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -932,89 +932,93 @@ __metadata: languageName: node linkType: hard -"@podlite/diagram@npm:^0.0.16": - version: 0.0.16 - resolution: "@podlite/diagram@npm:0.0.16" +"@podlite/diagram@npm:^0.0.18": + version: 0.0.18 + resolution: "@podlite/diagram@npm:0.0.18" dependencies: - "@podlite/schema": 0.0.12 + "@podlite/schema": 0.0.14 mermaid: 8.12.1 react-is: ^17.0.2 peerDependencies: mermaid: "*" - react: "*" - react-dom: "*" + react: "^16.0.0 || ^17.0.0 " + react-dom: ^16.0.0 || ^17.0.0 react-is: "*" - checksum: 44438743e576b0ea1b71834e91bc1a884cd2438004cb90aae69504246394c2ddb86b2e3e92699c154f93fd946680a319bdfeb352284ac4119b442576d612bbe6 + checksum: ee4f0f53cffa4cf1aea8aee590347b93b3d252f278e63ca57aa7d88994dac95d3627224554e7e3c2c5fb63542c3c1c51b796e028de8b7e3b3bc5d21d58702d8d languageName: node linkType: hard -"@podlite/image@npm:^0.0.11": - version: 0.0.11 - resolution: "@podlite/image@npm:0.0.11" +"@podlite/image@npm:^0.0.13": + version: 0.0.13 + resolution: "@podlite/image@npm:0.0.13" dependencies: - "@podlite/schema": ^0.0.12 - checksum: cccab6bae7ad9c5e4221537fdb6eb5ed4465f45164da8c0c3a12e7cb5be01639cc53157a4b7f3f42eacea3952b54bf9e4d92bf8cec5b6fe2125b41b8633df445 + "@podlite/schema": ^0.0.14 + peerDependencies: + react: "^16.0.0 || ^17.0.0 " + react-dom: ^16.0.0 || ^17.0.0 + checksum: cae1a403db94b5187c153ebd6e97509f6029bb664bde29258f9c0942ebf7ddc4785ed4df4075cf3c98671a8b6139a48cc83eb5e6bcfc1b5c37b765a5003dcf3b languageName: node linkType: hard -"@podlite/markdown@npm:0.0.5": - version: 0.0.5 - resolution: "@podlite/markdown@npm:0.0.5" +"@podlite/markdown@npm:0.0.7": + version: 0.0.7 + resolution: "@podlite/markdown@npm:0.0.7" dependencies: - "@podlite/schema": 0.0.12 - react: ^16.0.0 || ^17.0.0 + "@podlite/schema": 0.0.14 + react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - react-is: ^17.0.2 + react-is: ^17.0.0 remark-gfm: ^3.0.1 remark-parse: ^10.0.1 unified: ^10.1.2 peerDependencies: - react: ^16.0.0 || ^17.0.0 + react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: e79a93f4de15e5403f5afa8689ebac47f59dc80de563decd614752d806ff1111124036b499a04d34e3e6782ff41364c9d11c01802751a40564394217181c920f + checksum: d2760c035c9e39dc8ddd94374e4933cc271abc2d1b806e5a0a6df7fd52161dc0575e8839515812334b1fd6f7c85e57de6d8146fc9827673b9ce7afdb80a016e7 languageName: node linkType: hard -"@podlite/schema@npm:0.0.12, @podlite/schema@npm:^0.0.12": - version: 0.0.12 - resolution: "@podlite/schema@npm:0.0.12" +"@podlite/schema@npm:0.0.14, @podlite/schema@npm:^0.0.14": + version: 0.0.14 + resolution: "@podlite/schema@npm:0.0.14" dependencies: ajv: ^7.2.3 events: ^3.1.0 json-pointer: ^0.6.1 nanoid: 3.1.30 - checksum: 4fe1293bf9764d2a594bb60508925f15ca159473e0abacc152b58f21477b61c2df2a1f1582af72ce02d6e2e0afe1c7b8a2972fac1621a99ab57d75a1de170fa4 + checksum: 1bbb2041117a3c99b17ba51982bd037205c4a592634ba9a95c499c3cd49ee55bb1c119920ff943b3f9dcfdc4ebd7cbdd335abdc3e110f8019edf78316d7c8e1f languageName: node linkType: hard -"@podlite/to-jsx@npm:^0.0.16": - version: 0.0.16 - resolution: "@podlite/to-jsx@npm:0.0.16" +"@podlite/to-jsx@npm:^0.0.18": + version: 0.0.18 + resolution: "@podlite/to-jsx@npm:0.0.18" dependencies: - "@podlite/diagram": ^0.0.16 - "@podlite/schema": 0.0.12 - react-is: ^17.0.2 + "@podlite/diagram": ^0.0.18 + "@podlite/schema": 0.0.14 + podlite: 0.0.27 + react-is: ^17.0.0 peerDependencies: "@podlite/diagram": "*" "@podlite/schema": "*" - react: ^16.0.0 || ^17.0.0 + react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: 99082ba56250ab75a521cd285318de6294c0d27653a518bcbe9a22161bf463fd2b20fc3bacae8a9769bc8ee270220c92ef3ab075c2798cc9aecdc89806b98cfb + checksum: 25563b020e1e9b904219acc7ab7f62e52b27f3784c9732b8eed63ef632e4bb03c0b3ea4da34e3660eac61f6d2eef306ab37ee36c6889b24ceacc0c7d21f204c6 languageName: node linkType: hard -"@podlite/toc@npm:0.0.5": - version: 0.0.5 - resolution: "@podlite/toc@npm:0.0.5" +"@podlite/toc@npm:0.0.7": + version: 0.0.7 + resolution: "@podlite/toc@npm:0.0.7" dependencies: - "@podlite/schema": 0.0.12 - react: ^16.0.0 || ^17.0.0 + "@podlite/schema": 0.0.14 + react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - react-is: ^17.0.2 + react-is: ^17.0.0 peerDependencies: - react: ^16.0.0 || ^17.0.0 + react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: 9e8dfd3fc7a7a2cc8a956090c9d3411ed90488581fa7d864f75685f33c653df76e18f0e348f36ce361c6fd82be89a4984c39b256ab32a180287f8afbb02804d8 + checksum: e00fe20f05366fa4b8547a45106b383b050dce4a75b69a03b6bf847657aa54a8f6ba6105ffe8a9503d5c009d1fc5aa4407045ce79b830e97092c41cacb7d22b2 languageName: node linkType: hard @@ -7078,8 +7082,8 @@ __metadata: version: 0.0.0-use.local resolution: "podlite-web@workspace:." dependencies: - "@podlite/schema": ^0.0.12 - "@podlite/to-jsx": ^0.0.16 + "@podlite/schema": ^0.0.14 + "@podlite/to-jsx": ^0.0.18 "@types/jest": ^27.5.1 "@types/node": 17.0.17 "@types/react": 17.0.39 @@ -7097,7 +7101,7 @@ __metadata: next-images: ^1.8.4 next-optimized-images: ^2.6.2 nodemon: ^2.0.16 - podlite: ^0.0.25 + podlite: ^0.0.27 prettier: ^2.5.1 react: 17.0.2 react-dom: 17.0.2 @@ -7111,17 +7115,20 @@ __metadata: languageName: unknown linkType: soft -"podlite@npm:^0.0.25": - version: 0.0.25 - resolution: "podlite@npm:0.0.25" +"podlite@npm:0.0.27, podlite@npm:^0.0.27": + version: 0.0.27 + resolution: "podlite@npm:0.0.27" dependencies: - "@podlite/diagram": ^0.0.16 - "@podlite/image": ^0.0.11 - "@podlite/markdown": 0.0.5 - "@podlite/schema": ^0.0.12 - "@podlite/toc": 0.0.5 + "@podlite/diagram": ^0.0.18 + "@podlite/image": ^0.0.13 + "@podlite/markdown": 0.0.7 + "@podlite/schema": ^0.0.14 + "@podlite/toc": 0.0.7 nanoid: 3.1.30 - checksum: ccfb47b970b416e0d3ff8538d489a44bb8ed8ebea5761ee18130ab57d54692f9ab4b39af507ffaa4bf927fc88c05cd92db9a17b787cc924a9251d69b77b933b7 + peerDependencies: + react: ^16.0.0 || ^17.0.0 + react-dom: ^16.0.0 || ^17.0.0 + checksum: 0e529f2ff73603231abdb70ee2097c1c792f8796d9e4901c229bbb0a1bf4e8712f7a752dd3d9aa50f73228002664a2d2e5ce5ff83498249dde709a30e396cab3 languageName: node linkType: hard @@ -7313,7 +7320,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.1, react-is@npm:^17.0.2": +"react-is@npm:^17.0.0, react-is@npm:^17.0.1, react-is@npm:^17.0.2": version: 17.0.2 resolution: "react-is@npm:17.0.2" checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 @@ -7349,7 +7356,7 @@ __metadata: languageName: node linkType: hard -"react@npm:17.0.2, react@npm:^16.0.0 || ^17.0.0": +"react@npm:17.0.2, react@npm:^16.0.0 || ^17.0.0 ": version: 17.0.2 resolution: "react@npm:17.0.2" dependencies: From 4e3d1fcf6667068f25fb52e59b224d6d93f7d57c Mon Sep 17 00:00:00 2001 From: Aliaksandr Zahatski Date: Tue, 13 Feb 2024 09:16:15 +0100 Subject: [PATCH 4/4] new release --- CHANGELOG.pod6 | 3 ++ next.config.js | 1 + package.json | 8 ++--- yarn.lock | 86 +++++++++++++++++++++++++------------------------- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.pod6 b/CHANGELOG.pod6 index 4bc078b..195033e 100644 --- a/CHANGELOG.pod6 +++ b/CHANGELOG.pod6 @@ -1,6 +1,9 @@ =TITLE CHANGES =head1 Upcoming +=head1 0.1.14 +=item * C<=toc>, C<=markdown> are now standard blocks +=item * update dependencies =head1 0.1.13 =item * update dependencies =head1 0.1.12 diff --git a/next.config.js b/next.config.js index ed6b767..0c43d3d 100644 --- a/next.config.js +++ b/next.config.js @@ -37,6 +37,7 @@ module.exports = withPlugins([ filename: './static/assets/[name]-[contenthash].[ext]', }, }) + config.resolve.symlinks = false return config }, }, diff --git a/package.json b/package.json index 2c7401d..ce9e456 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "podlite-web", "description": "A minimal, lightweight starter for creating static blogs/sites using nexjs and Podlite markup language", - "version": "0.1.13", + "version": "0.1.14", "private": true, "scripts": { "next_dev": "next dev", @@ -24,8 +24,8 @@ "react-dom": "17.0.2" }, "devDependencies": { - "@podlite/schema": "^0.0.14", - "@podlite/to-jsx": "^0.0.18", + "@podlite/schema": "^0.0.15", + "@podlite/to-jsx": "^0.0.19", "@types/jest": "^27.5.1", "@types/node": "17.0.17", "@types/react": "17.0.39", @@ -42,7 +42,7 @@ "next-images": "^1.8.4", "next-optimized-images": "^2.6.2", "nodemon": "^2.0.16", - "podlite": "^0.0.27", + "podlite": "^0.0.28", "prettier": "^2.5.1", "react-modal": "^3.14.4", "rimraf": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 1caf68f..8092d2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -932,11 +932,11 @@ __metadata: languageName: node linkType: hard -"@podlite/diagram@npm:^0.0.18": - version: 0.0.18 - resolution: "@podlite/diagram@npm:0.0.18" +"@podlite/diagram@npm:^0.0.19": + version: 0.0.19 + resolution: "@podlite/diagram@npm:0.0.19" dependencies: - "@podlite/schema": 0.0.14 + "@podlite/schema": 0.0.15 mermaid: 8.12.1 react-is: ^17.0.2 peerDependencies: @@ -944,27 +944,27 @@ __metadata: react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 react-is: "*" - checksum: ee4f0f53cffa4cf1aea8aee590347b93b3d252f278e63ca57aa7d88994dac95d3627224554e7e3c2c5fb63542c3c1c51b796e028de8b7e3b3bc5d21d58702d8d + checksum: cff184c7592186777f32a2151505991fe58ca7ad88c07dbf6d942a1ea5e01dabafaa49323dc3a11bdc6ce8730cea57b7322679fe12d08dd3f7c94ac55356a10e languageName: node linkType: hard -"@podlite/image@npm:^0.0.13": - version: 0.0.13 - resolution: "@podlite/image@npm:0.0.13" +"@podlite/image@npm:^0.0.14": + version: 0.0.14 + resolution: "@podlite/image@npm:0.0.14" dependencies: - "@podlite/schema": ^0.0.14 + "@podlite/schema": ^0.0.15 peerDependencies: react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: cae1a403db94b5187c153ebd6e97509f6029bb664bde29258f9c0942ebf7ddc4785ed4df4075cf3c98671a8b6139a48cc83eb5e6bcfc1b5c37b765a5003dcf3b + checksum: 7297fb2ebcd1a5d292909fe1653ad8fcdc08d0c7b35c25a0dc5f5456601aa6815efb2fda9acdf4a5001d893b706c0569b4a332c8db440ec828e17ca8e13704c4 languageName: node linkType: hard -"@podlite/markdown@npm:0.0.7": - version: 0.0.7 - resolution: "@podlite/markdown@npm:0.0.7" +"@podlite/markdown@npm:0.0.8": + version: 0.0.8 + resolution: "@podlite/markdown@npm:0.0.8" dependencies: - "@podlite/schema": 0.0.14 + "@podlite/schema": 0.0.15 react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 react-is: ^17.0.0 @@ -974,51 +974,51 @@ __metadata: peerDependencies: react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: d2760c035c9e39dc8ddd94374e4933cc271abc2d1b806e5a0a6df7fd52161dc0575e8839515812334b1fd6f7c85e57de6d8146fc9827673b9ce7afdb80a016e7 + checksum: c959f6e171494ec54b2f60641d05628708830b4418a7a6eea0fa24d38b44011c3cfe342ad409f6016c44657c87c705dd2bb3b455680727270f0ce74c1df05a51 languageName: node linkType: hard -"@podlite/schema@npm:0.0.14, @podlite/schema@npm:^0.0.14": - version: 0.0.14 - resolution: "@podlite/schema@npm:0.0.14" +"@podlite/schema@npm:0.0.15, @podlite/schema@npm:^0.0.15": + version: 0.0.15 + resolution: "@podlite/schema@npm:0.0.15" dependencies: ajv: ^7.2.3 events: ^3.1.0 json-pointer: ^0.6.1 nanoid: 3.1.30 - checksum: 1bbb2041117a3c99b17ba51982bd037205c4a592634ba9a95c499c3cd49ee55bb1c119920ff943b3f9dcfdc4ebd7cbdd335abdc3e110f8019edf78316d7c8e1f + checksum: 769e4e622c6743e545f186e5c70995e8eaa87a4e0e49f249c0120c6789667ec3222f33f6cf35f0221b273024f7670ca3e7b093bcf981e9ea4dac821519d87f4e languageName: node linkType: hard -"@podlite/to-jsx@npm:^0.0.18": - version: 0.0.18 - resolution: "@podlite/to-jsx@npm:0.0.18" +"@podlite/to-jsx@npm:^0.0.19": + version: 0.0.19 + resolution: "@podlite/to-jsx@npm:0.0.19" dependencies: - "@podlite/diagram": ^0.0.18 - "@podlite/schema": 0.0.14 - podlite: 0.0.27 + "@podlite/diagram": ^0.0.19 + "@podlite/schema": 0.0.15 + podlite: 0.0.28 react-is: ^17.0.0 peerDependencies: "@podlite/diagram": "*" "@podlite/schema": "*" react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: 25563b020e1e9b904219acc7ab7f62e52b27f3784c9732b8eed63ef632e4bb03c0b3ea4da34e3660eac61f6d2eef306ab37ee36c6889b24ceacc0c7d21f204c6 + checksum: 9a1c42b186821f9c3abbdfdf9aa57ffacf5e3366e82d80a66b5bb9872ec60a5d2cb92a5899993e7bbf2920a177f8446a934cf30fbb2448cf1532656d1d2e1147 languageName: node linkType: hard -"@podlite/toc@npm:0.0.7": - version: 0.0.7 - resolution: "@podlite/toc@npm:0.0.7" +"@podlite/toc@npm:0.0.8": + version: 0.0.8 + resolution: "@podlite/toc@npm:0.0.8" dependencies: - "@podlite/schema": 0.0.14 + "@podlite/schema": 0.0.15 react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 react-is: ^17.0.0 peerDependencies: react: "^16.0.0 || ^17.0.0 " react-dom: ^16.0.0 || ^17.0.0 - checksum: e00fe20f05366fa4b8547a45106b383b050dce4a75b69a03b6bf847657aa54a8f6ba6105ffe8a9503d5c009d1fc5aa4407045ce79b830e97092c41cacb7d22b2 + checksum: 736dd74d5dc3f1c2013a3d680390b47be1398c47935c914468c98c4e385903cd4bcb965e219967f5e2f32b0c81862287829ef82864ddcd68b47083317bcfb3af languageName: node linkType: hard @@ -7082,8 +7082,8 @@ __metadata: version: 0.0.0-use.local resolution: "podlite-web@workspace:." dependencies: - "@podlite/schema": ^0.0.14 - "@podlite/to-jsx": ^0.0.18 + "@podlite/schema": ^0.0.15 + "@podlite/to-jsx": ^0.0.19 "@types/jest": ^27.5.1 "@types/node": 17.0.17 "@types/react": 17.0.39 @@ -7101,7 +7101,7 @@ __metadata: next-images: ^1.8.4 next-optimized-images: ^2.6.2 nodemon: ^2.0.16 - podlite: ^0.0.27 + podlite: ^0.0.28 prettier: ^2.5.1 react: 17.0.2 react-dom: 17.0.2 @@ -7115,20 +7115,20 @@ __metadata: languageName: unknown linkType: soft -"podlite@npm:0.0.27, podlite@npm:^0.0.27": - version: 0.0.27 - resolution: "podlite@npm:0.0.27" +"podlite@npm:0.0.28, podlite@npm:^0.0.28": + version: 0.0.28 + resolution: "podlite@npm:0.0.28" dependencies: - "@podlite/diagram": ^0.0.18 - "@podlite/image": ^0.0.13 - "@podlite/markdown": 0.0.7 - "@podlite/schema": ^0.0.14 - "@podlite/toc": 0.0.7 + "@podlite/diagram": ^0.0.19 + "@podlite/image": ^0.0.14 + "@podlite/markdown": 0.0.8 + "@podlite/schema": ^0.0.15 + "@podlite/toc": 0.0.8 nanoid: 3.1.30 peerDependencies: react: ^16.0.0 || ^17.0.0 react-dom: ^16.0.0 || ^17.0.0 - checksum: 0e529f2ff73603231abdb70ee2097c1c792f8796d9e4901c229bbb0a1bf4e8712f7a752dd3d9aa50f73228002664a2d2e5ce5ff83498249dde709a30e396cab3 + checksum: 529ce3425444364ab60adf81587cf71f9459471ac571abeb52831ffbd100b583082a987bfe5c8b75bdaf0d27f92e13f5238d1c39348cb53c5deb0e90293e3000 languageName: node linkType: hard