- blank = **BOOL** - if true, stops parsing and returns an empty string
 - panic_default = **BOOL** - if true, panics on an undefined default pattern
 - panic_undefined = **BOOL** - if true, panics on an undefined variable or array
+- source = **STRING** - change the the filetype of the source file
+- filetype = **STRING** - change the filetype of the output file
 - equal_arrays = **BOOL** - if true, panics if arrays in the same pattern have different sizes
+- pandoc = **BOOL** - toggles if pandoc is ran on this file to convert between filetypes, defaults to *true* in **source** dir, and *false* in **pattern** dir.
 
 ### source
 
 - ignore = **BOOL** - stops parsing and skips this file, useful for ignoring directories with scoped definitions
-- source = **STRING** - change the the filetype of the source file
-- filetype = **STRING** - change the filetype of the output file
-- pandoc = **BOOL** - toggles if pandoc is ran on this file to convert between filetypes
 - copy_only = **BOOL** - copys file or directory without processing anything
 
 
 - spaces are correctly preserved between directly adjacent substitutions
 - copy_only header directive
+- pandoc header now works on pattern files
 
 ## versions
-- 0.1.3: grammar update
+- 0.1.3: grammar update, new header directives
 - 0.1.2: multithreading
 - 0.1.1: initial release
 
--- /dev/null
+#{ pandoc = true }
+
+# GOOD
 
--- /dev/null
+&{test = 'pandoc'}
+
+source
 
         })),
     }?;
 
-    let file = parse_string(source, opts)?;
+    let mut file = parse_string(source, opts)?;
 
     Ok(file.construct()?)
 }
 
 use std::{collections::HashMap, path::PathBuf};
 
 use super::*;
+
 #[derive(Debug, Clone)]
 pub struct MetaFile<'a> {
     pub opts: &'a Options,
         Ok(metafile)
     }
 
-    pub fn construct(&self) -> Result<String, Box<MetaError>> {
+    pub fn construct(&mut self) -> Result<String, Box<MetaError>> {
         log!(self.opts, format!("building {}", self.path.display()), 1);
 
         if self.header.blank {
             return Err(Box::new(MetaError::Ignored));
         }
 
-        let html = self.to_html().map_err(MetaError::from)?;
+        let src_str: String;
+        if self.header.pandoc.map_or(true, |x| x) {
+            src_str = self.pandoc().map_err(MetaError::from)?;
+        } else {
+            src_str = self.get_source().map_err(MetaError::from)?;
+        }
 
         let pattern = self.get_pattern("base").map_err(MetaError::from)?;
         let mut base = parse_string(pattern, self.opts).map_err(|e| MetaError::ParserError {
         })?;
 
         base.merge(self);
-        base.patterns.insert(Scope::create_global("SOURCE"), html);
+        base.patterns
+            .insert(Scope::create_global("SOURCE"), src_str);
         let mut base_path = self.opts.pattern.join("base").join(
             self.patterns
                 .get(&Scope::create_global("base"))
 
         // copy over maps for expanding contained variables
         pattern.merge(self);
 
-        pattern.get_source()
+        if pattern.header.pandoc.unwrap_or(false) {
+            pattern.pandoc()
+        } else {
+            pattern.get_source()
+        }
     }
 }
 
 use super::*;
 
 impl<'a> MetaFile<'a> {
-    pub fn to_html(&self) -> Result<String> {
+    pub fn pandoc(&mut self) -> Result<String> {
         let string = self.get_source()?;
 
-        if self.opts.no_pandoc || !self.header.pandoc || string.is_empty() {
+        if self.opts.no_pandoc || string.is_empty() {
             return Ok(string);
         }
 
             .set_output_format(output, vec![]);
 
         if let pandoc::PandocOutput::ToBuffer(s) = pandoc.execute()? {
+            self.header.pandoc = Some(false);
             Ok(s)
         } else {
             Err(MetaError::Pandoc { file: self.name()? }.into())
 
     pub equal_arrays: bool,
     pub filetype: String,
     pub source: String,
-    pub pandoc: bool,
+    pub pandoc: Option<bool>,
     pub ignore: bool,
     pub copy_only: bool,
 }
             equal_arrays: false,
             filetype: String::from("html"),
             source: String::from("markdown"),
-            pandoc: true,
+            pandoc: None,
             ignore: false,
             copy_only: false,
         }
                 "panic_default" => header.panic_default = val == "true",
                 "panic_undefined" => header.panic_undefined = val == "true",
                 "equal_arrays" => header.equal_arrays = val == "true",
-                "pandoc" => header.pandoc = val == "true",
+                "pandoc" => header.pandoc = Some(val == "true"),
                 "filetype" => header.filetype = val.to_string(),
                 "source" => header.source = val.to_string(),
                 "ignore" => header.ignore = val == "true",
 
             let test_dir = opts.source.join("unit_tests");
             let mut path = test_dir.join($file);
             path.set_extension("meta");
-            let file = MetaFile::build(path, &opts)?;
+            let mut file = MetaFile::build(path, &opts)?;
 
             let str = match file.construct() {
                 Ok(f) => f,
             let test_dir = opts.source.join("unit_tests");
             let mut path = test_dir.join($file);
             path.set_extension("meta");
-            let file = MetaFile::build(path, &opts).unwrap();
+            let mut file = MetaFile::build(path, &opts).unwrap();
             assert_eq!(file.construct().unwrap(), $test);
         }
     };
     r#"variable: ${this} should get copied verbatim"#
 );
 
+unit_test!(
+    expandoc,
+    "header/expandoc",
+    "<html>\n<h1 id=\"good\">GOOD</h1>\n\n\n</html>\n"
+);
+
 panic_test!(ignore, "ignore.meta", "");
 
 #[test]