diff --git a/readme.nml b/readme.nml
index 5ee349e..55190a3 100644
--- a/readme.nml
+++ b/readme.nml
@@ -3,7 +3,7 @@
 @'html.css = style.css
 
 @tex.main.fontsize = 9
-@tex.main.preamble = \usepackage{xcolor} \\
+@tex.main.preamble = \usepackage{xcolor, amsmath} \\
 \definecolor{__color1}{HTML}{d5d5d5} \\
 \everymath{\color{__color1}\displaystyle}
 @tex.main.block_prepend = \color{__color1}
@@ -77,7 +77,7 @@ end
 
 Evaluating `!` from a kernel: `\%<![kernel] eval>\%`
 
- * `\%<![example] make_bold("Hello, World!")>\%` → %<![example] make_bold("Hello, World!")>%
+ * `\%<[example]! make_bold("Hello, World!")>\%` → %<[example]! make_bold("Hello, World!")>%
 
 # Latex
 
diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs
index 5e1768e..2ba9480 100644
--- a/src/compiler/compiler.rs
+++ b/src/compiler/compiler.rs
@@ -62,12 +62,12 @@ impl Compiler
 		}
 	}
 
-	pub fn header(&self, document: &Document) -> String
+	pub fn header(&self, document: &dyn Document) -> String
 	{
-		pub fn get_variable_or_error(document: &Document, var_name: &'static str) -> Option<Rc<dyn Variable>>
+		pub fn get_variable_or_error(document: &dyn Document, var_name: &'static str) -> Option<Rc<dyn Variable>>
 		{
 			document.get_variable(var_name)
-				.and_then(|(_, var)| Some(var))
+				.and_then(|var| Some(var))
 				.or_else(|| {
 					println!("Missing variable `{var_name}` in {}", document.source().name());
 					None
@@ -85,7 +85,7 @@ impl Compiler
 					result += format!("<title>{}</title>", self.sanitize(page_title.to_string())).as_str();
 				}
 
-				if let Some((_, css)) = document.get_variable("html.css")
+				if let Some(css) = document.get_variable("html.css")
 				{
 					result += format!("<link rel=\"stylesheet\" href=\"{}\">", self.sanitize(css.to_string())).as_str();
 				}
@@ -101,7 +101,7 @@ impl Compiler
 		result
 	}
 
-	pub fn footer(&self, _document: &Document) -> String
+	pub fn footer(&self, _document: &dyn Document) -> String
 	{
 		let mut result = String::new();
 		match self.target()
@@ -116,10 +116,10 @@ impl Compiler
 		result
 	}
 	
-	pub fn compile(&self, document: &Document) -> String
+	pub fn compile(&self, document: &dyn Document) -> String
 	{
 		let mut out = String::new();
-		let borrow = document.content.borrow();
+		let borrow = document.content().borrow();
 
 		// Header
 		out += self.header(document).as_str();
diff --git a/src/document/document.rs b/src/document/document.rs
index 5abf275..9f5886e 100644
--- a/src/document/document.rs
+++ b/src/document/document.rs
@@ -8,16 +8,19 @@ use super::element::Element;
 use super::variable::Variable;
 
 
+// TODO: Referenceable rework
+// Usize based referencing is not an acceptable method
+// if we want to support deltas for the lsp
 #[derive(Debug)]
 pub struct Scope {
     /// List of all referenceable elements in current scope.
-    /// All elements in this should return a non empty 
+    /// All elements in this should return a non empty
 	pub referenceable: HashMap<String, usize>,
 	pub variables: HashMap<String, Rc<dyn Variable>>,
 }
 
 impl Scope {
-	fn new() -> Self {
+	pub fn new() -> Self {
 		Self {
 			referenceable: HashMap::new(),
 			variables: HashMap::new(),
@@ -54,113 +57,82 @@ impl Scope {
     }
 }
 
-#[derive(Debug)]
-pub struct Document<'a> {
-	source: Rc<dyn Source>,
-	parent: Option<&'a Document<'a>>, /// Document's parent
+pub trait Document<'a>: core::fmt::Debug
+{
+	/// Gets the document [`Source`]
+	fn source(&self) -> Rc<dyn Source>;
 
-	// FIXME: Render these fields private
-	pub content: RefCell<Vec<Box<dyn Element>>>,
-	pub scope: RefCell<Scope>,
-}
+	/// Gets the document parent (if it exists)
+	fn parent(&self) -> Option<&'a dyn Document<'a>>;
 
-impl<'a> Document<'a>  {
-	pub fn new(source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Self
+	/// Gets the document content
+	/// The content is essentially the AST for the document
+	fn content(&self) -> &RefCell<Vec<Box<dyn Element>>>;
+
+	/// Gets the document [`Scope`]
+	fn scope(&self) -> &RefCell<Scope>;
+
+	/// Pushes a new element into the document's content
+	fn push(&self, elem: Box<dyn Element>)
 	{
-		Self {
-			source: source,
-			parent: parent,
-			content: RefCell::new(Vec::new()),
-			scope: RefCell::new(Scope::new()),
-		}
+		// TODO: RefTable
+
+		self.content()
+			.borrow_mut()
+			.push(elem);
 	}
 
-	pub fn source(&self) -> Rc<dyn Source> { self.source.clone() }
 
-    pub fn parent(&self) -> Option<&Document> { self.parent }
-
-    /// Push an element [`elem`] to content. [`in_paragraph`] is true if a paragraph is active
-	pub fn push(&self, elem: Box<dyn Element>)
+	/*
+	fn last_element(&'a self, recurse: bool) -> Option<Ref<'_, dyn Element>>
 	{
-        // Add index of current element to scope's reference table
-        if let Some(referenceable) = elem.as_referenceable()
-        {
-            // Only add if referenceable holds a reference
-            if let Some(ref_name) = referenceable.reference_name()
-            {
-                self.scope.borrow_mut().referenceable.insert(ref_name.clone(), self.content.borrow().len());
-            }
-        }
-
-		self.content.borrow_mut().push(elem);
-	}
-
-	pub fn last_element<T: Element>(&self, recurse: bool) -> Option<Ref<'_, T>>
-	{
-		let elem = Ref::filter_map(self.content.borrow(),
+		let elem = Ref::filter_map(self.content().borrow(),
 		|content| content.last()
-			.and_then(|last| last.downcast_ref::<T>())).ok();
+			.and_then(|last| last.downcast_ref::<Element>())
+		).ok();
+
 
 		if elem.is_some() || !recurse { return elem }
 
-		match self.parent
+		match self.parent()
 		{
 			None => None,
 			Some(parent) => parent.last_element(true),
 		}
 	}
 
-	pub fn last_element_mut<T: Element>(&self, recurse: bool) -> Option<RefMut<'_, T>>
+	fn last_element_mut(&'a self, recurse: bool) -> Option<RefMut<'_, dyn Element>>
 	{
-		let elem = RefMut::filter_map(self.content.borrow_mut(),
-		|content| content.last_mut()
-			.and_then(|last| last.downcast_mut::<T>())).ok();
+		let elem = RefMut::filter_map(self.content().borrow_mut(),
+		|content| content.last_mut()).ok();
 
 		if elem.is_some() || !recurse { return elem }
 
-		match self.parent
+		match self.parent()
 		{
 			None => None,
 			Some(parent) => parent.last_element_mut(true),
 		}
 	}
+	*/
 
-	pub fn get_reference(&self, ref_name: &str) -> Option<(&Document<'a>, std::cell::Ref<'_, Box<dyn Element>>)> {
-		match self.scope.borrow().referenceable.get(ref_name) {
-			// Return if found
-			Some(elem) => {
-                return Some((&self,
-                    std::cell::Ref::map(self.content.borrow(),
-                    |m| &m[*elem])))
-            },
-
-			// Continue search recursively
-			None => match self.parent {
-				Some(parent) => return parent.get_reference(ref_name),
-
-				// Not found
-				None => return None,
-			}
-		}
-	}
-
-    pub fn add_variable(&self, variable: Rc<dyn Variable>)
+    fn add_variable(&self, variable: Rc<dyn Variable>)
     {
-        self.scope.borrow_mut().variables.insert(
+        self.scope().borrow_mut().variables.insert(
             variable.name().to_string(),
             variable);
     }
 
-    pub fn get_variable<S: AsRef<str>>(&self, name: S) -> Option<(&Document<'a>, Rc<dyn Variable>)>
+    fn get_variable(&self, name: &str) -> Option<Rc<dyn Variable>>
     {
-        match self.scope.borrow().variables.get(name.as_ref())
+        match self.scope().borrow().variables.get(name)
         {
             Some(variable) => {
-                return Some((&self, variable.clone()));
+                return Some(variable.clone());
             },
 
 			// Continue search recursively
-            None => match self.parent {
+            None => match self.parent() {
                 Some(parent) => return parent.get_variable(name),
 
                 // Not found
@@ -169,16 +141,16 @@ impl<'a> Document<'a>  {
         }
     }
 
-	pub fn remove_variable<S: AsRef<str>>(&self, name: S) -> Option<(&Document<'a>, Rc<dyn Variable>)>
+	fn remove_variable(&self, name: &str) -> Option<Rc<dyn Variable>>
 	{
-        match self.scope.borrow_mut().variables.remove(name.as_ref())
+        match self.scope().borrow_mut().variables.remove(name)
         {
             Some(variable) => {
-                return Some((&self, variable.clone()));
+                return Some(variable.clone());
             },
 
 			// Continue search recursively
-            None => match self.parent {
+            None => match self.parent() {
                 Some(parent) => return parent.remove_variable(name),
 
                 // Not found
@@ -188,23 +160,44 @@ impl<'a> Document<'a>  {
 	}
 
     /// Merges [`other`] into [`self`]
-    pub fn merge(&self, other: Document, merge_as: Option<&String>)
+    fn merge(&self, content: &RefCell<Vec<Box<dyn Element>>>, scope: &RefCell<Scope>, merge_as: Option<&String>)
     {
 		match merge_as
 		{
-			Some(merge_as)	=> self.scope.borrow_mut()
+			Some(merge_as)	=> self.scope().borrow_mut()
 				.merge(
-					&mut *other.scope.borrow_mut(),
+					&mut *scope.borrow_mut(),
 					merge_as,
-					self.content.borrow().len()+1),
+					self.content().borrow().len()+1),
 			_ => {},
 		}
 
         // Content
-        self.content.borrow_mut().extend((other.content.borrow_mut())
+        self.content().borrow_mut().extend((content.borrow_mut())
             .drain(..)
             .map(|value| value));
     }
 }
 
+pub trait DocumentAccessors<'a>
+{
+	fn last_element<T: Element>(&self) -> Option<Ref<'_, T>>;
+	fn last_element_mut<T: Element>(&self) -> Option<RefMut<'_, T>>;
+}
 
+impl<'a> DocumentAccessors<'a> for dyn Document<'a> + '_
+{
+	fn last_element<T: Element>(&self) -> Option<Ref<'_, T>>
+	{
+		Ref::filter_map(self.content().borrow(),
+		|content| content.last()
+			.and_then(|last| last.downcast_ref::<T>())).ok()
+	}
+
+	fn last_element_mut<T: Element>(&self) -> Option<RefMut<'_, T>>
+	{
+		RefMut::filter_map(self.content().borrow_mut(),
+		|content| content.last_mut()
+			.and_then(|last| last.downcast_mut::<T>())).ok()
+	}
+}
diff --git a/src/document/element.rs b/src/document/element.rs
index e7e9abd..c12cf98 100644
--- a/src/document/element.rs
+++ b/src/document/element.rs
@@ -48,7 +48,7 @@ pub trait Element: Downcast
     fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { None }
 
     /// Compiles element
-    fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String>;
+    fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String>;
 }
 impl_downcast!(Element);
 
diff --git a/src/document/langdocument.rs b/src/document/langdocument.rs
new file mode 100644
index 0000000..60b7e14
--- /dev/null
+++ b/src/document/langdocument.rs
@@ -0,0 +1,38 @@
+use std::{cell::RefCell, rc::Rc};
+
+use crate::parser::source::Source;
+
+use super::{document::{Document, Scope}, element::Element};
+
+#[derive(Debug)]
+pub struct LangDocument<'a> {
+	source: Rc<dyn Source>,
+	parent: Option<&'a dyn Document<'a>>, /// Document's parent
+
+	// FIXME: Render these fields private
+	pub content: RefCell<Vec<Box<dyn Element>>>,
+	pub scope: RefCell<Scope>,
+}
+
+impl<'a> LangDocument<'a>
+{
+	pub fn new(source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Self
+	{
+		Self {
+			source: source,
+			parent: parent,
+			content: RefCell::new(Vec::new()),
+			scope: RefCell::new(Scope::new()),
+		}
+	}
+}
+
+impl<'a> Document<'a> for LangDocument<'a> {
+    fn source(&self) -> Rc<dyn Source> { self.source.clone() }
+
+    fn parent(&self) -> Option<&'a dyn Document<'a>> { self.parent.and_then(|p| Some(p as &dyn Document<'a>)) }
+
+    fn content(&self) -> &RefCell<Vec<Box<dyn Element>>> { &self.content }
+
+    fn scope(&self) -> &RefCell<Scope> { &self.scope }
+}
diff --git a/src/document/mod.rs b/src/document/mod.rs
index 387c3c9..d80a6b3 100644
--- a/src/document/mod.rs
+++ b/src/document/mod.rs
@@ -1,3 +1,4 @@
 pub mod document;
+pub mod langdocument;
 pub mod element;
 pub mod variable;
diff --git a/src/document/variable.rs b/src/document/variable.rs
index 5ce1af4..bae520f 100644
--- a/src/document/variable.rs
+++ b/src/document/variable.rs
@@ -1,6 +1,6 @@
 use std::{path::PathBuf, rc::Rc};
 use crate::{elements::text::Text, parser::{parser::Parser, source::{Source, Token, VirtualSource}}};
-use super::{document::Document};
+use super::document::Document;
 
 
 // TODO enforce to_string(from_string(to_string())) == to_string()
@@ -15,7 +15,7 @@ pub trait Variable
 	/// Converts variable to a string
 	fn to_string(&self) -> String;
 
-    fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a Document);
+    fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a dyn Document<'a>);
 }
 
 impl core::fmt::Debug for dyn Variable
@@ -52,7 +52,7 @@ impl Variable for BaseVariable
 
     fn to_string(&self) -> String { self.value.clone() }
 
-    fn parse<'a>(&self, _location: Token, parser: &dyn Parser, document: &'a Document) {
+    fn parse<'a>(&self, _location: Token, parser: &dyn Parser, document: &'a dyn Document<'a>) {
 		let source = Rc::new(VirtualSource::new(
 				self.location().clone(),
 			self.name().to_string(),
@@ -90,12 +90,12 @@ impl Variable for PathVariable
 
     fn to_string(&self) -> String { self.path.to_str().unwrap().to_string() }
 
-    fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a Document){
-		// TODO: Avoid copying the location twice...
+    fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a dyn Document) {
+		// TODO: Avoid copying the content...
 		// Maybe create a special VirtualSource where the `content()` method
 		// calls `Variable::to_string()`
 		let source = Rc::new(VirtualSource::new(
-			location.clone(),
+			location,
 			self.name().to_string(),
 			self.to_string()));
 
diff --git a/src/elements/code.rs b/src/elements/code.rs
index e41a6cf..5921a53 100644
--- a/src/elements/code.rs
+++ b/src/elements/code.rs
@@ -174,7 +174,7 @@ impl Element for Code {
 
     fn to_string(&self) -> String { format!("{self:#?}") }
 
-    fn compile(&self, compiler: &Compiler, _document: &Document)
+    fn compile(&self, compiler: &Compiler, _document: &dyn Document)
 		-> Result<String, String> {
 
 		match compiler.target()
@@ -226,7 +226,7 @@ impl CodeRule {
 		Self {
 			re: [
 				Regex::new(r"(?:^|\n)```(?:\[((?:\\.|[^\\\\])*?)\])?(.*?)(?:,(.*))?\n((?:\\(?:.|\n)|[^\\\\])*?)```").unwrap(),
-				Regex::new(r"``(?:\[((?:\\.|[^\[\]\\])*?)\])?(?:(.*)(?:\n|,))?((?:\\(?:.|\n)|[^\\\\])*?)``").unwrap(),
+				Regex::new(r"``(?:\[((?:\\.|[^\[\]\\])*?)\])?(?:(.*?)(?:\n|,))?((?:\\(?:.|\n)|[^\\\\])*?)``").unwrap(),
 			],
 			properties: PropertyParser::new(props)
 		}
@@ -239,7 +239,7 @@ impl RegexRule for CodeRule
 
     fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-    fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
+    fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
 		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut reports = vec![];
 
@@ -328,7 +328,7 @@ impl RegexRule for CodeRule
 		}
 
 		let theme = document.get_variable("code.theme")
-			.and_then(|(_doc, var)| Some(var.to_string()));
+			.and_then(|var| Some(var.to_string()));
 
 		if index == 0 // Block
 		{
diff --git a/src/elements/comment.rs b/src/elements/comment.rs
index 021f412..a75e21d 100644
--- a/src/elements/comment.rs
+++ b/src/elements/comment.rs
@@ -1,8 +1,8 @@
 use mlua::{Function, Lua};
 use regex::{Captures, Regex};
-use crate::parser::{parser::Parser, rule::RegexRule, source::{Source, Token}};
+use crate::{document::document::Document, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
 use ariadne::{Report, Label, ReportKind};
-use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}};
+use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element}};
 use std::{ops::Range, rc::Rc};
 
 #[derive(Debug)]
@@ -24,7 +24,7 @@ impl Element for Comment
     fn kind(&self) -> ElemKind { ElemKind::Invisible }
     fn element_name(&self) -> &'static str { "Comment" }
     fn to_string(&self) -> String { format!("{self:#?}") }
-    fn compile(&self, _compiler: &Compiler, _document: &Document)
+    fn compile(&self, _compiler: &Compiler, _document: &dyn Document)
 		-> Result<String, String> {
 		Ok("".to_string())
     }
@@ -45,7 +45,7 @@ impl RegexRule for CommentRule {
 
 	fn regexes(&self) -> &[Regex] { &self.re }
 
-	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
+    fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
 		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut reports = vec![];
 
@@ -73,7 +73,7 @@ impl RegexRule for CommentRule {
         parser.push(document, Box::new(
             Comment::new(
 				token.clone(),
-                content
+	            content
             )
         ));
 
diff --git a/src/elements/import.rs b/src/elements/import.rs
index 393e689..1fc089d 100644
--- a/src/elements/import.rs
+++ b/src/elements/import.rs
@@ -1,8 +1,7 @@
 use mlua::{Function, Lua};
-use regex::Regex;
-use crate::parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, SourceFile, Token}};
+use regex::{Captures, Regex};
+use crate::{document::document::{DocumentAccessors, Document}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, SourceFile, Token}}};
 use ariadne::{Report, Fmt, Label, ReportKind};
-use crate::document::document::Document;
 use std::{ops::Range, rc::Rc};
 
 use super::paragraph::Paragraph;
@@ -35,8 +34,8 @@ impl RegexRule for ImportRule {
 
 	fn regexes(&self) -> &[Regex] { &self.re }
 
-	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
-	{
+    fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: Captures)
+		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut result = vec![];
 
         // Path
@@ -138,13 +137,11 @@ impl RegexRule for ImportRule {
 			}
 		};
 
-		// TODO
-        let import_doc = parser.parse(import, Some(&document));
-
-        document.merge(import_doc, Some(&import_as));
+		let import_doc = parser.parse(import, Some(document));
+		document.merge(import_doc.content(), import_doc.scope(), Some(&import_as));
 
 		// Close paragraph
-		if document.last_element::<Paragraph>(false).is_some()
+		if document.last_element::<Paragraph>().is_some()
 		{
 			parser.push(document, Box::new(Paragraph::new(
 				Token::new(token.end()..token.end(), token.source())
diff --git a/src/elements/link.rs b/src/elements/link.rs
index 8a5bf0a..24b1188 100644
--- a/src/elements/link.rs
+++ b/src/elements/link.rs
@@ -1,5 +1,5 @@
 use mlua::{Function, Lua};
-use regex::Regex;
+use regex::{Captures, Regex};
 use serde::{Deserialize, Serialize};
 use crate::parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util};
 use ariadne::{Report, Fmt, Label, ReportKind};
@@ -26,7 +26,7 @@ impl Element for Link
     fn kind(&self) -> ElemKind { ElemKind::Inline }
     fn element_name(&self) -> &'static str { "Link" }
     fn to_string(&self) -> String { format!("{self:#?}") }
-    fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
         match compiler.target()
         {
             Target::HTML => {
@@ -51,7 +51,7 @@ pub struct LinkRule {
 
 impl LinkRule {
 	pub fn new() -> Self {
-		Self { re: [Regex::new(r"(?:^|\n)```(.*?)(?:,(.*))?\n((?:\\.|[^\[\]\\])*?)```").unwrap()] }
+		Self { re: [Regex::new(r"\[((?:\\.|[^\\\\])*?)\]\(((?:\\.|[^\\\\])*?)\)").unwrap()] }
 	}
 }
 
@@ -60,8 +60,8 @@ impl RegexRule for LinkRule {
 
 	fn regexes(&self) -> &[Regex] { &self.re }
 
-	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
-	{
+    fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
+		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut result = vec![];
         let link_name = match matches.get(1)
         {
diff --git a/src/elements/list.rs b/src/elements/list.rs
index dd05ef8..a73b7ae 100644
--- a/src/elements/list.rs
+++ b/src/elements/list.rs
@@ -1,6 +1,6 @@
 use std::{any::Any, cell::Ref, ops::Range, rc::Rc};
 
-use crate::{compiler::compiler::{Compiler, Target}, document::{document::Document, element::{ElemKind, Element}}, parser::{parser::Parser, rule::Rule, source::{Cursor, Source, Token, VirtualSource}}};
+use crate::{compiler::compiler::{Compiler, Target}, document::{document::{Document, DocumentAccessors}, element::{ElemKind, Element}}, parser::{parser::Parser, rule::Rule, source::{Cursor, Source, Token, VirtualSource}}};
 use ariadne::{Label, Report, ReportKind};
 use mlua::{Function, Lua};
 use regex::Regex;
@@ -57,7 +57,7 @@ impl Element for List
 
     fn to_string(&self) -> String { format!("{self:#?}") }
 
-    fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String> {
 		match compiler.target()
 		{
 			Target::HTML => {
@@ -196,10 +196,11 @@ impl ListRule {
 
 	}
 
-	fn parse_depth(depth: &str, document: &Document) -> Vec<(bool, usize)>
+	fn parse_depth(depth: &str, document: &dyn Document) -> Vec<(bool, usize)>
 	{
 		let mut parsed = vec![];
-		let prev_entry = document.last_element::<List>(true)
+		// FIXME: Previous iteration used to recursively retrieve the list indent
+		let prev_entry = document.last_element::<List>()
 			.and_then(|list| Ref::filter_map(list, |m| m.entries.last() ).ok() )
 			.and_then(|entry| Ref::filter_map(entry, |e| Some(&e.numbering)).ok() );
 
@@ -246,7 +247,8 @@ impl Rule for ListRule
 			|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
 	}
 
-	fn on_match<'a>(&self, parser: &dyn Parser, document: &'a Document<'a>, cursor: Cursor, _match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
+	fn on_match<'a>(&self, parser: &dyn Parser, document: &'a dyn Document<'a>, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
+		-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
 		let mut reports = vec![];
 		let content = cursor.source.content();
 		let (end_cursor, numbering, source) = match self.start_re.captures_at(content, cursor.pos) {
@@ -310,8 +312,8 @@ impl Rule for ListRule
 			},
 		};
 
-        let parsed_entry = parser.parse(Rc::new(source), Some(&document));
-		let mut parsed_paragraph = parsed_entry.last_element_mut::<Paragraph>(false).unwrap(); // Extract content from paragraph
+        let parsed_entry = parser.parse(Rc::new(source), Some(document));
+		let mut parsed_paragraph = parsed_entry.last_element_mut::<Paragraph>().unwrap(); // Extract content from paragraph
 		let entry = ListEntry::new(
 			Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()),
 			numbering,
@@ -319,14 +321,14 @@ impl Rule for ListRule
 		);
 
 		// Ger previous list, if none insert a new list
-		let mut list = match document.last_element_mut::<List>(false)
+		let mut list = match document.last_element_mut::<List>()
 		{
 			Some(last) => last,
 			None => {
 				parser.push(document,
 					Box::new(List::new(
 							Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()))));
-				document.last_element_mut::<List>(false).unwrap()
+				document.last_element_mut::<List>().unwrap()
 			}
 		};
 		list.push(entry);
diff --git a/src/elements/paragraph.rs b/src/elements/paragraph.rs
index c170160..65861ce 100644
--- a/src/elements/paragraph.rs
+++ b/src/elements/paragraph.rs
@@ -54,7 +54,7 @@ impl Element for Paragraph
 
     fn to_string(&self) -> String { format!("{:#?}", self)  }
 
-    fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String> {
 		if self.content.is_empty() { return Ok(String::new()) }
 
         match compiler.target()
@@ -109,7 +109,7 @@ impl Rule for ParagraphRule
 			.and_then(|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
     }
 
-    fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
+    fn on_match(&self, parser: &dyn Parser, document: &dyn Document, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
 		-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
 
 		let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos)
diff --git a/src/elements/raw.rs b/src/elements/raw.rs
index c24df80..3f51085 100644
--- a/src/elements/raw.rs
+++ b/src/elements/raw.rs
@@ -1,15 +1,14 @@
-use mlua::{Function, Lua};
+use mlua::{Error::BadArgument, Function, Lua};
 use regex::{Captures, Regex};
-use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util::{self, Property, PropertyParser}}};
+use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util::{self, Property, PropertyParser}}};
 use ariadne::{Fmt, Label, Report, ReportKind};
-use crate::document::document::Document;
-use std::{collections::HashMap, ops::Range, rc::Rc, str::FromStr};
+use std::{collections::HashMap, ops::Range, rc::Rc, str::FromStr, sync::Arc};
 
 #[derive(Debug)]
 struct Raw {
-	location: Token,
-	kind: ElemKind,
-	content: String,
+	pub(self) location: Token,
+	pub(self) kind: ElemKind,
+	pub(self) content: String,
 }
 
 impl Raw {
@@ -26,7 +25,7 @@ impl Element for Raw {
 
     fn to_string(&self) -> String { format!("{self:#?}") }
 
-    fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
 		Ok(self.content.clone())
     }
 }
@@ -59,7 +58,7 @@ impl RegexRule for RawRule
 
     fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-    fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
+    fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: Captures)
 		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut reports = vec![];
 
@@ -154,15 +153,43 @@ impl RegexRule for RawRule
 			}
 		};
 
-		parser.push(document, Box::new(Raw::new(
-			token.clone(),
-			raw_kind,
-			raw_content
-		)));
+		parser.push(document, Box::new(Raw {
+			location: token.clone(),
+			kind: raw_kind,
+			content: raw_content
+		}));
 
         reports
     }
 
-	// TODO
-	fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
+    fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
+		let mut bindings = vec![];
+
+		bindings.push(("push".to_string(), lua.create_function(
+			|_, (kind, content): (String, String)| {
+			// Validate kind
+			let kind = match ElemKind::from_str(kind.as_str())
+			{
+				Ok(kind) => kind,
+				Err(e) => return Err(BadArgument {
+						to: Some("push".to_string()),
+						pos: 1,
+						name: Some("kind".to_string()),
+						cause: Arc::new(mlua::Error::external(
+									format!("Wrong section kind specified: {e}")))})
+			};
+
+			CTX.with_borrow(|ctx| ctx.as_ref().map(|ctx| {
+				ctx.parser.push(ctx.document, Box::new(Raw {
+					location: ctx.location.clone(),
+					kind,
+					content,
+				}));
+			}));
+
+			Ok(())
+		}).unwrap()));
+		
+		bindings
+    }
 }
diff --git a/src/elements/script.rs b/src/elements/script.rs
index 93bd96d..fa083ff 100644
--- a/src/elements/script.rs
+++ b/src/elements/script.rs
@@ -1,8 +1,7 @@
 use mlua::{Function, Lua};
 use regex::{Captures, Regex};
-use crate::{lua::kernel::{Kernel, KernelContext, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token, VirtualSource}, util}};
+use crate::{document::document::Document, lua::kernel::{Kernel, KernelContext, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token, VirtualSource}, util}};
 use ariadne::{Fmt, Label, Report, ReportKind};
-use crate::document::document::Document;
 use std::{ops::Range, rc::Rc};
 
 use super::text::Text;
@@ -18,7 +17,7 @@ impl ScriptRule {
 		Self {
             re: [
 				Regex::new(r"(?:^|\n)@<(?:(.*)\n?)((?:\\.|[^\\\\])*?)(?:\n?)>@").unwrap(),
-				Regex::new(r"%<([^\s[:alpha:]])?(?:\[(.*?)\])?((?:\\.|[^\\\\])*?)(?:\n?)>%").unwrap()
+				Regex::new(r"%<(?:\[(.*?)\])?([^\s[:alpha:]])?((?:\\.|[^\\\\])*?)(?:\n?)>%").unwrap()
 			],
 			eval_kinds: [
 				("", "Eval"),
@@ -60,11 +59,11 @@ impl RegexRule for ScriptRule
 
     fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-    fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
+    fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: Captures)
 		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut reports = vec![];
 
-		let kernel_name = match matches.get(if index == 0 {1} else {2}) {
+		let kernel_name = match matches.get(1) {
 			None => "main".to_string(),
 			Some(name) => {
 				match ScriptRule::validate_kernel_name(parser.colors(), name.as_str())
@@ -84,13 +83,7 @@ impl RegexRule for ScriptRule
 				}
 			}
 		};
-		let kernel_name = matches.get(if index == 0 {1} else {2})
-			.and_then(|name| {
-				let trimmed = name.as_str().trim_start().trim_end();
-				(!trimmed.is_empty()).then_some(trimmed)
-			})
-			.unwrap_or("main");
-		let kernel = parser.get_kernel(kernel_name).unwrap_or_else(|| {
+		let kernel = parser.get_kernel(kernel_name.as_str()).unwrap_or_else(|| {
 			parser.insert_kernel(kernel_name.to_string(), Kernel::new(parser))
 		});
 
@@ -143,7 +136,7 @@ impl RegexRule for ScriptRule
 			else // Eval
 			{
 				// Validate kind
-				let kind = match matches.get(1) {
+				let kind = match matches.get(2) {
 					None => 0,
 					Some(kind) => {
 						match self.validate_kind(parser.colors(), kind.as_str())
diff --git a/src/elements/section.rs b/src/elements/section.rs
index 4ea478d..9af30a6 100644
--- a/src/elements/section.rs
+++ b/src/elements/section.rs
@@ -1,8 +1,8 @@
 use mlua::{Error::BadArgument, Function, Lua};
 use regex::Regex;
-use crate::{compiler::compiler::Target, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
+use crate::{compiler::compiler::Target, document::document::Document, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
 use ariadne::{Report, Fmt, Label, ReportKind};
-use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element, ReferenceableElement}}};
+use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element, ReferenceableElement}};
 use std::{ops::Range, rc::Rc, sync::Arc};
 
 #[derive(Debug)]
@@ -21,7 +21,7 @@ impl Element for Section
     fn element_name(&self) -> &'static str { "Section" }
     fn to_string(&self) -> String { format!("{self:#?}") }
     fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
-    fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
         match compiler.target()
         {
             Target::HTML => {
@@ -61,7 +61,7 @@ impl RegexRule for SectionRule {
 
 	fn regexes(&self) -> &[Regex] { &self.re }
 
-	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
+	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
 	{
 		let mut result = vec![];
 		let section_depth = match matches.get(1)
@@ -89,6 +89,7 @@ impl RegexRule for SectionRule {
 		// [Optional] Reference name
 		let section_refname = matches.get(2).map_or_else(|| None,
 			|refname| {
+				/* TODO: Wait for reference rework
 				// Check for duplicate reference
 				if let Some((ref_doc, reference)) = document.get_reference(refname.as_str())
 				{
@@ -112,6 +113,7 @@ impl RegexRule for SectionRule {
 						.with_note(format!("Previous reference was overwritten"))
 						.finish());
 				}
+				*/
 			Some(refname.as_str().to_string())
 		});
 
diff --git a/src/elements/style.rs b/src/elements/style.rs
index 6af05a1..a3248b1 100644
--- a/src/elements/style.rs
+++ b/src/elements/style.rs
@@ -1,8 +1,7 @@
 use mlua::{Function, Lua};
 use regex::{Captures, Regex};
-use crate::{compiler::compiler::{Compiler, Target}, document::element::{ElemKind, Element}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, state::State}};
+use crate::{compiler::compiler::{Compiler, Target}, document::{document::{DocumentAccessors, Document}, element::{ElemKind, Element}}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, state::State}};
 use ariadne::{Fmt, Label, Report, ReportKind};
-use crate::document::document::Document;
 use crate::parser::state::Scope;
 use std::{cell::RefCell, ops::Range, rc::Rc};
 use lazy_static::lazy_static;
@@ -29,7 +28,7 @@ impl Element for Style
 	fn kind(&self) -> ElemKind { ElemKind::Inline }
 	fn element_name(&self) -> &'static str { "Section" }
 	fn to_string(&self) -> String { format!("{self:#?}") }
-	fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
+	fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
 		match compiler.target()
 		{
 			Target::HTML => {
@@ -66,7 +65,7 @@ impl State for StyleState
 {
 	fn scope(&self) -> Scope { Scope::PARAGRAPH }
 
-	fn on_remove<'a>(&self, parser: &dyn Parser, document: &Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+	fn on_remove<'a>(&self, parser: &dyn Parser, document: &dyn Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
 		let mut result = Vec::new();
 		self.toggled
 			.iter()
@@ -80,7 +79,7 @@ impl State for StyleState
 
 			//let active_range = range.start .. paragraph.location().end()-1;
 
-			let paragraph = document.last_element::<Paragraph>(false).unwrap();
+			let paragraph = document.last_element::<Paragraph>().unwrap();
 			let paragraph_end = paragraph.content.last()
 				.and_then(|last| Some((last.location().source(), last.location().end()-1 .. last.location().end())))
 				.unwrap();
@@ -145,7 +144,7 @@ impl RegexRule for StyleRule
 
 	fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-	fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, _matches: Captures) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
+	fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, _matches: Captures) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
 		let result = vec![];
 
 		let query = parser.state().query(&STATE_NAME);
diff --git a/src/elements/tex.rs b/src/elements/tex.rs
index 9900233..5be07ad 100644
--- a/src/elements/tex.rs
+++ b/src/elements/tex.rs
@@ -123,7 +123,7 @@ impl Element for Tex {
 
     fn to_string(&self) -> String { format!("{self:#?}") }
 
-    fn compile(&self, compiler: &Compiler, document: &Document)
+    fn compile(&self, compiler: &Compiler, document: &dyn Document)
 		-> Result<String, String> {
 
 		match compiler.target() {
@@ -136,18 +136,18 @@ impl Element for Tex {
 					}
 				});
 
-				let exec = document.get_variable(format!("tex.{}.exec", self.env))
-					.map_or("latex2svg".to_string(), |(_, var)| var.to_string());
+				let exec = document.get_variable(format!("tex.{}.exec", self.env).as_str())
+					.map_or("latex2svg".to_string(), |var| var.to_string());
 				// FIXME: Because fontsize is passed as an arg, verify that it cannot be used to execute python/shell code
-				let fontsize = document.get_variable(format!("tex.{}.fontsize", self.env))
-					.map_or("12".to_string(), |(_, var)| var.to_string());
-				let preamble = document.get_variable(format!("tex.{}.preamble", self.env))
-					.map_or("".to_string(), |(_, var)| var.to_string());
+				let fontsize = document.get_variable(format!("tex.{}.fontsize", self.env).as_str())
+					.map_or("12".to_string(), |var| var.to_string());
+				let preamble = document.get_variable(format!("tex.{}.preamble", self.env).as_str())
+					.map_or("".to_string(), |var| var.to_string());
 				let prepend = if self.block == TexKind::Inline { "".to_string() }
 				else
 				{
-					document.get_variable(format!("tex.{}.block_prepend", self.env))
-						.map_or("".to_string(), |(_, var)| var.to_string()+"\n")
+					document.get_variable(format!("tex.{}.block_prepend", self.env).as_str())
+						.map_or("".to_string(), |var| var.to_string()+"\n")
 				};
 
 				let latex = match self.block
@@ -205,7 +205,7 @@ impl RegexRule for TexRule
 
     fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-    fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
+    fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: Captures)
 		-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut reports = vec![];
 
diff --git a/src/elements/text.rs b/src/elements/text.rs
index 1eed8a5..ea765d5 100644
--- a/src/elements/text.rs
+++ b/src/elements/text.rs
@@ -1,6 +1,6 @@
 use mlua::{Function, Lua};
 
-use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{rule::Rule, source::Token}};
+use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{parser::Parser, rule::Rule, source::Token}};
 
 #[derive(Debug)]
 pub struct Text
@@ -27,7 +27,7 @@ impl Element for Text
 	fn element_name(&self) -> &'static str { "Text" }
     fn to_string(&self) -> String { format!("{self:#?}") }
 
-    fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
+    fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
         Ok(compiler.sanitize(self.content.as_str()))
     }
 }
@@ -41,11 +41,10 @@ impl Rule for TextRule
 
     fn next_match(&self, cursor: &crate::parser::source::Cursor) -> Option<(usize, Box<dyn std::any::Any>)> { None }
 
-    fn on_match(&self, parser: &dyn crate::parser::parser::Parser, document: &crate::document::document::Document, cursor: crate::parser::source::Cursor, match_data: Option<Box<dyn std::any::Any>>) -> (crate::parser::source::Cursor, Vec<ariadne::Report<'_, (std::rc::Rc<dyn crate::parser::source::Source>, std::ops::Range<usize>)>>) { panic!("Text canno match"); }
+    fn on_match(&self, parser: &dyn Parser, document: &dyn Document, cursor: crate::parser::source::Cursor, match_data: Option<Box<dyn std::any::Any>>) -> (crate::parser::source::Cursor, Vec<ariadne::Report<'_, (std::rc::Rc<dyn crate::parser::source::Source>, std::ops::Range<usize>)>>) { panic!("Text canno match"); }
 
     fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
 		let mut bindings = vec![];
-
 		bindings.push(("push".to_string(), lua.create_function(
 			|_, content: String| {
 			CTX.with_borrow(|ctx| ctx.as_ref().map(|ctx| {
diff --git a/src/elements/variable.rs b/src/elements/variable.rs
index 0a63daa..60fba59 100644
--- a/src/elements/variable.rs
+++ b/src/elements/variable.rs
@@ -1,8 +1,8 @@
 use mlua::{Function, Lua};
 use regex::Regex;
-use crate::parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token}};
+use crate::{document::document::Document, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token}}};
 use ariadne::{Report, Fmt, Label, ReportKind};
-use crate::document::{document::Document, variable::{BaseVariable, PathVariable, Variable}};
+use crate::document::variable::{BaseVariable, PathVariable, Variable};
 use std::{ops::Range, rc::Rc};
 
 pub struct VariableRule {
@@ -91,7 +91,7 @@ impl RegexRule for VariableRule {
 
 
 
-	fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
+	fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
 	{
 		let mut result = vec![];
         // [Optional] variable kind
@@ -223,7 +223,7 @@ impl RegexRule for VariableSubstitutionRule
 
     fn regexes(&self) -> &[regex::Regex] { &self.re }
 
-    fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
+    fn on_regex_match<'a>(&self, _index: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
 		let mut result = vec![];
 
         let variable = match matches.get(1)
@@ -307,27 +307,13 @@ impl RegexRule for VariableSubstitutionRule
                             .finish());
                         return result;
                     }
-                    Some((_, var)) => var,
+                    Some(var) => var,
                 }
             },
             _ => panic!("Unknown error")
         };
 
 		variable.parse(token, parser, document);
-		//let parsed = variable.parse(
-		//	token,
-		//	parser,
-		//	document
-		//);
-		////document.merge(parsed, None);
-		//parsed.content.borrow_mut()
-		//	.drain(..)
-		//	.for_each(|elem| parser.push(document, elem));
-		//parser.push(document, )
-
-		// TODO: Full rework of document
-		// parser shound parse into previous document, and not into a new document
-		// This should prevent having to sue `recurse: bool` in the last_element getters
 
         return result;
     }
diff --git a/src/lsp/semantic.rs b/src/lsp/semantic.rs
index 49418ea..cebcf68 100644
--- a/src/lsp/semantic.rs
+++ b/src/lsp/semantic.rs
@@ -71,20 +71,36 @@ pub fn semantic_token_from_document(document: &Document) -> Vec<SemanticToken>
 		source: source.clone()
 	};
 
-	document.content.borrow()
-		.iter()
-		.for_each(|elem| {
-			if let Some(paragraph) = elem.downcast_ref::<Paragraph>()
-			{
-				paragraph.content
-					.iter()
-					.for_each(|elem| provide(&mut semantic_tokens, &mut cursor, elem));
-			}
-			else
-			{
-				provide(&mut semantic_tokens, &mut cursor, elem);
-			}
-		});
+	semantic_tokens.push(SemanticToken {
+		delta_line: 1,
+		delta_start: 1,
+		length: 5,
+		token_type: 0,
+		token_modifiers_bitset: 0,
+	});
+
+	semantic_tokens.push(SemanticToken {
+		delta_line: 1,
+		delta_start: 1,
+		length: 5,
+		token_type: 1,
+		token_modifiers_bitset: 0,
+	});
+
+	//document.content.borrow()
+	//	.iter()
+	//	.for_each(|elem| {
+	//		if let Some(paragraph) = elem.downcast_ref::<Paragraph>()
+	//		{
+	//			paragraph.content
+	//				.iter()
+	//				.for_each(|elem| provide(&mut semantic_tokens, &mut cursor, elem));
+	//		}
+	//		else
+	//		{
+	//			provide(&mut semantic_tokens, &mut cursor, elem);
+	//		}
+	//	});
 
 	semantic_tokens
 }
diff --git a/src/lua/kernel.rs b/src/lua/kernel.rs
index 7ac6b7b..8e0bb81 100644
--- a/src/lua/kernel.rs
+++ b/src/lua/kernel.rs
@@ -1,19 +1,19 @@
-use std::{cell::{RefCell, RefMut}, rc::Rc};
+use std::cell::{RefCell, RefMut};
 
-use mlua::{Error, FromLua, Lua, UserData, UserDataMethods};
+use mlua::Lua;
 
 use crate::{document::document::Document, parser::{parser::Parser, source::Token}};
 
-pub struct KernelContext<'a>
+pub struct KernelContext<'a, 'b>
 {
 	pub location: Token,
 	pub parser: &'a dyn Parser,
-	pub document: &'a Document<'a>,
+	pub document: &'b dyn Document<'b>,
 	//pub parser: &'a dyn Parser,
 }
 
 thread_local! {
-    pub static CTX: RefCell<Option<KernelContext<'static>>> = RefCell::new(None);
+    pub static CTX: RefCell<Option<KernelContext<'static, 'static>>> = RefCell::new(None);
 }
 
 #[derive(Debug)]
@@ -23,7 +23,6 @@ pub struct Kernel
 }
 
 impl Kernel {
-
 	// TODO: Take parser as arg and 
 	// iterate over the rules
 	// to find export the bindings (if some)
diff --git a/src/main.rs b/src/main.rs
index 089dcf3..5600898 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -75,26 +75,27 @@ fn main() {
 	if debug_opts.contains(&"ast".to_string())
 	{
 		println!("-- BEGIN AST DEBUGGING --");
-		doc.content.borrow().iter().for_each(|elem| {
+		doc.content().borrow().iter().for_each(|elem| {
 			println!("{}", (elem).to_string())
 		});
 		println!("-- END AST DEBUGGING --");
 	}
 
 
-	if debug_opts.contains(&"ref".to_string())
-	{
-		println!("-- BEGIN REFERENCES DEBUGGING --");
-		let sc = doc.scope.borrow();
-		sc.referenceable.iter().for_each(|(name, pos)| {
-			println!(" - {name}: `{:#?}`", doc.content.borrow()[*pos]);
-		});
-		println!("-- END REFERENCES DEBUGGING --");
-	}
+	// TODO
+	//if debug_opts.contains(&"ref".to_string())
+	//{
+	//	println!("-- BEGIN REFERENCES DEBUGGING --");
+	//	let sc = doc.scope.borrow();
+	//	sc.referenceable.iter().for_each(|(name, pos)| {
+	//		println!(" - {name}: `{:#?}`", doc.content.borrow()[*pos]);
+	//	});
+	//	println!("-- END REFERENCES DEBUGGING --");
+	//}
 	if debug_opts.contains(&"var".to_string())
 	{
 		println!("-- BEGIN VARIABLES DEBUGGING --");
-		let sc = doc.scope.borrow();
+		let sc = doc.scope().borrow();
 		sc.variables.iter().for_each(|(_name, var)| {
 			println!(" - `{:#?}`", var);
 		});
@@ -103,7 +104,7 @@ fn main() {
 
 
 	let compiler = Compiler::new(compiler::compiler::Target::HTML, db_path);
-	let out = compiler.compile(&doc);
+	let out = compiler.compile(doc.as_ref());
 
 	std::fs::write("a.html", out).unwrap();
 }
diff --git a/src/parser/langparser.rs b/src/parser/langparser.rs
index 2789a39..80f000f 100644
--- a/src/parser/langparser.rs
+++ b/src/parser/langparser.rs
@@ -1,8 +1,8 @@
-use std::{cell::{RefCell, RefMut}, collections::{HashMap, HashSet}, ops::Range, rc::Rc};
+use std::{cell::{Ref, RefCell, RefMut}, collections::{HashMap, HashSet}, ops::Range, rc::Rc};
 
 use ariadne::{Label, Report};
 
-use crate::{document::{document::Document, element::{ElemKind, Element}}, elements::{paragraph::Paragraph, registrar::register, text::Text}, lua::kernel::{Kernel, KernelHolder}, parser::source::{SourceFile, VirtualSource}};
+use crate::{document::{document::{DocumentAccessors, Document}, element::{ElemKind, Element}, langdocument::LangDocument}, elements::{paragraph::Paragraph, registrar::register, text::Text}, lua::kernel::{Kernel, KernelHolder}, parser::source::{SourceFile, VirtualSource}};
 
 use super::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source, Token}, state::StateHolder, util};
 
@@ -132,14 +132,14 @@ impl Parser for LangParser
 	fn state_mut(&self) -> std::cell::RefMut<'_, StateHolder> { self.state.borrow_mut() }
 
 	/// Add an [`Element`] to the [`Document`]
-	fn push<'a>(&self, doc: &'a Document<'a>, elem: Box<dyn Element>)
+	fn push<'a>(&self, doc: &dyn Document, elem: Box<dyn Element>)
 	{
 		if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible
 		{
-			let mut paragraph = doc.last_element_mut::<Paragraph>(false)
+			let mut paragraph = doc.last_element_mut::<Paragraph>()
 				.or_else(|| {
 					doc.push(Box::new(Paragraph::new(elem.location().clone())));
-					doc.last_element_mut::<Paragraph>(false)
+					doc.last_element_mut::<Paragraph>()
 				}).unwrap();
 
 			paragraph.push(elem);
@@ -147,20 +147,20 @@ impl Parser for LangParser
 		else
 		{
 			// Process paragraph events
-			if doc.last_element_mut::<Paragraph>(false)
+			if doc.last_element::<Paragraph>()
 				.is_some_and(|_| true)
 			{
 				self.handle_reports(doc.source(),
-				self.state_mut().on_scope_end(self, &doc, super::state::Scope::PARAGRAPH));
+				self.state_mut().on_scope_end(self, doc, super::state::Scope::PARAGRAPH));
 			}
 
 			doc.push(elem);
 		}
 	}
 
-	fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Document<'a>
+	fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Box<dyn Document<'a>+'a>
 	{
-		let doc = Document::new(source.clone(), parent);
+		let doc = LangDocument::new(source.clone(), parent);
 		let mut matches = Vec::new();
 		for _ in 0..self.rules.len() {
 			matches.push((0usize, None));
@@ -169,10 +169,10 @@ impl Parser for LangParser
 		let content = source.content();
 		let mut cursor = Cursor::new(0usize, doc.source()); // Cursor in file
 
-		if parent.is_some() // Terminate parent's paragraph state
+		if let Some(parent) = parent // Terminate parent's paragraph state
 		{
-			self.handle_reports(parent.as_ref().unwrap().source(),
-			self.state_mut().on_scope_end(self, parent.as_ref().unwrap(), super::state::Scope::PARAGRAPH));
+			self.handle_reports(parent.source(),
+			self.state_mut().on_scope_end(self, parent, super::state::Scope::PARAGRAPH));
 		}
 	
 		loop
@@ -193,7 +193,8 @@ impl Parser for LangParser
 			{
 
 				// Rule callback
-				let (new_cursor, reports) = (*rule).on_match(self, &doc, rule_pos, match_data);
+				let dd: &'a dyn Document = unsafe {std::mem::transmute(&doc as &dyn Document)};
+				let (new_cursor, reports) = rule.on_match(self, dd, rule_pos, match_data);
 
 				self.handle_reports(doc.source(), reports);
 
@@ -210,10 +211,10 @@ impl Parser for LangParser
 		self.handle_reports(doc.source(),
 			self.state_mut().on_scope_end(self, &doc, super::state::Scope::DOCUMENT));
 		
-		return doc;
+		return Box::new(doc);
 	}
 
-	fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a Document<'a>)
+	fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a dyn Document<'a>)
 	{
 		let mut matches = Vec::new();
 		for _ in 0..self.rules.len() {
@@ -228,10 +229,10 @@ impl Parser for LangParser
 			let (rule_pos, rule, match_data) = self.update_matches(&cursor, &mut matches);
 
 			// Unmatched content
-			let text_content = util::process_text(&document, &content.as_str()[cursor.pos..rule_pos.pos]);
+			let text_content = util::process_text(document, &content.as_str()[cursor.pos..rule_pos.pos]);
 			if !text_content.is_empty()
 			{
-				self.push(&document, Box::new(Text::new(
+				self.push(document, Box::new(Text::new(
 							Token::new(cursor.pos..rule_pos.pos, source.clone()),
 							text_content
 				)));
@@ -240,7 +241,7 @@ impl Parser for LangParser
 			if let Some(rule) = rule
 			{
 				// Rule callback
-				let (new_cursor, reports) = (*rule).on_match(self, &document, rule_pos, match_data);
+				let (new_cursor, reports) = (*rule).on_match(self, document, rule_pos, match_data);
 
 				self.handle_reports(document.source(), reports);
 
diff --git a/src/parser/parser.rs b/src/parser/parser.rs
index aab0ba3..be104a1 100644
--- a/src/parser/parser.rs
+++ b/src/parser/parser.rs
@@ -115,11 +115,11 @@ pub trait Parser: KernelHolder
 	}
 
 	/// Add an [`Element`] to the [`Document`]
-	fn push<'a>(&self, doc: &'a Document<'a>, elem: Box<dyn Element>);
+	fn push<'a>(&self, doc: &dyn Document, elem: Box<dyn Element>);
 
 	/// Parse [`Source`] into a new [`Document`]
-	fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Document<'a>;
+	fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Box<dyn Document<'a>+'a>;
 
 	/// Parse [`Source`] into an already existing [`Document`]
-	fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a Document<'a>);
+	fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a dyn Document<'a>);
 }
diff --git a/src/parser/rule.rs b/src/parser/rule.rs
index c344800..99c7706 100644
--- a/src/parser/rule.rs
+++ b/src/parser/rule.rs
@@ -14,7 +14,7 @@ pub trait Rule {
 	/// Finds the next match starting from [`cursor`]
 	fn next_match(&self, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
 	/// Callback when rule matches
-	fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
+	fn on_match<'a>(&self, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), cursor: Cursor, match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
 	/// Export bindings to lua
 	fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
 }
@@ -73,7 +73,7 @@ pub trait RegexRule
 	fn regexes(&self) -> &[regex::Regex];
 
 	/// Callback on regex rule match
-	fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
+	fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
 
 	fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
 }
@@ -100,7 +100,7 @@ impl<T: RegexRule> Rule for T {
 			(pos, Box::new(id) as Box<dyn Any>));
 	}
 
-	fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, match_data: Option<Box<dyn Any>>)
+	fn on_match<'a>(&self, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), cursor: Cursor, match_data: Option<Box<dyn Any>>)
 		-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
 		let content = cursor.source.content();
 		let index = unsafe { match_data.unwrap_unchecked().downcast::<usize>().unwrap_unchecked() };
diff --git a/src/parser/state.rs b/src/parser/state.rs
index 2ec01f9..5cc9cee 100644
--- a/src/parser/state.rs
+++ b/src/parser/state.rs
@@ -27,7 +27,7 @@ pub trait State: Downcast
 	fn scope(&self) -> Scope;
 
 	/// Callback called when state goes out of scope
-	fn on_remove<'a>(&self, parser: &dyn Parser, document: &Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
+	fn on_remove<'a>(&self, parser: &dyn Parser, document: &dyn Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
 }
 impl_downcast!(State);
 
@@ -70,7 +70,7 @@ impl StateHolder
 			.map_or(None, |st| Some(st.clone()))
 	}
 
-	pub fn on_scope_end(&mut self, parser: &dyn Parser, document: &Document, scope: Scope) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
+	pub fn on_scope_end(&mut self, parser: &dyn Parser, document: &dyn Document, scope: Scope) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
 	{
 		let mut result = vec![];
 		
diff --git a/src/parser/util.rs b/src/parser/util.rs
index 6e5c09f..219ef37 100644
--- a/src/parser/util.rs
+++ b/src/parser/util.rs
@@ -2,10 +2,10 @@ use std::collections::HashMap;
 
 use unicode_segmentation::UnicodeSegmentation;
 
-use crate::{document::{document::Document, element::ElemKind}, elements::paragraph::Paragraph};
+use crate::{document::{document::{Document, DocumentAccessors}, element::ElemKind}, elements::paragraph::Paragraph};
 
 /// Processes text for escape characters and paragraphing
-pub fn process_text(document: &Document, content: &str) -> String
+pub fn process_text(document: &dyn Document, content: &str) -> String
 {
 	let mut escaped = false;
 	let mut newlines = 0usize; // Consecutive newlines
@@ -30,7 +30,7 @@ pub fn process_text(document: &Document, content: &str) -> String
 					}
 				}
 				None => {
-					if document.last_element::<Paragraph>(false)
+					if document.last_element::<Paragraph>()
 						.and_then(|par| par.find_back(|e| e.kind() != ElemKind::Invisible)
 						.and_then(|e| Some(e.kind() == ElemKind::Inline)))
 							.unwrap_or(false)
@@ -65,7 +65,7 @@ pub fn process_text(document: &Document, content: &str) -> String
 			// Content begins with whitespace
 			if prev.is_none()
 			{
-				if document.last_element::<Paragraph>(false).is_some()
+				if document.last_element::<Paragraph>().is_some()
 				{
 					return (out+g, Some(g));
 				}