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

Include other files #441

Open
ghost opened this issue Dec 28, 2019 · 6 comments
Open

Include other files #441

ghost opened this issue Dec 28, 2019 · 6 comments

Comments

@ghost
Copy link

ghost commented Dec 28, 2019

Currently it seems it is not possible to include a file, is that the case? Other
projects have this built in:

https://gohugo.io/functions/readfile

@beryllium
Copy link
Member

Sculpin uses the Twig template engine, which has an include function as documented here: https://twig.symfony.com/doc/3.x/functions/include.html

For content that you don't want rendered out to HTML directly, you might want to put it in the source/_includes directory - I'm pretty sure that will make it available as an include without separately rendering the partial file.

@ghost
Copy link
Author

ghost commented Dec 28, 2019

@beryllium thanks, but it doesnt seem to work:

$ cat source/_posts/2012-10-16-balrog.md
---
title: Balrog
tags: [balrog, community, static site generator]
---

~~~
{{ include('day.php') }}
~~~

$ cat source/_posts/day.php
<?php
echo "sunday monday\n";

$ vendor/bin/sculpin generate
Detected new or updated files
Generating: 100% (44 sources / 0.02 seconds)
Converting:  91%
In ChainLoader.php line 98:

  Template "day.php" is not defined in "FileSource:FilesystemDataSource:/tmp/
  blog-skeleton/source:_posts/2012-10-16-balrog.md" at line 1.

@beryllium
Copy link
Member

This was more challenging than I expected at first. Putting the example day.php file in the _posts folder gave me a different (and much less helpful) error message than your example - I'll have to find a way to improve that.

Here is the approach I took to enable your example to work:

$ cat source/_posts/2012-10-16-balrog.md
---
title: Balrog
tags: [balrog, community, static site generator]
categories: [personal]
---
Content:

```
{{include('day.php')|escape('html')}}
```

$ cat source/_includes/day.php
This is a PHP file.

<?php

echo "When Twig includes this file, it will be read as text, NOT executed as PHP.";

So it seems as though _includes is designated in the source as a folder containing twig includes. Other such folders are named _views, _partials, and _layouts. The definition of these values appears to be done here, which indicates that it is customizable in your sculpin_kernel.yml file:

https://github.com/sculpin/sculpin/blob/master/src/Sculpin/Bundle/TwigBundle/DependencyInjection/Configuration.php#L39-L38

Setting custom values in app/config/sculpin_kernel.yml would look like this:

$ cat app/config/sculpin_kernel.yml
sculpin_content_types:
    posts:
        permalink: blog/:year/:month/:day/:filename/

sculpin_twig:
    source_view_paths:
        - _views
        - _layouts
        - _partials
        - _includes
        - _custom

At which point you could store the day.php file in source/_custom/day.php.

@ghost
Copy link
Author

ghost commented Dec 28, 2019

@beryllium thanks very much, but I dont think that is going to work for my use
case. include must be able to accept a relative path, or in the worst case
an absolute path. Further, the "fragments" must be allowed to live next to the
files they would be included in. So something like this would need to be
supported:

source/
   _posts/
      sunday/
         index.md
         one.php
         two.php
      monday/
         index.md
         one.php
         two.php

I am using something like this now with Hugo, but I am looking to move away from
Hugo, just having a hard time finding something that offers the features I use.

@beryllium
Copy link
Member

Looks like this isn't a use case that Sculpin would be able to support without an alternative approach (e.g., delving into the code to create a twig extension that acts like readFile - quite a hassle compared to an out-of-the-box solution, if one can be found).

Another issue is that the _posts folder (or any other Content Type's folder) is kind of treated like a database, so the engine doesn't expect there to be extra files there. If you were making plain pages (not belonging to a Content Type), rather than posts, it would be a bit more amenable to that workflow, but even then there would still be the hassle of creating the class to enable file reading.

Such an extension would look something like this:

<?php

class TwigReadFileExtension extends Twig_Extension
{
    protected $sourceDir;
    public function __construct($sourceDir)
    {
        $this->sourceDir = $sourceDir;
    }

    public function getName()
    {
        return 'readfile_extension';
    }

    public function getFunctions()
    {
        $sourceDir = $this->sourceDir;
        return array(
            new \Twig_SimpleFunction('readfile', function ($file) use ($sourceDir) {
                // @todo add extra logic to prevent filesystem escape & to clean up concatenated path
                return file_get_contents($sourceDir . $file);
            }
        );
    }
}

And it would be configured in the sculpin_kernel.yml file similar to this:

services:
  readFileExtension:
    class: TwigReadFileExtension
    arguments:
      $sourceDir: '%sculpin.sourceDir%'
    tags:
    - 'twig.extension'
    public: true

The suggestions above are untested, so there might be unexpected roadblocks. For example, autoloading won't know where to look out of the box without configuring composer.json for it, so adding a manual require "TwigReadFileExtension.php"; to the top of SculpinKernel.php might be a quick way to get the class loaded. I might have misremembered the exact name of the %sculpin.sourceDir% parameter in the dependency injection container. And logic might need to be added elsewhere to skip the non-markdown files in the source/_posts/ folder.

@ghost
Copy link
Author

ghost commented Jan 8, 2020

Darn, I thought I had something. I see reStructuredText has ability to include
files:

https://docutils.sourceforge.io/docs/ref/rst/directives.html#include

bypassing any need to Sculpin to do it. However RST is not supported with
Sculpin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant