Oh I got it! I got clues from the Jekyll Feed plugin, which generates a feed.xml file based on pages on the site.
It uses PageWithoutAFile so it doesn’t get the read error. See jekyll-feed source.
Here is my plugin. It generates a file my-file.xml with one row abcdef.
module SamplePlugin
class MyPageGenerator < Jekyll::Generator
safe true
def generate(site)
dir = '.'
name = 'my-file.xml'
site.pages << Jekyll::PageWithoutAFile.new(site, site.source, dir, name).tap do |file|
file.content = 'abcdef'
file.data.merge!(
"layout" => nil,
"sitemap" => false,
)
file.output
end
end
end
end
I made layout nil so there is nothing else on the page. OR you can use a layout - the abcdef content gets inserted as {{ content }} of the layout.
To do that, replace nil above, or take out the merge and set layouts for all pages to be page in config file.