diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs
index 7714571..de7c04f 100644
--- a/src/compiler/compiler.rs
+++ b/src/compiler/compiler.rs
@@ -1,3 +1,4 @@
+use std::cell::Ref;
 use std::cell::RefCell;
 use std::cell::RefMut;
 use std::collections::HashMap;
@@ -20,6 +21,8 @@ pub struct Compiler {
 	cache: Option<RefCell<Connection>>,
 	reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
 	// TODO: External references, i.e resolved later
+	
+	sections_counter: RefCell<Vec<usize>>,
 }
 
 impl Compiler {
@@ -35,9 +38,34 @@ impl Compiler {
 			target,
 			cache: cache.map(|con| RefCell::new(con)),
 			reference_count: RefCell::new(HashMap::new()),
+			sections_counter: RefCell::new(vec![]),
 		}
 	}
 
+	/// Gets the section counter for a given depth
+	/// This function modifies the section counter
+	pub fn section_counter(&self, depth: usize) -> Ref<'_, Vec<usize>>
+	{
+		// Increment current counter
+		if self.sections_counter.borrow().len() == depth {
+			self.sections_counter.borrow_mut().last_mut()
+				.map(|id| *id += 1);
+			return Ref::map(self.sections_counter.borrow(), |b| &*b);
+		}
+
+		// Close
+		while self.sections_counter.borrow().len() > depth {
+			self.sections_counter.borrow_mut().pop();
+		}
+
+		// Open
+		while self.sections_counter.borrow().len() < depth {
+			self.sections_counter.borrow_mut().push(1);
+		}
+
+		Ref::map(self.sections_counter.borrow(), |b| &*b)
+	}
+
 	/// Sanitizes text for a [`Target`]
 	pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
 		match target {
diff --git a/src/elements/script.rs b/src/elements/script.rs
index 325adc4..9c64c78 100644
--- a/src/elements/script.rs
+++ b/src/elements/script.rs
@@ -282,7 +282,7 @@ impl RegexRule for ScriptRule {
 mod tests {
 	use super::*;
 	use crate::elements::link::Link;
-use crate::elements::list::ListEntry;
+	use crate::elements::list::ListEntry;
 	use crate::elements::list::ListMarker;
 	use crate::elements::paragraph::Paragraph;
 	use crate::elements::style::Style;
diff --git a/src/elements/section.rs b/src/elements/section.rs
index 60e97a9..6d2be6b 100644
--- a/src/elements/section.rs
+++ b/src/elements/section.rs
@@ -17,6 +17,7 @@ use mlua::Error::BadArgument;
 use mlua::Function;
 use mlua::Lua;
 use regex::Regex;
+use section_kind::NO_NUMBER;
 use std::ops::Range;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -38,13 +39,25 @@ impl Element for Section {
 	fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
 		match compiler.target() {
 			Target::HTML => {
+				let mut number = String::new();
+
+				if (self.kind & NO_NUMBER) != NO_NUMBER {
+					let numbering = compiler.section_counter(self.depth);
+					number = numbering
+						.iter()
+						.map(|n| n.to_string())
+						.collect::<Vec<_>>()
+						.join(".");
+					number += " ";
+				}
+
 				Ok(format!(
-				r#"<h{0} id="{1}">{2}</h{0}>"#,
-				self.depth,
-				Compiler::refname(compiler.target(), self.title.as_str()),
-				Compiler::sanitize(compiler.target(), self.title.as_str())
-			))
-			},
+					r#"<h{0} id="{1}">{number}{2}</h{0}>"#,
+					self.depth,
+					Compiler::refname(compiler.target(), self.title.as_str()),
+					Compiler::sanitize(compiler.target(), self.title.as_str())
+				))
+			}
 			Target::LATEX => Err("Unimplemented compiler".to_string()),
 		}
 	}
@@ -136,15 +149,15 @@ impl RegexRule for SectionRule {
 		};
 
 		// [Optional] Reference name
-		let section_refname = matches.get(2).map_or_else(
-			|| None,
-			|refname| {
-				// Check for duplicate reference
-				if let Some(elem_reference) = document.get_reference(refname.as_str())
-				{
-					let elem = document.get_from_reference(&elem_reference).unwrap();
+		let section_refname =
+			matches.get(2).map_or_else(
+				|| None,
+				|refname| {
+					// Check for duplicate reference
+					if let Some(elem_reference) = document.get_reference(refname.as_str()) {
+						let elem = document.get_from_reference(&elem_reference).unwrap();
 
-					result.push(
+						result.push(
 						Report::build(ReportKind::Warning, token.source(), refname.start())
 						.with_message("Duplicate reference name")
 						.with_label(
@@ -163,10 +176,10 @@ impl RegexRule for SectionRule {
 							.with_color(parser.colors().warning))
 						.with_note(format!("Previous reference was overwritten"))
 						.finish());
-				}
-				Some(refname.as_str().to_string())
-			},
-		);
+					}
+					Some(refname.as_str().to_string())
+				},
+			);
 
 		// Section kind
 		let section_kind = match matches.get(3) {