Repository: asciidoctor/asciidoctor (Ruby)

Issue:
Don't skip front matter at the top of included files
When the skip-front-matter attribute is set, the parser skips the front matter both at the top of the primary document and at the top of any included file. The latter behavior is unexpected and can produce unexpected results. It should be moved to an option on the include directive named skip-front-matter.


Discussion:
Since the effect of the skip-front-matter attribute was undocumented and untested, we can classify this as a bug / clarification.
As it turns out, there is [a mention](https://docs.asciidoctor.org/asciidoctor/latest/html-backend/skip-front-matter/#skip-front-matter-option) in the Asciidoctor user manual that the skip-front-matter attribute also applies to included files.

> Asciidoctor also removes front matter when reading include files.

Therefore, let's push this to the next minor release.
However, since it doesn't discern between different types of include files, this could end up shaving off lines of a non-AsciiDoc include file. But since this could affect functioning systems, we'll stick with deferring to the next minor.
In [section 76.1](https://asciidoctor.org/docs/user-manual/#front-matter-added-for-static-site-generators) of the user manual, it currently says:

> If the skip-front-matter attribute is set via the CLI or API (e.g., -a skip-front-matter)...

But as far as I can tell, there is currently no discussion in the manual about having the following in the AsciiDoc Document Header of an individual `.adoc` file.

```
:skip-front-matter:
```

I currently use this to skip front matter in any file that is included in that particular `.adoc` file. For example, I use `:skip-front-matter:` in the `.adoc` file that produces my https://www.ii.com/qutebrowser-configpy/. In that `.adoc` file, I have this:

```
----
include::{localincludedir}/included-config-defaults.py[]
----
```

And `included-config-defaults.py` begins with this:

```
---
generated: 2019-08-08 with qb 1.7.0
---

## Autogenerated config.py
## Documentation:
##   qute://help/configuring.html
##   qute://help/settings.html
```

That `generated:` line is for my eyes only and it's useful to be able to do this. Whatever changes you make to the way this works, please document all ways of skipping front matter:

* CLI
* API
* the Asciidoc Document Header of an individual `.adoc` file
* option in the include directive

Thanks!

> as far as I can tell, there is currently no discussion in the manual about having the following in the AsciiDoc Document Header of an individual .adoc file.

That's because that was never the intention of this feature. It's really by accident that this inherits into include files. I understand that this may be needed for include files, but that really should have been an option on the include directive itself.
> I understand that this may be needed for include files, but that really should have been an option on the include directive itself.

I've added support for the `ksip-front-matter` option on the include directive as well.



Patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 4d5c529c91..51b4a4a878 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -35,6 +35,7 @@ Enhancements::
   * Honor `level` and `formatter` keyword arguments passed to Logger constructor (#4250)
   * Add support for skipping TOML front matter (Hugo) when `skip-front-matter` attribute is set (#4300) (*@abhinav*)
   * Add support for Wistia using the video macro
+  * Skip front matter in included content if skip-front-matter option is set on include directive (#3437)
 
 Compliance::
 
@@ -64,6 +65,10 @@ Improvements::
   * Return `nil` if name passed to `Asciidoctor::SafeMode.value_for_name` is not recognized (#3526)
   * Modify default stylesheet to honor text-* roles on quote blocks
 
+Bug Fixes::
+
+  * When skip-front-matter document attribute is set, only skip front matter in primary document, not included content (#3437)
+
 == 2.0.24 (2025-10-13) - @mojavelinux
 
 Compliance::
diff --git a/lib/asciidoctor/reader.rb b/lib/asciidoctor/reader.rb
index 20048da062..bd771d25c1 100644
--- a/lib/asciidoctor/reader.rb
+++ b/lib/asciidoctor/reader.rb
@@ -607,6 +607,7 @@ class PreprocessorReader < Reader
   # Public: Initialize the PreprocessorReader object
   def initialize document, data = nil, cursor = nil, opts = {}
     @sourcemap = (@document = document).sourcemap
+    opts = opts.merge skip_front_matter: true if document.attributes['skip-front-matter'] && (!opts.key? :skip_front_matter)
     super data, cursor, opts
     if (default_include_depth = (document.attributes['max-include-depth'] || 64).to_i) > 0
       # track absolute max depth, current max depth for comparing to include stack size, and relative max depth for reporting
@@ -716,7 +717,7 @@ def push_include data, file = nil, path = nil, lineno = 1, attributes = {}
     end
 
     # effectively fill the buffer
-    if (@lines = prepare_lines data, normalize: @process_lines || :chomp, condense: false, indent: attributes['indent']).empty?
+    if (@lines = prepare_lines data, normalize: @process_lines || :chomp, condense: false, indent: attributes['indent'], skip_front_matter: attributes['skip-front-matter-option']).empty?
       pop_include
     else
       # FIXME we eventually want to handle leveloffset without affecting the lines
@@ -794,8 +795,7 @@ def to_s
   def prepare_lines data, opts = {}
     result = super
 
-    # QUESTION should this work for AsciiDoc table cell content? Currently it does not.
-    if @document && @document.attributes['skip-front-matter'] && (front_matter = skip_front_matter! result)
+    if opts[:skip_front_matter] && (front_matter = skip_front_matter! result)
       @document.attributes['front-matter'] = front_matter.join LF
     end
 


Test patch:
diff --git a/test/fixtures/with-front-matter.adoc b/test/fixtures/with-front-matter.adoc
new file mode 100644
index 0000000000..f14d448476
--- /dev/null
+++ b/test/fixtures/with-front-matter.adoc
@@ -0,0 +1,4 @@
+---
+name: value
+---
+content
diff --git a/test/reader_test.rb b/test/reader_test.rb
index 9ae5bcc355..32515e88cf 100644
--- a/test/reader_test.rb
+++ b/test/reader_test.rb
@@ -585,6 +585,41 @@ class ReaderTest < Minitest::Test
         assert_equal front_matter, doc.attributes['front-matter']
         assert_equal 7, reader.lineno
       end
+
+      test 'should not skip front matter in include file if skip-front-matter attribute is set' do
+        input = <<~'EOS'
+        ....
+        include::fixtures/with-front-matter.adoc[]
+        ....
+        EOS
+        doc = document_from_string input, safe: :safe, parse: false, base_dir: DIRNAME
+        reader = doc.reader
+        expected = [
+          '....',
+          '---',
+          'name: value',
+          '---',
+          'content',
+          '....',
+        ]
+        assert_equal expected, reader.readlines
+      end
+
+      test 'should skip front matter in include file if skip-front-matter option is set on include directiv' do
+        input = <<~'EOS'
+        ....
+        include::fixtures/with-front-matter.adoc[opts=skip-front-matter]
+        ....
+        EOS
+        doc = document_from_string input, safe: :safe, parse: false, base_dir: DIRNAME
+        reader = doc.reader
+        expected = [
+          '....',
+          'content',
+          '....',
+        ]
+        assert_equal expected, reader.readlines
+      end
     end
 
     context 'Include Stack' do