diff --git a/Sources/MarkdownUtilities/FormatConversion/HTML/HTMLOptions.swift b/Sources/MarkdownUtilities/FormatConversion/HTML/HTMLOptions.swift
new file mode 100644
index 0000000..f4d3a12
--- /dev/null
+++ b/Sources/MarkdownUtilities/FormatConversion/HTML/HTMLOptions.swift
@@ -0,0 +1,60 @@
+/// Configuration options for Markdown → HTML conversion.
+public struct HTMLOptions: ConversionOptions, Sendable {
+
+ // MARK: - ConversionOptions
+
+ /// Prepend YAML frontmatter as an HTML comment (``).
+ public var includeFrontmatter: Bool
+
+ // MARK: - Document structure
+
+ /// Wrap the rendered body in a minimal HTML document skeleton:
+ /// `
…`.
+ public var wrapInDocument: Bool
+
+ // MARK: - Rendering behaviour
+
+ /// Render soft line breaks as `
` instead of a space.
+ public var hardBreaks: Bool
+
+ /// Pass raw HTML through unchanged (unsafe). When `false`, raw HTML is
+ /// replaced with an HTML comment placeholder.
+ public var allowUnsafeHTML: Bool
+
+ /// Convert straight quotes to curly, `---` to em dashes, `--` to en dashes.
+ public var smartPunctuation: Bool
+
+ // MARK: - Feature toggles
+
+ /// Which GFM extensions to enable. Defaults to `.all`.
+ public var extensions: MarkdownExtensionOptions
+
+ // MARK: - Default
+
+ /// Default options: no frontmatter, no document wrapper, soft breaks,
+ /// safe HTML, no smart punctuation, all GFM extensions enabled.
+ public static let `default` = HTMLOptions(
+ includeFrontmatter: false,
+ wrapInDocument: false,
+ hardBreaks: false,
+ allowUnsafeHTML: false,
+ smartPunctuation: false,
+ extensions: .all
+ )
+
+ public init(
+ includeFrontmatter: Bool = false,
+ wrapInDocument: Bool = false,
+ hardBreaks: Bool = false,
+ allowUnsafeHTML: Bool = false,
+ smartPunctuation: Bool = false,
+ extensions: MarkdownExtensionOptions = .all
+ ) {
+ self.includeFrontmatter = includeFrontmatter
+ self.wrapInDocument = wrapInDocument
+ self.hardBreaks = hardBreaks
+ self.allowUnsafeHTML = allowUnsafeHTML
+ self.smartPunctuation = smartPunctuation
+ self.extensions = extensions
+ }
+}
diff --git a/Sources/MarkdownUtilities/FormatConversion/HTML/MarkdownExtensionOptions.swift b/Sources/MarkdownUtilities/FormatConversion/HTML/MarkdownExtensionOptions.swift
new file mode 100644
index 0000000..bc2bef0
--- /dev/null
+++ b/Sources/MarkdownUtilities/FormatConversion/HTML/MarkdownExtensionOptions.swift
@@ -0,0 +1,62 @@
+import MarkdownSyntax
+
+/// Controls which GFM extensions are active during Markdown → HTML rendering.
+///
+/// This is our public API for toggling individual features. Internally it maps to
+/// `CMExtensionOption` — users never touch that type directly.
+///
+/// Use `.all` (the default) for full GFM support or `.none` for CommonMark-only output.
+/// Individual options can be combined using set operations:
+/// ```swift
+/// var options = MarkdownExtensionOptions.all
+/// options.remove(.tables) // all GFM except tables
+///
+/// let tablesOnly: MarkdownExtensionOptions = [.tables]
+/// ```
+public struct MarkdownExtensionOptions: OptionSet, Sendable {
+ public let rawValue: Int64
+ public init(rawValue: Int64) { self.rawValue = rawValue }
+
+ /// No GFM extensions — CommonMark only.
+ public static let none: MarkdownExtensionOptions = []
+
+ /// All supported GFM extensions (tables, autolinks, strikethrough, tagfilters, tasklist).
+ public static let all: MarkdownExtensionOptions = [.tables, .autolinks, .strikethrough, .tagfilters, .tasklist]
+
+ // MARK: - GFM Extensions (bits 0–4, matching CMExtensionOption's layout)
+
+ /// GFM pipe tables.
+ public static let tables = MarkdownExtensionOptions(rawValue: 1)
+
+ /// URL autolinks.
+ public static let autolinks = MarkdownExtensionOptions(rawValue: 2)
+
+ /// `~~Strikethrough~~` via double tildes.
+ public static let strikethrough = MarkdownExtensionOptions(rawValue: 4)
+
+ /// Filter unsafe HTML tags from output (e.g. `