d4l-data4life / kirby3-static-site-generator

Static site generator plugin for Kirby 3+. With this plugin you can create a directory with assets, media and static html files generated from your pages. The result is an even faster site with less potential vulnerabilities.
MIT License
134 stars 8 forks source link

Generating single page after first statics page were created #41

Closed psntr closed 3 years ago

psntr commented 3 years ago

Hello!

I don't think it's a bug but rather a misconfiguration on my end. I'm a bit struggling to understand how a page would be generated after the first initial page generation (via the panel). From the readme.md one should use the default kirby hooks, in my case I opted for the page.update:after. So this is what I have based on the doc and by going through previous posts issues:

In my config file I want to put a parameters $pages for the new D4L\StaticSiteGenerator to prevent re-indexing all the pages again.

'd4l' => [
        'static_site_generator' => [
            'endpoint' => 'generate-static-site', # set to any string like 'generate-static-site' to use the built-in endpoint (necessary when using the blueprint field)
            'output_folder' => './static', # you can specify an absolute or relative path
            'preserve' => [], # preserve individual files / folders in the root level of the output folder (anything starting with "." is always preserved)
            'base_url' => '/', # if the static site is not mounted to the root folder of your domain, change accordingly here
            'skip_media' => false, # set to true to skip copying media files, e.g. when they are already on a CDN; combinable with 'preserve' => ['media']
            'skip_templates' => [] # ignore pages with given templates (home is always rendered)
        ]
    ],
'hooks' => [
        'page.update:after' => function ($newPage, $oldPage) {
            $kirby = kirby();
            $pageID = $newPage->id();
            $tmplt = $kirby->page($pageID);
            // Using $tmplt instead of $pageID returns same error
            $tmplts = $kirby->page($pageID)->children()
            // Using $tmplts instead of $pageID doesn't generate pages
            $staticSiteGenerator = new D4L\StaticSiteGenerator($kirby, null, $pageID);
            $fileList = $staticSiteGenerator->generate($outputFolder = './static', $baseUrl = '/', $preserve = []);
        }
    ]

Expected Behavior

To only render the current page that is being updated not re-rendered all the index. I saw there is a way to skip templates, but not sure it's what I want because it will still render the siblings because they have the same templates?

Current Behavior

It's throws an error:

The form could not be saved
Exception: TypeError
D4L\StaticSiteGenerator::__construct(): Argument #3 ($pages) must be of type ?Kirby\Cms\Pages, string given, called in /path/site/config/config.php on line 45

Or it doesn't generate pages when using the $tmplts = $kirby->page($pageID)->children().

Steps to Reproduce

Context

PHP: 8.0 "getkirby/cms": "^3.5", "d4l/kirby-static-site-generator": "^1.1", "hashandsalt/kirby3-webp": "^0.0.6", "bnomei/kirby3-janitor": "^2.8"

jonathan-reisdorf commented 3 years ago

Hi @psntr,

it is officially not supported to partially render pages while preserving the rest. There are ways to do this and I'll post a hook example here, but it has a lot of limitations:

'hooks' => [
  'page.update:after' => function ($newPage) {
    $kirby = kirby();
    $pages = $newPage->index();
    $pages->add($newPage);
    $staticSiteGenerator = new D4L\StaticSiteGenerator($kirby, ['...'], $pages);
    $staticSiteGenerator->generate('./static', '/', Kirby\Toolkit\Dir::read('./static', [], false));
  },
],

Explanation: $pages = $newPage->index(); gets a flat child index of the changed page, then we add the currently changed page with $pages->add($newPage);. This pages collection you can then pass to the static site generator.

However, by default, the generator erases all files in the target folder before generation, which means we have to circumvent this mechanism here to partially generate just one page and its descendants while preserving the rest of the previously generated pages and assets. That is done by passing an array with an invalid path ['...'] to the constructor and flagging all previously existing files and folders as preserved by passing Kirby\Toolkit\Dir::read('./static', [], false) to generate() (-> an array with all previously existing file and folder child items of the static folder).

While this works, it comes as already mentioned with a lot of limitations:

jonathan-reisdorf commented 3 years ago

An example which works for basic content changes has been provided - closing the issue. Please feel free to reopen if there are questions left.