Skip to content

Instantly share code, notes, and snippets.

@samselikoff
Last active May 6, 2021 14:18
Show Gist options
  • Save samselikoff/38c59bdff8ca619a87c28e9c8d8b99f9 to your computer and use it in GitHub Desktop.
Save samselikoff/38c59bdff8ca619a87c28e9c8d8b99f9 to your computer and use it in GitHub Desktop.

Revisions

  1. samselikoff revised this gist May 4, 2021. 1 changed file with 98 additions and 0 deletions.
    98 changes: 98 additions & 0 deletions next.config.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    let { withProse } = require("./src/remark/withProse");
    let { withSyntaxHighlighting } = require("./src/remark/withSyntaxHighlighting");
    let { withTableOfContents } = require("./src/remark/withTableOfContents");
    let { withExamples } = require("./src/remark/withExamples");
    let { withLayout } = require("./src/remark/withLayout");
    let { withNextLinks } = require("./src/remark/withNextLinks");
    let { VueLoaderPlugin } = require("vue-loader");
    let path = require("path");

    const withMDX = require("@next/mdx")({
    options: {
    remarkPlugins: [
    withProse,
    withSyntaxHighlighting,
    withTableOfContents,
    withNextLinks,
    withExamples,
    withLayout,
    ],
    },
    });
    module.exports = withMDX({
    pageExtensions: ["js", "jsx", "mdx"],

    async redirects() {
    return [
    { source: "/react", destination: "/", permanent: false },
    { source: "/vue", destination: "/", permanent: false },
    ];
    },

    webpack(config) {
    config.resolveLoader.modules.push(
    path.resolve(__dirname, "src", "loaders")
    );

    config.module.rules.push({
    test: /\.(png|jpe?g|gif)$/i,
    use: [
    {
    loader: "file-loader",
    options: {
    publicPath: "/_next",
    name: "static/media/[name].[hash].[ext]",
    },
    },
    ],
    });

    config.module.rules.push({
    test: /\.svg$/,
    use: (resource) => {
    // this is to make it so each svg import has a unique id. when importing
    // an svg use the resource query to modify the id...
    // example:
    // import { ReactComponent as Icon } from "@/svgs/my-icon?uniqueId"
    //
    let svg = path.parse(resource.resource).name;
    let id = resource.resourceQuery
    ? resource.resourceQuery.replace(/^\?/, "_")
    : "_";
    let prefix = `${svg}-${id}`;
    return [
    {
    loader: "@svgr/webpack",
    options: {
    svgoConfig: {
    plugins: [
    {
    prefixIds: {
    prefix,
    },
    },
    ],
    },
    },
    },
    {
    loader: "file-loader",
    options: {
    publicPath: "/_next",
    name: "static/media/[name].[hash].[ext]",
    },
    },
    ];
    },
    });

    config.module.rules.push({
    test: /\.vue$/,
    loader: "vue-loader",
    });

    config.plugins.push(new VueLoaderPlugin());

    return config;
    },
    });
  2. samselikoff created this gist May 4, 2021.
    47 changes: 47 additions & 0 deletions withProse.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    /*
    Usage:
    const withMDX = require("@next/mdx")({
    options: {
    remarkPlugins: [
    withProse,
    ],
    },
    });
    */

    const proseComponents = ["Heading"];

    const isJsNode = (node) => {
    return (
    ["jsx", "import", "export"].includes(node.type) &&
    !/^<[a-z]+(>|\s)/.test(node.value) &&
    !new RegExp(`^<(${proseComponents.join("|")})(>|\\s)`).test(node.value)
    );
    };

    module.exports.withProse = () => {
    return (tree) => {
    let insideProse = false;
    tree.children = tree.children.flatMap((node, i) => {
    if (insideProse && isJsNode(node)) {
    insideProse = false;
    return [{ type: "jsx", value: "</div>" }, node];
    }
    if (!insideProse && !isJsNode(node)) {
    insideProse = true;
    return [
    { type: "jsx", value: '<div className="prose">' },
    node,
    ...(i === tree.children.length - 1
    ? [{ type: "jsx", value: "</div>" }]
    : []),
    ];
    }
    if (i === tree.children.length - 1 && insideProse) {
    return [node, { type: "jsx", value: "</div>" }];
    }
    return [node];
    });
    };
    };