npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

wordpress-to-asstro-ssg

v2.9.0

Published

export wordpress content into an Astro SSG project.

Downloads

469

Readme

wordpress-to-asstro-ssg

NPM Git

export WordPress content into an Astro SSG project.

This is for Astro projects configured for a static output using the local files router.

There are two parts to this project.

PART 1: The data collections.

In your Astro content config, ./src/content/config.ts, we need to tell Astro what the WordPress data schemas are.

To do this, provide the used WordPress schemas ( ex: Posts and Pages ) definitions to this config file.

ex:

import {definePosts, definePages} from "wordpress-to-asstro-ssg";

export const collections = {
	posts: definePosts,
	pages: definePages
};

PART 2: Generating the data

To use the data in Wordpress, we will generate local JSON files. We also need to collect the assets.

to do so, make a node script for your project.

In this script, first import as source by copying this line:

import { generateContentFromWP } from 'wordpress-to-asstro-ssg/node_src/genContentFromWP.mjs';

And you may need to include any shared dependencies in your project as well.

Now call the generate function with your own options in a new file. Here, I'm using the file ./node_src/genContentFromWP.mjs.

example:


await generateContentFromWP({
  processStringDataValueFn: processWPStringItem,
  srcContentFolder: `./src/content`,
  publicAssetsFolder: `./public/wp`,
  exportData: true,
  exportMedia: true,
  encoding: "utf8",
  wp_api_endpoint: 'https://staging.mywordpress.com/wp-json/',
})

And include the string processing function. WordPress content may be improperly encoded, and will depend on your setup.

Since this may be different on each setup, you are required to supply this function.

WARN: This is the main cause of unexpected characters on the output JSON.

For example, here is a starting point:

import utf8 from "utf8";
import unidecode from "unidecode";
import {decode} from 'html-entities';
import { generateContentFromWP } from 'wordpress-to-asstro-ssg/node_src/genContentFromWP.mjs';

const processWPStringItem = ( item ) => {
  // HTML entities decode
  item = decode( item );
  // UNIcode decode
  item = unidecode( item );
  // UTF8 decode
  item = utf8.decode( item );
  // urls
  item = item.replaceAll( "http://mywordpress/", "" );
  item = item.replaceAll( "https://mywordpress/", "" );
  item = item.replaceAll( "http://staging.mywordpress/", "" );
  item = item.replaceAll( "https://staging.mywordpress/", "" );
  item = item.replaceAll( "http://mywordpress", "" );
  item = item.replaceAll( "https://mywordpress", "" );
  item = item.replaceAll( "http://staging.mywordpress", "" );
  item = item.replaceAll( "https://staging.mywordpress", "" );
  // media paths
  item = item.replaceAll( "wp-content/", "/wp/" );
  // strange edge cases
  item = item.replaceAll( "wp-json/wp/v2/", "" );
  // Extras
  return item;
}

Next, run this script with node, ex:

node ./bin/genContentFromWP.mjs

This will access your WordPress instance and generate the JSON data as well as copying over any assets from WordPress.

At this point, you can access the data with Astro. Example:

const pages = (await getCollection('pages')).sort(
	(a, b) => a.data.modified.valueOf() - b.data.modified.valueOf()
);

NOTE:

The library that is fetching the data is a bit old now, and the specific fork that I am using here is not robust. It works for now, but I expect that this might cause errors at some point.

Bonus: SiteMap

I also wanted a SiteMap data structure for my projects, which is included here.


import {getAstroSitemap} from "wordpress-to-asstro-ssg";
let siteMap = await getAstroSitemap();

<section>
  <h4>Pages:</h4>
  <ul>
    {
      _.map(Object.values( siteMap.pages ), (parent) => (
          parent.isRootItem &&
          <li>
            <a href={`/${parent.data.slug}/`}>
              <h4 class="title">{parent.data.title.rendered}</h4>
            </a>

            { parent.children &&
                <ul>
                  {
                    _.map(Object.values( parent.children ), (child) => (
                        <li>
                          <a href={`/${child.data.slug}/`}>
                            <h5 class="title">{child.data.title.rendered}</h5>
                          </a>
                          
                          // and so on, deep nesting needs better JSX logic here 
                          
                        </li>
                    ))
                  }
                </ul>
            }
          </li>
      ))
    }
  </ul>

  <br />
  <br />
  <br />

  <h4>Posts:</h4>
  <ul>

    {
      _.map(Object.values( siteMap.posts ), (parent) => (
          <li>
            <a href={`/${parent.data.slug}/`}>
              <h4 class="title">{parent.data.title.rendered}</h4>
            </a>
          </li>
      ))
    }
  </ul>
</section>

Then, Astro can build the sitemap.xml files with this config in the astro.config.mjs file:

import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://mywebsite.com',
  integrations: [
    sitemap(),
  ]
});