GithubHelp home page GithubHelp logo

slinkity / slinkity Goto Github PK

View Code? Open in Web Editor NEW
470.0 4.0 42.0 3.91 MB

To eleventy and beyond! The all-in-one tool for templates where you want them, component frameworks where you need them πŸš€

Home Page: https://slinkity.dev

License: Other

JavaScript 29.33% Nunjucks 13.53% SCSS 16.43% CSS 2.00% Svelte 7.04% Vue 6.31% TypeScript 25.36%
react eleventy esbuild vite jamstack svelte vue

slinkity's Introduction

License: MIT Twitter: slinkitydotdev

Slinkity

⚠️ This project is no longer maintained. The project owner (@bholmesdev) now works on Astro full-time. If you want to build component-driven content sites, give Astro a try! If you're committed to 11ty and want to use client components, consider 11ty's WebC project.

About

Slinkity is a simple way to handle styles and component frameworks on your 11ty site. Once installed, this:

  • πŸš€ Unlocks component frameworks like React for writing page templates and layout templates. Turn an existing .html or .liquid file into a .jsx file, and you're off to the componentized races.
  • πŸ”– Includes powerful shortcodes to insert components into existing pages. Add a line like this to your markdown, HTML, Nunjucks, etc, and watch the magic happen: {% react 'path/to/component' %}
  • πŸ’§ Hydrates these components when and how you want. Use component frameworks as a static template to start, and opt-in to shipping JS as needed with our partial hydration helpers.
  • πŸ’… Bundles all your resources with the power of Vite. Use your favorite CSS preprocessor, JS minifier, and more with minimal config.

Technologies used

Slinkity stands on the shoulders of giants. You can think of Slinkity as the "glue" binding 2 tools together:

  1. Eleventy: a static site generator with a rich feature set for fetching data, composing layouts, and inserting content with "shortcodes."
  2. Vite: a bundler that takes the boilerplate out of your set up. It'll compile JS component frameworks, handle CSS preprocessors with little-to-no config (say, SCSS and PostCSS), and show dev changes on-the-fly using hot module replacement (HMR).

Getting started

Use our CLI command to spin up a Slinkity site: npm init slinkity. This demos our core functionality while staying as lean as possible.

To learn more, and explore adding Slinkity to existing 11ty projects...

slinkity's People

Contributors

aleksandrhovhannisyan avatar alexmunoz avatar andrewleedham avatar andystevenson avatar arkanemoose avatar bdougie avatar bendmyers avatar bholmesdev avatar bramsmulders avatar falldowngoboone avatar gingerchew avatar grawl avatar jadenguitarman avatar joshbnntt avatar justinsthomas avatar kylesloper avatar nachtfunke avatar paulshryock avatar rodneylab avatar santicros avatar smithbm2316 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

slinkity's Issues

Unit test core functionality

Is your feature request related to a problem? Please describe.
We have quite a few core + helper functions in our reactPlugin directory that could use testing. At the moment, we just have one test total in our utils directory πŸ™ƒ

List of tests left to write

  • reactPlugin/toRendererHtml - unit tests
  • reactPlugin/index -> add-react-renderer-script HTML transform - snapshot tests
  • reactPlugin/addShortcode -> argsArrayToPropsObj Shortcode props reader - unit tests
  • reactPlugin/toFormattedDataForProps 11ty data converter - unit tests
    - [ ] utils/toUnixPath - unit tests This helper no longer exists!

Type Checking the source code

Is your feature request related to a problem? Please describe.
I have been looking into how we can get better type safety into the JSDoc on the back of #93 (comment) and thought I'd share my findings as a feature request.

Describe the solution you'd like
Linting/CI to catch JSDoc types that don't match up with the actual source code.

Describe alternatives you've considered
We could convert the whole repo to TypeScript, although from speaking with @bholmesdev I believe he wants to avoid that where possible.

Findings
I was initially looking into eslint-plugin-jsdoc, since currently types are stored there. However, it does not seem to support the TypeScript types with JavaScript code that we are using, it either supports basic JSDoc types or full TypeScript. Although, I do still think it would be a useful tool for normalising the formatting and applying rules to how JSDoc is written. We may have to manually configure things like TypeScript globals though (e.g: Record) because it does not know what that is, or just disable the type part of the plugin.

In order to actually check that all the typings work, it seems we would need to use the --checkJs option of tsc. Currently, Slinkity has a tsconfig.json which is pointing at the defineConfig types as that is the only user-facing code and produces declaration files to support that API. We would likely need to have 2 tsconfig.json files, one for type checking everything as another linting step, and another to generate the aforementioned declaration files.

Allow resource imports from outside your 11ty output directory

Is your feature request related to a problem? Please describe.
Paraphrasing @nachtfunke's issue: I wanted to break up a .scss file into a set of fragments with nested CSS imports. When I slapped stylesheet.scss into the head of my template, I was surprised that none of these nested scss imports could resolve. This is because all imports are relative to the output directory (i.e. _site), so any files that aren't copied to this directory can't be found. I needed to passthrough copy all stylesheets to the output for imports to work. This is pretty unintuitive, since I don't want to ship 10 stylesheets to the end user!

Note that Vite will delete unused resources (including stylesheets) during production builds. Still, the mental model of passthrough copying unprocessed files doesn't really fit with 11ty's paradigm.

Describe the solution you'd like
We should allow imports relative to either:

  • the base of your project
  • your input directory configured in 11ty

Sure, you can write and resolve an absolute path yourself. But we could also provide some helpful import aliases using Vite's alias feature. I propose introducing 2 new aliases for this:

  • @root/... relative to the base
  • @input/... relative to the input directory

For instance, say we have a project set up like so:

_site/ #build output
  index.html
src/ #build input
  index.html
styles/
  base.scss
  import1.scss
  import2.scss
  ...
scripts/
  main.js

And say that index.html attempts to grab that unprocessed stylesheet. Instead of passthrough copying, we could import from the @root like so:

<head>
  <link rel="stylesheet" href="@root/styles/base.scss">
</head>

Same should work for ESM imports as well given Vite's aliasing setup!

<script type="module">
  import '@root/scripts/main.js'
  ...
</script>

Bonus: no need to passthrough copy components anymore!

We're pretty constrained right now needing to passthrough copy all components living in _includes/components. This is pretty inefficient and requires maintaining some Node readFile + writeFile code. Allowing import aliases outside the output would eliminate this constraint. Heck, you could easily place your components in _includes without that nested components directory! We'd just need 11ty to ignore component saves when live reloading (otherwise it reprocesses all routes unexpectedly).

Describe alternatives you've considered
Documenting the need for passthrough copying all project dependencies. This doesn't feel very sustainable for the problems already outlined.

Additional context

  • Should ensure that Vite aliases also work for href imports
  • Should document import aliases + the problems you run into without them
  • Should remove _includes/components constraint from our docs
  • Should allow imports outside Vite's root to prevent console warnings. This might do the trick

Multiple components on a page breaks the dev server

Describe the bug
Using 2 or more component shortcodes on the same page with hydration (ex. 2 eagerly loaded components) breaks on server startup. Note: this does not happen when you start with a single shortcode on the page, then add another shortcode while the dev server is running. It will only happen when:

  • multiple shortcodes are present on the page before running slinkity --serve
  • The Vite cache is fresh (i.e. node_modules/.vite is empty)

Error

`TemplateContentRenderError` was thrown

Eleventy:EleventyErrorHandler (error stack):
TemplateContentRenderError: Having trouble rendering liquid template ./src/index.md

[11ty] tag "react" not found, file:./src/index.md, line:3, col:1

`ParseError` was thrown

Eleventy:EleventyErrorHandler (error stack):
tag "react" not found, file:./src/index.md, line:3, col:1

   1| # ajcwebdev-slinkity
   2| 
>> 3| {% react 'components/Hello' %}
   4| 
   5| {% react 'components/Counter' %}

Eleventy:EleventyErrorHandler ParseError:

tag "react" not found, file:./src/index.md,
line:3, col:1 at ParseError.LiquidError [as constructor]

(/Users/ajcwebdev/ajcwebdev-slinkity/node_modules/liquidjs/dist/liquid.node.cjs.js:577:28)

[11ty] tag "react" not found

`AssertionError` was thrown:

Eleventy:EleventyErrorHandler (error stack):
AssertionError: tag "react" not found at new AssertionError (/Users/ajcwebdev/ajcwebdev-slinkity/node_modules/liquidjs/dist/liquid.node.cjs.js:653:28)

To Reproduce
Steps to reproduce the behavior:

  1. Create any page template with multiple shortcodes:
{% react 'Component' %}
{% react 'Component2' %}
  1. Start the dev server using slinkity --serve or slinkity --serve --incremental

Notice an error occurs.

Expected behavior
The build should continue without issues.

Additional context
The error hints at using the same import name across each hydration loader. This shouldn't cause any issues since they're wrapped in different script tags, but it looks like ESBuild smashes the script tags together during parsing.

Investigated using the latest v0.13 for ESBuild and downgrading to Vite v2.3, but the issue seems to persist.

Support named shortcode arguments for props

Is your feature request related to a problem? Please describe.
This is our syntax for passing key / value pairs right now:

<!--nunjucks-->
{% react 'Component', 'prop1', value1, 'prop2', value2 %}
<!--liquid-->
{% react 'Component' 'prop1' value1 'prop2' value2 %}

This is fine, but it's not clear that the keys and values pair together. We'd ideally have a syntax closer to HTML attributes here.

Describe the solution you'd like
Looks like 11ty supports named arguments out-of-the-box for Nunjucks! See documentation here. I see no reason we can't implement this for components.

{% react 'Component', prop1=value1, prop2=value2 %}

Describe alternatives you've considered
Recommending that users pass props by constructing objects in a variable. Alek's tutorial looks pretty promising, but it's definitely intense for beginners.

Additional context
Add any other context or screenshots about the feature request here.

New partial hydration modes

Is your feature request related to a problem? Please describe.
I want to have finer control over when my component is hydrated on the page. I expect these 5 methods from Astro's partial hydration to work:

  • load: Hydrate when the DOM is finished parsing
  • idle: Hydrate when the main thread is no longer busy (aka DOM is done parsing, and any JS outside my component is finished running)
  • visible: Hydrate when my component has scrolled into view
  • media: Hydrate when a media query is met
  • none: Never hydrate

Describe the solution you'd like
I'd like to see a new API similar to Astro's client:property helper. We'll use some new naming for Slinkity though:

Prop name change: hydrate (instead of Astro's client)

  • this describes the "purpose" of the prop better than client in my opinion: to hydrate your static markup
  • ties directly into the feature's name on our documentation: Partial Hydration
  • hey, hydrate or diedrate am I right?

Comparison of Astro and Slinkity syntax

Astro:

import ReactComponent from '...'
---

<ReactComponent client:visible />

Slinkity:

{% react 'components/ReactComponent' hydrate="lazy" %}

Value naming

Slinkity Astro
eager load
lazy visible
none [empty]
  • we changed visible to lazy because a) visible could be associated with the display and visibility properties in CSS (which can cause confusion), and b) this feature is often compared to lazy image loading in the DOM. Yes, lazy is often an overloaded term in CS. But if we're going to choose a short and concise name, why not choose something similar to existing browser features?
  • we also changed load to eager to add a yin to lazy's yang. It also made less sense to use load after switching from client to hydrate for the prop name (i.e. client:load makes sense, but hydrate="load" doesn't as much)
  • we allow hydrate="none" as a potential value, since we will allow users to choose a default hydration method for their project (but no hydration is the default!). Including a "none" allows users to override whatever default they've chosen to opt-out of hydration

Handling idle, media, etc

You may have noticed a few hydration modes like idle, media, and client:only are missing from that table. Well, we have a special plan for those... check out this proposal in the comments πŸ˜„

XML error β€” moving to Slinkity

Our team has begun a migration to Slinkity purely for the Vite x Eleventy workflow as advised by @bholmesdev. We are currently testing it out on our Eleventy boilerplate and receive this error:

Stacktrace:
Cannot read property 'insertAdjacentHTML' of null
[Error] We failed to render components used in file src
We recommend trying to:
delete your output directory and restart the server / build
clear your node_modules and running a clean install with "npm i"
Visit https://slinkity.dev to review our changelogs!

Slinkity then serves the site at localhost:8080 but on page visit the CLI throws another error:

 Unable to parse {"file":"/index.html","line":161,"column":10}

With no logical reason to why this syntax is parsed incorrectly.

To Reproduce

  1. Clone this repo
  2. npm i
  3. npm run start
  • Win 10 x64
  • Chredge v95

I was told that @AndrewLeedham has done some good work with #65 and might offer some good opinions.

Thanks all,

Failing to render React on Windows

Describe the bug

Slinkity fails to render both React components and React component pages during development on all pages but index.

Build serves a html page with an empty <slinkity-react-mount-point> on those pages with no React content.

To Reproduce

  1. Clone slinkity-starter or any other Slinkity project using the Windows OS
  2. Ensure there are react components / react component pages in directories with permalinks other than / (index)
  3. Run development server and open pages
  4. Look at console

Errors thrown

Errors logged to console outline that Slinkity can not be found in node_modules .

WIN x64

Support *any* component shortcode + page with renderer plugins

Is your feature request related to a problem? Please describe.
Our React page and shortcode components are heavily tied to our core Slinkity plugin. This isn't very extensible, since we'd have to write our own bespoke logic for Vue shortcodes + pages, Svelte, Lit Element, etc. Ideally, we could let the community build these using a plugin architecture!

Describe the solution you'd like
We'll be basing this on Astro's UI renderer config, but with additional hooks to set up components at the page level.

We should abstract all logic for setting up component pages and shortcodes to a plugin API. This comes with a few major changes:

  • Our React logic will move to a new package, with the naming convention @slinkity/react-renderer. We'll enforce this for future renderer plugins as well.
  • We'll introduce a slinkity.config.js file for users to apply renderer plugins. We'll likely mirror Vite's config format, with their type checking + defineConfig helper as a nice-to-have. Here's how you might apply our React renderer:
const reactRenderer = require('@slinkity/react-renderer')

module.exports = defineConfig({
  rendererPlugins: [
    reactRenderer({...rendererConfigOptionsIfAny}),
  ]
})
  • We'll drop the requirement to install react and react-dom from the docs. Instead, installing the React renderer will import all associated framework libs. Same should go for future renderer plugins!

Describe alternatives you've considered
Uhhh manually writing all this renderer logic by hand? Yeah no thanks.

Add links to GitHub and home pages from docs

Where did our docs fail you?

After navigating from the homepage to the documentation, I expected a nav bar to:

  • take me to the project's source code (in case I want to contribute or leave a star)
  • take me back to the homepage

How can we improve?

Add a simplified navbar with 3 items:

  • a logo to the left that takes you to the docs "Overview" page
  • a homepage link on the right to return home
  • a GitHub link on the right that links to the GitHub. Ideally includes an icon denoting it as an external link. See Vite's GitHub link below:

image

Fails to build XML or JSON feeds from eleventy-base-blog

Describe the bug
The eleventy-base-blog has nunjucks templates that generate both XML and JSON feeds for RSS readers. When using Slinkity in place of eleventy these fail to build.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://stackblitz.com/github/AndrewLeedham/eleventy-base-blog-slinkity
  2. Run npm run build in the terminal.
  3. See the issue.

Expected behavior
Slinkity to work out-the-box with the eleventy-starter-blog.

Logs

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] > Having trouble writing template: .11ty-build-YLF9VP/sitemap.xml

`TemplateWriterWriteError` was thrown
[11ty] > Cannot read properties of null (reading 'insertAdjacentHTML')

`TypeError` was thrown:
[11ty]     TypeError: Cannot read properties of null (reading 'insertAdjacentHTML')
        at applyViteHtmlTransform (/home/projects/jvmiqqwvx.github/node_modules/slinkity/lib/plugin/index.js:99:31)
        at Object.eval (/home/projects/jvmiqqwvx.github/node_modules/slinkity/lib/plugin/index.js:161:22)
        at Template.runTransforms (/home/projects/jvmiqqwvx.github/node_modules/@11ty/eleventy/src/Template.js:512:38)
        at async Template.renderPageEntry (/home/projects/jvmiqqwvx.github/node_modules/@11ty/eleventy/src/Template.js:787:15)
        at async eval (/home/projects/jvmiqqwvx.github/node_modules/@11ty/eleventy/src/Template.js:803:21)
        at async Promise.all (index 0)
        at async Promise.all (index 1)

(please complete the following information):

  • OS: macOS 11.2.3
  • Browser: Chrome 95
  • Version: 0.2.0

Additional context
Seems to me that Vite is assuming the template is outputting HTML, but in this case, it is either XML or JSON which it does not understand.

Document adding styles to your project

What feature were you trying to use?

I wanted to import SASS files and CSS modules into my Slinkity project.

Where did our docs fail you?

I used Vite's documentation to figure out how SASS imports worked, since I couldn't find any resources on Slinkity's own documentation!

How can we improve?

I'd suggest adding a new page to the doc's main navigation called "styling." This page should contain a few topics:

  1. A brief overview of 11ty's passthrough copy options. This is used to copy any asset (including styles) to the build directory of your project. For instance, if you have a styles directory at the base of your project, you can copy over all the contents of that directory using eleventyConfig.addPassthroughCopy('styles')
  2. **How to add css, scss, sass, less, and more to existing pages using link tags. A powerful example would be: open any base layout you haven your project, and add a link tag referencing a file in your build output. For instance, if you had a heading.scss in that styles folder you passthrough copied, you can use it on any page using <link rel="stylesheet" href="/styles/heading.scss">. Yes, you can just say .scss! Vite knows what to do with it.
  3. How to use CSS modules in component files. It's as simple as importing these styles from literally anywhere like so: import styles from './styles/heading.module.css'. Funny enough, you don't even need to passthrough copy CSS modules to the build output! Wherever these files live, styles will get applied correctly.
  4. Anything else I'm missing here!

CSS Module support

Is your feature request related to a problem? Please describe.
When importing .module.css files into my components, I don't see my styles when I:

  • disable JS in my browser
  • render my component statically using render: static

Describe the solution you'd like
CSS modules should get compiled at buildtime using 11ty, and at runtime (or production-bundle-time?) using Vite.

Additional context
We have a separate build step for static rendering. It should be easy to add CSS modules to our ESbuild call found here.

Also worth looking into Vite's SSR API. This is likely a separate tech initiative though, since it completely changes our approach.

Better surface contributors on homepage

Where did our docs fail you?

When browsing the list of contributors on the homepage, I noticed quite a few quality contributors were missing. This is because we maintain our own list of contributors in yaml. Understandably, new contributors don't know / don't want to update this list by hand!

How can we improve?

Let's try sourcing our list of contributors from GitHub's API. This should be pretty easy using their repos API πŸ”₯

Tooling: Improve local debugging experience

Is your feature request related to a problem? Please describe.
Debugging Slinkity against a local project is not enjoyable right now. In short, you need to npm pack after any change is made, run npm i again from local test projects, then restart the dev server. Due to Babel's slow builds and npm's install speed, this means a 10-15 sec wait to see each change. That's not including the overhead of ping-ponging between 2 terminal windows 😞

Why not use npm link?

When using npm link or yarn link to tie dependencies together, I hit peer dependency issues with @11ty/eleventy. This means I need to temporarily install this as a dev dependency, and remember to revert this change once my PR is pushed.

Once I start a dev server using this link, I run into another unexpected error in my browser console:

Uncaught SyntaxError: The requested module '/@fs/Users/benholmes/Repositories/slinkity/lib/plugin/reactPlugin/_client/toMountPointById.js' does not provide an export named 'toMountPointById'

After discussing on the Vite discord server, it sounds like we're not properly exposing our _client files from our package.json. This doesn't cause problems when running npm pack. However, since Vite relies on the package.json to decide which dependencies to process and optimize, it'll break using a symlink via npm link.

Describe the solution you'd like
There are a few related improvements I'd like to see:

  1. We should replace our Babel build process with esbuild. This would open the door to faster builds, a nice watch command for development, and a simpler build config compared to babel's plugin bonanza.
  2. We should investigate alternatives to npm link. The need to install and uninstall to get around the peer dep issue isn't great in my opinion. According to SvelteKit's contributing guide, pnpm offers a nice alternative that could work!
  3. Client-facing files should be exposed as exports from a slinkity/client package. We just need a client.js that barrel exports everything, plus an files entry in our package.json.

Document usage of Node 14

What feature were you trying to use?

I expected to keep using Node v12 in my 11ty project (v12 and up according to their package.json). However, when I attempted to deploy my project on Netlify, I received an error relating to fs/promises failing to resolve.

Where did our docs fail you?

I couldn't find any documentation on which node version to enforce with my project. If I had known to use Node v14, I could have resolved my issue much faster.

How can we improve?

  1. Bump the engines section of our package.json to Node 14 and up. This could fix Netlify's reaching for Node v12 by default.
  2. Document the recommended Node version under our README and our quick start guide.

Vue support

Is your feature request related to a problem? Please describe.
I'm limited to using .jsx templates with React for interactive routes + shortcodes on my site. .vue files should be an option too!

Describe the solution you'd like

I would expect to get feature parity with existing .jsx files. We'll likely use Vue's single page components as a starting point to simplify scoped CSS compilation.

  • a vue shortcode to render components in existing templates, with the freedom to pass props: {% vue 'components/Evan-tually.vue' 'render' 'static' %}
  • support for .vue extensions on page-level templates
    • a way for pass frontmatter to 11ty as part of the data cascade
    • a way to choose props you want the component to receive in the clientside bundle, similar to getProps
  • support for our 3 rendering modes:
    • eager: load our component on page load
    • lazy: load our component when scrolled to (note: the Vue library can still be loaded on page load!)
    • static: render our component to static HTML + CSS, no JavaScript shipped

Describe alternatives you've considered
Well, erm, React I guess πŸ™ƒ

Add a leading file name/path to code blocks consistently

What feature were you trying to use?

I was cruising the config documentation.

Where did our docs fail you?

The config documentation had some code blocks that were missing the file name/path that they were related to. Like the vite.config.js blocks didn't have the file name at the top, but the slinkity.config.js ones did.

How can we improve?

The leading file name/path helps me find what I'm looking for, but also helps me not lose track of where I am in the documentation. Having them there in general just helps, regardless of "context change" or only being in one context.

I created a branch that fixed the few I ran into, which I can make a PR for.

Rendering the same component shortcode twice breaks hydration

Describe the bug
When copying and pasting a react shortcode with the same component path, only the first one is actually interactive.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new template file (ex. index.html)
  2. Add multiple react shortcodes referencing the same component. You can pass different props to each, but the bug will persist:
<div>
{% react 'components/GlassCounter.jsx' %}
{% react 'components/GlassCounter.jsx' %}
{% react 'components/GlassCounter.jsx' 'random' 'prop' %}
  1. Attempt to interact with the second and third components. Notice they are not interactive.

Expected behavior
All components should be interactive when rendered as eager or lazy.

The "to" argument must be of type string. Received type boolean (false)

Describe the bug

I'm getting the following error when trying to migrate to Slinkity:

[11ty] > Having trouble writing template: false

`TemplateWriterWriteError` was thrown
[11ty] > The "to" argument must be of type string. Received type boolean (false)

`TypeError` was thrown:
[11ty]     TypeError [ERR_INVALID_ARG_TYPE]: The "to" argument must be of type string. Received type boolean (false)
        at new NodeError (node:internal/errors:371:5)
        at validateString (node:internal/validators:119:11)
        at relative (node:path:1192:5)
        at Object.<anonymous> (//path/to/project/node_modules/slinkity/lib/plugin/index.js:140:30)
        at Template.runTransforms (//path/to/project/node_modules/@11ty/eleventy/src/Template.js:527:38)
        at async Template.renderPageEntry (//path/to/project/node_modules/@11ty/eleventy/src/Template.js:802:15)
        at async //path/to/project/node_modules/@11ty/eleventy/src/Template.js:827:21
        at async Promise.all (index 0)
        at async Promise.all (index 6)

I suspect this is related to #84. I have the following permalink: falses:

Removing these allows the server to start.

To Reproduce

  1. Clone https://github.com/AleksandrHovhannisyan/aleksandrhovhannisyan.com.
  2. Check out the slinkity branch/
  3. Run yarn to install dependencies.
  4. Run yarn serve to start up the slinkity server.
  5. Observe the error early on in the output.

Expected behavior
The error shouldn't occur πŸ˜„

(please complete the following information):

  • OS: Windows 10 (WSL)
  • 11ty version: beta 5

Transition to using Vite middleware on custom dev server

Is your feature request related to a problem? Please describe.
We currently use a combination of 2 things to pull off server side rendering:

  1. Prerender your components to static HTML within eleventy using shortcodes
  2. Hydrate those components on the client by applying script tags and using the Vite server to interpret those script tags

This approach has a fundamental flaw though: how do we re-process that static HTML from step 1 when you save changes to a component? Well, there's no way for 11ty to know which components are used within a given template! Our only option would be to reprocess every template on your site when you save changes to a component. Certainly doesn't fit our theme of incremental builds and HMR 😬

Describe the solution you'd like
Instead of prerendering the components within eleventy, we should prerender on browser request using a custom server. This means we'd only prerender when you visit that route in your browser. We'd hot reloading at the component level too, since we only re-render the components that changed between page refreshes!

See Vite's SSR documentation here.

Describe alternatives you've considered
Rebuilding your entire site on every component change (not great for performance)

Support .tsx components

Is your feature request related to a problem? Please describe.
I would like to use Slinkity with TypeScript React templates.

Describe the solution you'd like
Slinkity to see .tsx templates the same way it sees .jsx. From what I can tell this would just work out the box, as Vite already supports .tsx.

Describe alternatives you've considered
Just using .jsx with typedocs. However, I am looking to use Slinkity with vanilla-extract which requires full TypeScript.

Additional context
I played around with this in my own fork, and it seems to #justwork when swapping all the .tsx occurrences with .jsx. Although to support this properly I suppos we would need to register 2 plugins for each extension.

Parsing error on `logo.html` in Slinkity docs

Describe the bug
A strange parsing error occurs on our doc's logo.html.

11ty] Copied 33 files / Wrote 8 files in 0.37 seconds (v1.0.0-canary.41)
[11ty] Watching…
[11ty] Unhandled rejection in promise: (more in DEBUG output)
[11ty] > Unable to parse {"file":"/index.html","line":137,"column":7}
135|          <stop offset="1" stop-color="#FAFF02" ></stop>
136|        
137|        <linearGradient id="paint8_linear" x1="265.37" y1="-9.04662e-06" x2="148.808" y2="126.632"
   |        ^
138|          gradientUnits="userSpaceOnUse">
139|          <stop stop-color="#FF00D6" ></stop>

`Error` was thrown:
[11ty]     Error: Unable to parse {"file":"/index.html","line":137,"column":7}
    135|          <stop offset="1" stop-color="#FAFF02" ></stop>
    136|        
    137|        <linearGradient id="paint8_linear" x1="265.37" y1="-9.04662e-06" x2="148.808" y2="126.632"
       |        ^
    138|          gradientUnits="userSpaceOnUse">
    139|          <stop stop-color="#FF00D6" ></stop>
        at traverseHtml (/Users/benholmes/Repositories/slinkity/docs/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:21240:15)
        at processTicksAndRejections (internal/process/task_queues.js:95:5)
        at async devHtmlHook (/Users/benholmes/Repositories/slinkity/docs/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:56997:5)
        at async applyHtmlTransforms (/Users/benholmes/Repositories/slinkity/docs/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:21550:21)
        at async viteTransformMiddleware (/Users/benholmes/Repositories/slinkity/docs/node_modules/slinkity/lib/plugin/index.js:135:23)
^Cnpm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `slinkity --serve --incremental`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/benholmes/.npm/_logs/2021-10-31T22_05_32_698Z-debug.log

To Reproduce
Steps to reproduce the behavior:

  1. Go to the docs directory of this project
  2. Run npm start
  3. Notice a parsing error occurs on index.html (and any other file for that matter, if you delete index.md)

Expected behavior
Parsing should continue to work in-line with regular 11ty. Note that the project compiles when using plain 11ty!

(please complete the following information):

  • OS: OSX 11.5.1 (20G80)
  • Browser N/A
  • Version 0.2.0

Additional context
Looks like Node HTML parser just launched a new major version. Doing some local testing, it seems SVGs are parsed incorrectly on the latest v4. This behavior should be fixed when upgrading to v5.

Rework `props` API to separate "11ty" data from "component" data

Is your feature request related to a problem? Please describe.

Here's how 11ty sends and receives data to pages right now:

  1. Grabs the frontmatter it needs to shove into the data cascade
  2. Renders your page component with said data

But at step one, we don't know what 11tydata looks like yet (since we haven't assembled the data cascade). So if we called a function like this to figure out your frontmatter:

export const getProps = (data) => ({
  date: data.page.date,
  names: data.cmsData.names,
  title: 'Roll Call',
})

data would be undefined the first time around! This causes a nasty exception trying to access nested keys like cmsData, unless you use optional chaining to avoid breaking that first call (i.e. data?.cmsData?.names).

Describe the solution you'd like
I'd like a new API that separates our 2 concerns: data to get passed to the cascade, and data that your component wants to receive. That API may look like this:

// my-fancy-page.jsx

// what data does 11ty need to know?
export const frontMatter = {
  title: 'Roll Call',
}

// what data does your component need to know?
export function getProps(data) {
  return {
    date: data.page.date,
    names: data.cmsData.names,
  }
}

So instead of getProps doing everything, it would mostly act as a filter for which parts of the data cascade your component wants. This also combines 2 familiar APIs:

  • NextJS's getStaticProps function, which is very similar to our getProps
  • 11ty's existing frontMatter support, which is rep'd by our frontMatter variable.

Additional notes
We may want to support const frontmatter and const frontMatter to avoid confusion! It's hard to know which to use, so let's just look for either one πŸ™ƒ

Vite import aliases don't work when building for production

Describe the bug
Vite import aliases for SCSS files don't work when building for production.

To Reproduce
Ive added <link rel="stylesheet" href="/@includes/styles/styles.scss" /> to my base.njk and this works beautifully in HMR mode. But when I try to build for production (npx slinkity) i get the following error:

[vite:load-fallback] Could not load /Users/bram/Developer/supple-kit/eleventy-supple-starter/.11ty-build-U0dn1s/_includes/styles/styles.scss (imported by .11ty-build-U0dn1s/index.html): ENOENT: no such file or directory, open '/Users/bram/Developer/supple-kit/eleventy-supple-starter/.11ty-build-U0dn1s/_includes/styles/styles.scss'
[11ty] Unhandled rejection in promise: (more in DEBUG output)

Expected behavior
I expect the build to succeed with a compiled CSS file.

(please complete the following information):

  • OS: MacOS 12.0.1
  • Browser: n/a
  • Version: 0.3.3
  • NodeJS: 14.18.1

Use Vite SSR for static rendering

Is your feature request related to a problem? Please describe.
We roll our own esbuild process for statically rendering component pages / component shortcodes right now. Sure it's fast, but it has some obvious problems:

  • We have to re-implement any loaders Vite would normally handle. Say, CSS modules, SASS, Svelte (eventually), etc
  • It's a lot of overhead to maintain. We've already resorted to hack-y methods to prevent actual file output (aka just process in memory).

Describe the solution you'd like
We could use Vite SSR to generate any static HTML on the server. This would take 2 forms:

Dev server
We'd spin up a second Vite server to handle SSR. The key is adding middlewareMode: 'srr' as an option like so:

const vite = await createViteServer({
    root: dir.output, // accessible anywhere within the Slinkity plugin
    server: {
      middlewareMode: 'ssr',
    },
    clearScreen: false,
 })

Then, wherever we would normally call our internal helper to generate a Node-friendly component, we'd just grab the component directly using Vite's vite.ssrLoadModule:

const { default: Component } = await vite.ssrLoadModule(pathToComponent)

Production builds
We can't rely on vite.ssrLoadModule for production builds, since we can't spin up a dev server here! We'll need to use vite.build to get a fairly similar output. It just takes a little massaging to grab that module on the server without writing components to the file system:

const { output } = await vite.build({
      root: dir.output,
      build: {
        ssr: true,
        write: false,
        rollupOptions: {
          input: pathToComponent,
        }
      }
    })
    // requireFromString is a separate module already used in Slinkity!
    // used for converting a string of JS to something we can import
    const { default: Component } = requireFromString(output[0].code)

Open questions
There are a few important pieces we'll need to work out:

  1. Grabbing the outputted CSS when rendering to string. If you opt out of hydration, we won't have the component client-side to process these. It looks like we can grab the tree of CSS imports using a little hack-y magic:
// crawl for imports ending in .css
vite.moduleGraph.urlToModuleMap.get(pathToComponent).importedModules

...but I'm hoping there's a more first-class solution to this problem!
2. There's no caching if we call vite.build on every page / shortcode. This is pretty inefficient! Ideally, we'd only process each component + props combination once, and store the result in some in-memory map.

Assets disappear when building to _site via 11ty image plugin

Update: 03.16.22

This issue turned into a whole separate discussion on supporting 11ty image at all when using Slinkity. We arrived at a pretty simple solution: expose the intermediate 11ty directory during production builds so images are preserved. This is now resolved!

Original issue (now a will-not-fix!)

Is your feature request related to a problem? Please describe.

There is no current solution for including images in the Slinkity documentation.

Describe the solution you'd like

Something that will let us easily drop in images without having to worry about manually optimizing for size or responsiveness.

Describe alternatives you've considered

Ben suggested copying the image shortcode from their docs as the easiest way to get this setup.

Additional context

This is mostly a note for myself, but if anyone wants to take this on in the next week or two before I get to it then it should make for a pretty simple PR.

Add Prettier Config

Is your feature request related to a problem? Please describe.
When contributing to the project I missed the section in Contributing.md that explains Prettier is in use (my bad). And submitted the code changes un-formatted before noticing the failing linting step.

Describe the solution you'd like
Move the prettier options from the ESLint config to a Prettier config at the root. Then new contributors who are aware of prettier will see the config straight away and plugins like vscode-prettier will pick up the config and allow for formatting on save etc if enabled.

Describe alternatives you've considered

  • Running npm run lint:fix does fix the formatting issues, but that is a fairly manual process.
  • npm run lint:fix could be a pre-commit hook, but that would not allow formatting on save or hooking in to the various editor formatting options.
  • I could duplicate the prettier config into my user settings for this repo in vscode, but again that doesn't seem like an optimal solution.

Switch to pnpm

Is your feature request related to a problem? Please describe.
We currently use "plain" npm for everything in our repo. This comes with a few problems:

  • slowest installation times of all available options
  • nothing to help with managing workspaces, should we need them

Describe the solution you'd like
I'd like to choose something faster and/or sexier for our project. pnpm seems to fit the bill according to this thread from Jared Palmer!

Describe alternatives you've considered
Yarn v1 seems like a tried-and-true choice for speeding up local installs. Still, it suffers from:

  • unique keywords that differ from npm like add instead of i. Some like this, but I personally think it hurts the beginner-friendliness for new contributors
  • it's aging by comparison to Yarn v2 (which is a hassle to set up). Worth investigating v3 though.

Update: decided on Yarn 3
We've decided to use Yarn 3 instead given our team's existing familiarity with Yarn 1. Redwood's decision to use Yarn 3 gives us some confidence as well!

RFC - Shortcode syntax for components

Is your feature request related to a problem? Please describe.
If you opt to use React + JSX for your page templates, you don't have a clean way to use shortcodes. Sure, you can access shortcodes when mapping props to your component pages:

function getProps(eleventyData) {
  const oneXEngineer = 1
  return {
    tenXEngineer: eleventyData.shortcodes.make10xEngineer(oneXEngineer)
  }
}
// -> { tenXEngineer: 10 }

Example from our documentation

...but this requires you to use dangerouslySetInnerHtml to use that markup. If you're attempting to use, say, the 11ty image plugin for every image on your site, this quickly becomes a lot of overhead!

It's equally frustrating if you want partial hydration while using JSX, Vue, or Svelte as your templating language. You'll need to call shortcodes.react for every component you want to partially hydrate, including components nested within other components.

Describe the solution you'd like
I'd like to see a Shortcode component I can easily use throughout my component pages. We'll use React as a stomping grounds for this, but the syntax would be similar across Vue and Svelte as well. For instance, say we have an image shortcode declared in our config like so:

const Image = require("@11ty/eleventy-img");
function imageShortcode(src, alt, sizes, widths) {
  let options = {
    widths: widths,
    formats: ['jpeg'],
  };
  Image(src, options);

  let imageAttributes = { alt, sizes };
  metadata = Image.statsSync(src, options);
  return Image.generateHTML(metadata, imageAttributes);
}

module.exports = function(eleventyConfig) {
  eleventyConfig.addShortcode('image', imageShortcode);
}

You could call out this shortcode using a component like so:

// 1. Import Shortcode from the slinkity package. I'd imagine a set of /client exports specifically for this
import { Shortcode } from 'slinkity/client'

export default function MyPage() {
  return (
    <div>
      <Shortcode.image args={['/super/cool/image.jpg', 'Super cool image']} />
    </div>
  )
}

Pulling apart that syntax:

  • Shortcodes would be available as object keys. Since our shortcode is declared as image, we call Shortcode.image. Note: will need to investigate whether Vue and Svelte can do this.
  • This will be a wrapper for dangerously setting inner HTML on a shortcode output. Yes, it really is that simplistic.
  • args receives an array of unnamed arguments. In this case, /super/cool/image.jpg will be the src param passed to 11ty image, and Super cool image will be the alt.

Named parameters?
I considered this for the React shortcode in particular. We'd allow something like this:

<Shortcode.react args={['/path/to/component.jsx']} hydrate="eager" secondProp={42} />

There's a couple problems with this though:

  1. We've introduced some "reserved" names that can't be used as named arguments. For instance, if your component ever wants args as a prop, you're kinda screwed!
  2. Using args just for the component path isn't very legible. It feels like args is a half-solution we could handle better.

So, I'm considering a different option: named arguments will be an object {...} as the last parameter to args. Here's how we'd refactor that previous example:

<Shortcode.react args={['/path/to/component.jsx', { hydrate: 'eager', secondProp: 42 }]} />

This avoids any naming collisions and treats args as the source of truth! We'll just need to be smart about mapping named arguments to nunjucks shortcodes, which was already an outstanding issue.

Major limitation: You can't use shortcodes in hydrated components!

Shortcodes can make any call that Node is okay with. In other words, reading and writing to the file system is fair game. This means shortcode components need to be processed serverside without accidentally shipping to the client. As I see things today, you'll need to avoid hydrating any component pages (or nested component shortcodes) if you want to use this Shortcode component.

We'll need some linting to gracefully warn the user when they're hydrating a shortcode. We'll probably link them to the approach I mentioned at the top of this RFC.

Shortcode live reloading doesn't work when render = "static"

Describe the bug
In development, I expect the page to live reload whenever I save changes to shortcode components. However, the page does not reload when render is static. I need to manually save the template using that shortcode before I see the change.

To Reproduce
Steps to reproduce the behavior:

  1. Start with a component under _includes/components
  2. Add that component to any template as a shortcode, with render set to static
  3. Save a change to that component
  4. Notice the page doesn't reload with the changes. Refreshing the page doesn't help either.

Expected behavior
Changes to any component under _includes should re-process templates using those components.

(please complete the following information):

  • OS: OSX Big Sur
  • Browser Chrome, Safari, Firefox

Additional context
This likely has to do with eleventy's live reloading when using --incremental. If we use addPassthroughCopy to copy components to the output directory, all template builds are automatically skipped

Add a CONTRIBUTING.md

Where did our docs fail you?

As a new contributor, I am unsure how to navigate the Slinkity codebase. Some expected questions:

  • What's the difference between these cli and plugin directories?
  • How to components actually get hydrated?
  • Where does Vite fit into all this 11ty config?

How can we improve?

Let's create a CONTRIBUTING.md that outlines the overall structure of the codebase. This should outline all the steps involved in rendering + hydrating components, and all the dependencies that get us there.

Should compile when `permalink` is `false`

Describe the bug
In eleventy you can apply permalink with a false value to remove the rendering of the template. In Slinkity you check for !outputPath.endsWith('.html') in 2 places. booleans don't have endsWith as functions and thus building breaks.

I've created an accompanying PR to fix the issue: #83

Docs: explain importance of `/public` for asset handling by Vite

What feature were you trying to use?

I was promised I could use any existing 11ty functionality without issue. However, I found some assets getting unexpectedly trashed during production builds. To quote @AleksandrHovhannisyan:

I'm wondering why files like someFile.liquid don't get written. e.g.:

---
permalink: /robots.txt
eleventyExcludeFromCollections: true
excludeFromSitemap: true
---
User-agent: *
Sitemap: {{ "sitemap.xml" | toAbsoluteUrl }}

More contextβ€”I see this in the output:

[11ty] Writing .11ty-build-DcNVBN/robots.txt from ./src/robots.liquid
[11ty] Writing .11ty-build-DcNVBN/sitemap.xml from ./src/sitemap.liquid

But then those files disappear. Not sure why they get written to a temp folder.

Where did our docs fail you?

Our docs fail to describe how production builds work in Slinkity, where we:

  1. Write your 11ty build to a temporary builder
  2. Use Vite to process that temporary build and output into the intended output folder

This causes a nasty issue for those using CLI tools to directly output to _site, since those resources will be clobbered by the Vite build (see #74). But in this case, Aleksandr is attempting to output static non-html resources using permalinks. In order for Vite to keep these assets around, Vite requires you to use a /public directory to flag these resources as "do not touch"

How can we improve?

Add a section for "gotchas coming from 11ty" and describe the purpose of the /public directory. In short, it is meant for resources that:

  1. Vite should not touch
  2. Are not referenced by any files in your code. Ex. a directory of fonts doesn't need to exist in a /public directory since they're likely referenced by a CSS file. However, something like a robots.txt (which no file explicitly imports) should be copied to a /public directory.

Default <html> layout no longer applied to templates

Describe the bug
The docs promise to apply an <html> and <body> to routes if none exists. This was accidentally removed after resolving #19

To Reproduce
Steps to reproduce the behavior:

  1. Create a new route as described in the component pages documentation
  2. Start the server using slinkity --serve

Notice you'll see the exception Cannot read property 'insertAdjacentHTML' of null

Component shortcodes sometimes render twice in markdown

Describe the bug
Shortcodes used in markdown appear to render twice (with broken hydration) whenever the underlying component uses:

  • h1 - h6 tags
  • p tags
  • div, section, and other layout-based elements

To Reproduce

  1. Create a React component using any of the above tags
  2. Use that component as a shortcode on any .md file (ex. {% react 'components/explosion' %})
  3. Start the dev server
  4. Notice the component is rendered twice
  5. Replace any of the offending tags with a span, and notice the issue is resolved

Expected behavior
My component is only rendered once.

Screenshots
image

// _includes/components/Image.jsx
import React from 'react'
const Image = ({  }) => (
  <div>
    <img src="https://picsum.photos/300" alt="" />
  </div>
)
export default Image
<!--page.md-->
# Very nice

It's a page!

{% react 'components/Time' %}

Additional context
All shortcodes are wrapped in p tags when they're rendered. Once this markdown file passes through cheerio for applying our React mount points, anything that's not a valid child of a p (like another p, h1-h6, etc) is pushed outside the p tag below the mount point. This causes:

  1. Our statically rendered React component to appear outside the mount point
  2. Our hydrated React component to get rendered inside the (now empty) mount point

Hence, our double rendering issue!

Docs redesign - add new theming

Code changes

  1. Add shades of purple to our set of :root CSS variables. These exist in our Slinkity starter project already!

I'm also open to changing these variable names to something more semantic. For instance, since --purple-1 will be used instead of --black (see step 4), we could add a --primary-dark variable that maps to --purple-1 as a more meaningful token.

  1. Remove the network background currently used in the _layouts/base, and replace with a new grid background. This shouldn't require any new SVGs! It is fairly easy to pull off with linear gradients. Again, we can reuse code from our Slinkity starter project (see here)

  2. Update all usages of --grey-100 with --purple-2

  3. Update all usages of --black with --purple-1

Out of scope

Any changes to UI elements themselves. These should be tackled in future issues.

Docs redesign - table of contents

We currently

Out of scope: actual dev work. This is a design ticket only!

Initial design exploration

I've found 2 different approaches to a table of contents. The first adds a second sidebar to the right of the documentation itself on desktop, and wraps this TOC to the top of the page for narrower devices.

  • pros: optimizes for space, surfaces TOC on narrower screens instead of hiding behind a slide-out menu
  • cons: must to scroll to top to find TOC on narrower screens

The second embeds the table of contents inside the side navigation. This appears just below your currently selected page

  • pros: optimizes for space on narrower devices, avoids burying the lead on mobile
  • cons: requires more scrolling to find nav items below the TOC, less space efficient on desktop, hides TOC behind slide-out on mobile

See screenshots of each approach on design exploration Figma πŸ‘‰

Goals

  • decide on which approach to use
  • create mockups for all 3 breakpoints
  • draft a dev issue

Using Slinkity with existing repo - "could not auto-determine entry point..."

Describe the bug
I took an existing repo, updated it to Eleventy 1.0.0-beta.2, changed it over from Tailwind to Sass, and then installed Slinkity and tried replacing the package.json Eleventy commands with Slinkity commands. On npm run start, I got the following error message (followed by many Vite-related items β€” e.g., 12:04:27 PM [vite] page reload with the specific HTML file it's presumably building β€” which implied rendering success otherwise):

(!) Could not auto-determine entry point from rollupOptions or html files and there are no explicit optimizeDeps.include patterns. Skipping dependency pre-bundling.
[Info] Now serving on port 3000 πŸš€
[Info] Visit http://localhost:3000 in your favorite browser (that isn't IE πŸ˜‰)
(!) Could not auto-determine entry point from rollupOptions or html files and there are no explicit optimizeDeps.include patterns. Skipping dependency pre-bundling. (x2)

To Reproduce
Steps to reproduce the behavior:

  1. In package.json scripting, replace the Eleventy commands with Slinkity commands as per the Slinkity docs.
  2. Execute the proper script (e.g., npm run start).
  3. Note the error message as the script fails.

Expected behavior
I expected the site to load in development mode.

Screenshots
N/A

Versions

  • OS: macOS 11.6
  • Browser: N/A because site didn't load.
  • Eleventy version: 1.0.0-beta.2
  • Slinkity version: 0.1.10

Additional context
Add any other context about the problem here.

Docs - introduce fluid type scaling

Where did our docs fail you?

We currently use whatever font sizes the browser provides by default across headings. This is fine, but could cause inconsistent user experiences. We mostly avoided custom sizing because it's so dang hard to configure and scale across breakpoints.

How can we improve?

I saw @AleksandrHovhannisyan's fluid type scale site and thought "yes, that's the one!". I say we use this to configure our font sizes asap 😁

  • min font size: 14px
  • max font size: 18px (our body font runs a bit smaller than other typefaces I've used, so 16px doesn't feel right to me)

Fix documentation layout - sticky TOC

Where did our docs fail you?

While scrolling to the documentation, I expect the table of contents to remain fixed on the side for easy browsing. Instead, the TOC scrolls with the content.

How can we improve?

Introduce position: sticky to keep that TOC in view while I scroll!

Rework component props storage to handle styles + squoosh some bugs

Is your feature request related to a problem? Please describe.
Right now, we keep track of a given component's props based on the path. It all comes down to this object at the top of our React plugin:

const componentToPropsMap = {}

This object gets passed to our shortcode and our page extension to keep track of everyone's props. Otherwise, we wouldn't know which props to apply in our HTML transform.

Using the component's path as the key is very limiting. It causes a few major issues:

  1. If you attempt to hydrate the same component multiple times with different props, you'll get an incorrect result
  2. If we want to keep track of other properties related to a component (ex. CSS module styles), we can't! We'd need to restructure the value of our map to have multiple keys

Describe the solution you'd like

I'd like to rework our map in 2 ways:

  • change the key from a component path to a randomized hash. This hash will be applied to component mount points as an attribute, which our HTML transform will pick up for finding associated props
  • change the value to an object with multiple keys: { props, styles }. We could add more in the future.

Describe alternatives you've considered
We've considered inserting the props and styles directly into the HTML output whenever a shortcode or page is processed. This has a major problem for props in particular though: we'll need to stringify our props using the JS stringify helper (no, we don't use JSON stringify!). In order to read this value in the transform, we'd likely need to run an eval over the stringified props, which is... very dangerous.

Lazy hydration broken in production builds

Describe the bug
When using render: 'lazy' on a component, all resources are still loaded on page load from production builds.

To Reproduce
Steps to reproduce the behavior:

  1. Use render: 'lazy' on any component shortcode
  2. Run slinkity to complete a production build
  3. Visit that production build using a local server (say, npx serve _site)
  4. Notice that all resources are loaded even when component is not visible on the page. In fact, module preload scripts are present in the head for all vendor bundles!

Expected behavior
Resources should only appear in the network activity when your component is visible on the page.

Add instructions for running example to README

Is your feature request related to a problem? Please describe.

  • New users might be confused about how to get a boilerplate Slinkity app up and running, especially if they aren't familiar with 11ty.

Describe the solution you'd like

  • Provide instructions in README.md to run the example contained in this repo.

Describe alternatives you've considered

  • An init command that generates a boilerplate would also be useful.

Additional context

  • Instructions for running the example project:
git clone https://github.com/slinkity/slinkity/
cd slinkity/example
npm i --save-dev slinkity @11ty/[email protected]
npm i react react-dom
npx slinkity --serve

Screen Shot 2021-09-09 at 10 51 44 AM

Add a `slinkity.config` for all configuration options

Is your feature request related to a problem? Please describe.
We don't support any configuration options right now (apart from CLI flags). This will become more problematic as we add features that could mess with your existing 11ty setup!

Describe the solution you'd like

We should support a slinkity.config.js for configuring all Slinkity options. I'd want to follow Vite's config format for this, since they've definitely figured out clean type checking in TS and JS files using the defineConfig wrapper. By comparison, eleventy's approach is a bit less traditional and harder to type check.

Describe alternatives you've considered
I also considered exposing Slinkity as a plugin within your existing .eleventy.js config. So if you want to configure anything, you'd need to import Slinkity as a plugin like so:

const { slinkityPlugin } = require('slinkity')

module.exports = function(eleventyConfig) {
  eleventyConfig.addPlugin(slinkity, { ...options })
}

However, this would be very hard to parse given 11ty's lack of async plugin support. I could see this in the longer term if we drop the slinkity CLI entirely. But for now, just creating our own config file seems like the path of least resistance.

Additional context
One important piece is Vite's use of ESM syntax. I'd like to do the same to make TypeScript + type importing a nicer experience. But we'll need to mention an important caveat: if you import a dependency into your slinkity config, and it doesn't have a CommonJS version, it will probably break! This is because 11ty (and Slinkity itself) still run on CommonJS imports only. I hope to change this as soon as we can.

Docs redesign - new navigation structure + theming

New designs

Sidebar changes:

  • a nicer experience for mobile and tablet users - a collapsable menu you can summon from anywhere on the page (instead of scrolling back to the top)
  • new section headings to better surface our pages
  • a nicer a e s t h e t i c in keeping with our retro theme 😎

Primary nav changes:

  • a new purple background to match our new theme

Documentation content changes:

  • a dull purple background to match our new theme

Mobile and tablet breakpoints

Note: These should match with the breakpoint(mobile) and breakpoint(tablet) values under our SCSS functions

image

Desktop and above

image

Code changes

  • we'll likely need a new mixin to represent those nav section headings. I say "mixin" since it'll be a combo of font-family, text-transform to all caps, and wider letter-spacing. I'm open to any naming scheme here; maybe subheading or decorative-heading?
  • we currently assume all visitors have the Monaco font on their device, but this probably isn't sustainable! We should probably find this font face and add it to our assets/fonts directory.
  • the docs.11tydata.js will need a new data structure to support section headings. The section headings shown in the mockup are intended for production (it's not dummy data!), so structure our data to support that. i18n is out of scope.

PostCSS support (and Tailwind as a sideeffect)

Is your feature request related to a problem? Please describe.
At that time slinkity lacks of PostCSS support.
I know sass supports a huge amount of things, but this is not the only solution to write styles. In my opinion sass or scss syntax with things like some monsterous mixins just slows donw DX. In PostCSS you just install required plugin, set options and continue write your styles with some new magical property or function. In most cases I doesn't need all this sass things like nesting. I can add only a few needed number of this with PostCSS.
This time all that stuff like automatic fallbacks for properties, custom functions, sass-like variables in plain css and of course Tailwind we can't use. Eleventy have templating in markdown, lets add the same functionality to css.

Describe the solution you'd like
Implement slinkity as a plugin or config like in 61#. Then we can pass PostCSS config to vites css.postcss options.
With plain vite I usually add postcss.config.js path and all works fine. As soon this feature will be implemented then all tailwind stuff will be working automagically.

Describe alternatives you've considered
Check for an existence of postcss.config.js and pass this if exists to vites css.postcss. But slinkity config seems more viable solution than that.

Additional context

CSS modules don't work when rendering components without hydration

Describe the bug
When using render='static' on component pages or shortcodes, CSS modules aren't applied to the HTML template.

Expected behavior
I expect my CSS modules to get applied to the page as a <style> tag, similar to how hydrated components work.

Additional context
This is likely an issue with how we store styles alongside our components! At the moment, we only grab related resources for a component (including styles) when we apply our hydration loaders to the page. Ideally, we could apply styles for all components on the page, even if no hydration loaders are present.

Add anchor links to documentation

Where did our docs fail you?

I found a specific section of documentation that was quite helpful. However, I can't copy a link to that specific heading!

How can we improve?

  1. Add unique ids to each heading on our documentation. This should be automated by eleventy, appending IDs to each heading in our documentation (or every markdown file on the site if you prefer).
  2. Show a link icon πŸ”— when hovering over a section heading. On click, we should append that heading's ID to the URL for easy share-ability.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.