Flutter-Bounty-Hunters / static_shock

A static site generator for Dart.
MIT License
59 stars 5 forks source link

[Shock] - Support componentized file structure #78

Open matthew-carroll opened 3 months ago

matthew-carroll commented 3 months ago

Static Shock currently supports pipeline access to layouts and components. Those are currently defined a specific location.

For example:

/source/
  _includes/
    components/
    layouts/

Similarly, the Sass plugin compiles Sass to CSS, again from a specific location:

/source/
  styles/

Images also tend to be stored in a global location:

/source/
  images/

That said, image are found with Pickers, which offer more control than the layout and component hard-coded locations.

These locations might be configurable, but they're always just one location. This concept of a global location leads to global references, which can work against natural packaging.

Templates and styles beside the content

Consider a website that has a bunch of guides, all of which use the same template and styles. It might be desirable to create a directory for the content, template, and styles, as shown below:

/source/
  guides/
    _data.yaml
    guide.jinja
    guide.sass
    my-guide-1.md
    my-guide-2/
      index.md
      screenshot-1.png
      screenshot-2.png
    my-guide-3.md

In this example, there's no good reason to force guide.jinja into /source/_includes/layouts/ and there's no reason to force guide.sass into /source/styles/.

Holistic Components

A layout or component likely includes HTML and CSS. It may even include JS. It would be nice to be able to define such a component across multiple files:

/source/
  _includes/
    components/
      footer.html
      google-analytics.html
      navbar.jinja
      table-of-contents/
        component.html
        styles.sass
        scripts.js
    layouts/
      top-level-page/
        layout.html
        styles.sass
        scripts.js

Challenges

To support arbitrary layout and component locations, we'd need to figure out at least the following issues:

Ideas

We could introduce an extension for layouts and components: my-layout.jinja.layout and my-component.jinja.component.

When looking specifically within /source/_includes/components/ and /source/_includes/layouts/ we could look specifically for a file called component.xxxx and layout.xxxx, respectively. The layout is probably always Jinja at this point. But the component could be .html, .jinja, .txt, or anything else.

suragch commented 1 month ago

I'm writing an article that has several screen shots. I'd like to keep the images close to the article source text. The following structure would be nice:

source/
    posts/
        my-post-one/
            img/
                image1.png
                image2.png
            my-post-one.md
        my-post-two/
            img/
                image1.png
                image2.png
            my-post-two.md

From within the article text, I would reference the images like so:

![My Image](./img/image1.png)
![My Image](./img/image2.png)

The two posts would be available at:

Is this currently possible or is this what this issue is addressing?

See also Docusaurus images

matthew-carroll commented 1 month ago

Can you give it a try and see what happens? The only thing I know that you need to change is that if you want the directory name to essentially be the URL, you need to name the inner Markdown file as index.md. That way it becomes index.html, and the web server will automatically server that file when the user requests the directory.

Example:

mydomain.com/posts/my-post-one/

vs

mydomain.com/posts/my-post-one/my-post-one.html

The image placement, in theory, should work. But I'd like for you to try it to see if something in the path/url management blows up. We map from a file path to a final URL path which has some intermediate steps that might get screwed up. But I'd like for this goal to be possible if it's not already.

matthew-carroll commented 1 month ago

Also, is there something specific about the Docusaurus images that you wanted me to see?

suragch commented 1 month ago

I'm trying it out with this file structure:

Screenshot 2024-05-17 at 12 52 57

Here is my /source/posts/my-post-one/index.md:

---
title: Text
description: Testing images
layout: layouts/homepage.jinja
---

# This is a test

![My Image](./img/image1.png)
![My Image](./img/image2.png)

This is the result that I see in the browser:

Screenshot 2024-05-17 at 12 51 40

After further investigation...

I see now that I need to add a new picker in main.dart:

..pick(DirectoryPicker.parse("images"))
..pick(DirectoryPicker.parse("posts/my-post-one/img")) // new line

Now it works:

Screenshot 2024-05-17 at 13 03 21

Ideally, I would prefer not to have to add a new picker for every article I write. But I guess a picker is already better than my current strategy, which has been to replicate the article file structure within the images folder.

Also, is there something specific about the Docusaurus images that you wanted me to see?

Docusaurus allows relative links to images within the article working directory (as SS also does I now understand) but without adding additional configuration elsewhere.

matthew-carroll commented 1 month ago

Can you use an ExtensionPicker to pick all the images in your source set to avoid all that work to pick per post?

https://pub.dev/documentation/static_shock/latest/static_shock/ExtensionPicker-class.html

matthew-carroll commented 1 month ago

Also, do your problems go away if you change a path like ./img/image1.png to img/image1.png?

suragch commented 1 month ago

Nice! Using ..pick(ExtensionPicker('png')) worked.

Changing ./img/image1.png to img/image1.png didn't change anything. It didn't work without the extension picker and it still worked with the extension picker.

matthew-carroll commented 1 month ago

Changing ./img/image1.png to img/image1.png didn't change anything. It didn't work without the extension picker and it still worked with the extension picker.

I'm a little confused. Are you saying that relative paths ./img/image1.png did work once you switched to the extension picker?

I thought you were describing two separate issues: picking the images, and referencing the images. I want to make sure that relative references are working for you.

suragch commented 1 month ago

My only problem was picking the images (getting them copied to the build folder). Referencing the images (once they exist in the build folder) is not an issue. The relative path works.

matthew-carroll commented 1 month ago

Great! Anything else holding you back from a componentized file structure? Or anything else we should look into to consider that approach implemented?

When I filed this ticket I wasn't sure what I would find. Maybe it was gonna work, maybe it wasn't. If you can think of any other way to stress test the goal, that would be great.

suragch commented 1 month ago

At this point I'm not trying to move styling or layout to a subfolder, but I see how it can be done. I would probably use a file picker for that.

I don't know how to differentiate a layout/component vs a piece of content/asset in the general case, but I think we can assume that media files (png, jpg, mp3, mp4, etc) are content. These can be automatically copied without making the user do it. That is, there can be a media picker in the SS generated default project.

matthew-carroll commented 1 month ago

At the moment, all files under _includes/layouts are considered layout templates, and everything under _includes/components are considered component templates. Conversely, everything outside those directories are NOT considered either a layout template or a component. So that's the hard and fast rule right now.

If you check the original issue that I filed, you'll see that I'm considering altering that particular approach.