Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate stdlib doc pages #432

Merged
merged 14 commits into from
Apr 19, 2023
303 changes: 247 additions & 56 deletions flake.lock

Large diffs are not rendered by default.

61 changes: 31 additions & 30 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

inputs.nixpkgs.url = "nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.nickel.url = "github:tweag/nickel/stable";
inputs.nickel.url = "github:tweag/nickel";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it on purpose, or a left-over from tests? If we are going to target master, I suppose we should merge this PR in an unstable branch, and not in master. Although we plan to release 1.0 very soon.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's left over from testing. It would probably make sense to merge this PR into an unstable branch on nickel-lang.org and change this input over before integrating into master.


outputs =
{ self
Expand All @@ -17,34 +17,35 @@
, nickel
}:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
packageInfo = pkgs.lib.importJSON ./package.json;
nickelWasm = nickel.packages.${system}.nickelWasm;
nickelUserManual = nickel.packages.${system}.userManual;
in rec {
devShell = pkgs.mkShell {
packages = with pkgs; [
nodejs_latest
autoconf
automake
gettext
libtool
cmake
pkg-config
libpng
zlib
nasm
];
shellHook = ''
rm -rf nickel-repl
ln -s ${nickelWasm}/nickel-repl nickel-repl
ln -s ${nickelUserManual} src/nickel-manual
let
pkgs = nixpkgs.legacyPackages.${system};
nickelWasm = nickel.packages.${system}.nickelWasm;
nickelUserManual = nickel.packages.${system}.userManual;
nickelStdlibDoc = nickel.packages.${system}.stdlibJson;
in
{
devShell = pkgs.mkShell {
packages = with pkgs; [
nodejs_latest
autoconf
automake
gettext
libtool
cmake
pkg-config
libpng
zlib
nasm
];
shellHook = ''
ln -sfn ${nickelWasm}/nickel-repl nickel-repl
ln -sfn ${nickelUserManual} src/nickel-manual
ln -sfn ${nickelStdlibDoc} src/nickel-stdlib-doc

echo "== Run \`npm run develop\` to start developing"
echo " or"
echo "== Run \`npm run build\` to build the website"
'';
};
});
echo "== Run \`npm run develop\` to start developing"
echo " or"
echo "== Run \`npm run build\` to build the website"
'';
};
});
}
20 changes: 16 additions & 4 deletions gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ module.exports = {
name: 'Documentation',
link: '/user-manual'
},
{
name: 'Standard Library',
link: '/stdlib'
},
{
name: 'Playground',
link: '/playground'
Expand All @@ -26,6 +30,9 @@ module.exports = {
{name: "Tutorial", link: "/user-manual/tutorial"},
],
},
stdlib: {
link: '/stdlib'
},
},
plugins: [
'gatsby-plugin-react-helmet',
Expand All @@ -35,10 +42,17 @@ module.exports = {
{
resolve: `gatsby-source-filesystem`,
options: {
name: `markdown-pages`,
name: `user-manual`,
path: `${__dirname}/src/nickel-manual`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `stdlib-doc`,
path: `${__dirname}/src/nickel-stdlib-doc`,
},
},
`gatsby-plugin-sass`,
{
resolve: `gatsby-transformer-remark`,
Expand All @@ -58,8 +72,6 @@ module.exports = {
],
},
},
// {
// resolve: `gatsby-remark-prismjs`,
// },
`gatsby-transformer-json`,
],
};
83 changes: 80 additions & 3 deletions gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('path')

exports.onCreateWebpackConfig = ({ _stage, actions, _loaders }) => {
actions.setWebpackConfig({
experiments: {
Expand Down Expand Up @@ -29,11 +31,11 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

result.data.allMarkdownRemark.edges.forEach(edge => {
const page = edge.node.frontmatter.slug;
let path = `/user-manual/${page}`;
let page_path = `/user-manual/${page}`;

actions.createRedirect({
fromPath: `${path}.md`,
toPath: path,
fromPath: `${page_path}.md`,
toPath: page_path,
redirectInBrowser: true,
isPermanent: true
});
Expand All @@ -50,4 +52,79 @@ exports.createPages = async ({ actions, graphql, reporter }) => {

redirectToIntro("/user-manual/");
redirectToIntro("/user-manual");

let redirectToStdlibStd = fromPath => (
actions.createRedirect({
fromPath,
toPath: `/stdlib/std`,
redirectInBrowser: true,
isPermanent: true,
})
);

redirectToStdlibStd("/stdlib/");
redirectToStdlibStd("/stdlib");
};

// Make a StdlibSection node in the format expected by the page generation code
// We pass the original content as JSON so we can query the entire thing at once instead of havin gatsby integrate it into the GraphQL schema
const makeStdlibSection = ({ actions, createNodeId, createContentDigest, node, slug, name, content }) => {
newNode = {
id: createNodeId(`${node.id} >>> Nickel Stdlib Doc ${slug}`),
yannham marked this conversation as resolved.
Show resolved Hide resolved
parent: node.id,
slug,
name,
internal: {
contentDigest: createContentDigest(content),
content: JSON.stringify(content),
type: "StdlibSection"
}
};
actions.createNode(newNode);
actions.createParentChildLink({ parent: node, child: newNode })
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I general I feel like this new blobs of code in this file could maybe be made easier to understand with a bit of documentation. I think I understand what it is doing, mostly pre-processing of stdlib and user manual data and make them readily available as structured data to be used easily by the other pages, but not sure I would get everything again in 6 months 😅

exports.onCreateNode = ({ node, getNode, createNodeId, createContentDigest, actions }) => {
// We make a new node type "UserManualMarkdown" to make the filesystem query in `src/pages/user-manual/{UserManualMarkdown.slug}.js` more specific
if (node.internal.type === "MarkdownRemark" && getNode(node.parent).sourceInstanceName === "user-manual") {
newNode = {
id: createNodeId(`Nickel User Manual ${node.id}`),
parent: node.id,
slug: node.frontmatter.slug,
internal: {
contentDigest: node.internal.contentDigest,
type: "UserManualMarkdown",
},
};
actions.createNode(newNode);
actions.createParentChildLink({ parent: node, child: newNode })
}

// Preprocess the JSON stdlib documentation data that we get from Nickel into a format that makes it easier to handle
if (node.internal.type === "NickelStdlibDocJson") {
const toplevelName = getNode(node.parent).name;
docsContent = JSON.parse(getNode(node.parent).internal.content);

// Since we don't want to have every module displayed under the `std` namespace on the website, we split out those top-level entries which have subfields.
toplevelFields = Object.fromEntries(Object.entries(docsContent).filter(([key, value]) => !value.fields));

makeStdlibSection({
actions, createNodeId, createContentDigest,
node,
slug: toplevelName,
name: toplevelName,
content: toplevelFields,
})

// What's left are the stdlib functions living in the top-level `std` namespace
Object.entries(docsContent).filter(([key, value]) => !!value.fields).forEach(([slug, value]) => {
makeStdlibSection({
actions, createNodeId, createContentDigest,
node,
slug: `${toplevelName}-${slug}`,
name: `${toplevelName}.${slug}`,
content: value.fields,
})
});
}
}