From 4f27dc2f18185311a0fcb6c0ed5433bb21add373 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 15 May 2017 16:26:11 +0900 Subject: [PATCH 01/18] Move find_content_components to content mod --- src/content/page.rs | 4 ++-- src/content/section.rs | 3 ++- src/content/utils.rs | 31 ++++++++++++++++++++++++++++++- src/utils.rs | 36 +----------------------------------- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/content/page.rs b/src/content/page.rs index 64cd1f5e..ee6faf03 100644 --- a/src/content/page.rs +++ b/src/content/page.rs @@ -12,8 +12,8 @@ use errors::{Result, ResultExt}; use config::Config; use front_matter::{PageFrontMatter, split_page_content}; use markdown::markdown_to_html; -use utils::{read_file, find_content_components}; -use content::utils::{find_related_assets, get_reading_analytics}; +use utils::{read_file}; +use content::utils::{find_related_assets, find_content_components, get_reading_analytics}; diff --git a/src/content/section.rs b/src/content/section.rs index 876432c3..29f6578a 100644 --- a/src/content/section.rs +++ b/src/content/section.rs @@ -8,9 +8,10 @@ use serde::ser::{SerializeStruct, self}; use config::Config; use front_matter::{SectionFrontMatter, split_section_content}; use errors::{Result, ResultExt}; -use utils::{read_file, find_content_components}; +use utils::{read_file}; use markdown::markdown_to_html; use content::Page; +use content::utils::find_content_components; #[derive(Clone, Debug, PartialEq)] diff --git a/src/content/utils.rs b/src/content/utils.rs index 6f2be61a..f74e9496 100644 --- a/src/content/utils.rs +++ b/src/content/utils.rs @@ -33,13 +33,36 @@ pub fn get_reading_analytics(content: &str) -> (usize, usize) { } +/// Takes a full path to a .md and returns only the components after the first `content` directory +/// Will not return the filename as last component +pub fn find_content_components>(path: P) -> Vec { + let path = path.as_ref(); + let mut is_in_content = false; + let mut components = vec![]; + + for section in path.parent().unwrap().components() { + let component = section.as_ref().to_string_lossy(); + + if is_in_content { + components.push(component.to_string()); + continue; + } + + if component == "content" { + is_in_content = true; + } + } + + components +} + #[cfg(test)] mod tests { use std::fs::File; use tempdir::TempDir; - use super::{find_related_assets, get_reading_analytics}; + use super::{find_related_assets, find_content_components, get_reading_analytics}; #[test] fn can_find_related_assets() { @@ -74,4 +97,10 @@ mod tests { assert_eq!(word_count, 2000); assert_eq!(reading_time, 10); } + + #[test] + fn can_find_content_components() { + let res = find_content_components("/home/vincent/code/site/content/posts/tutorials/python.md"); + assert_eq!(res, ["posts".to_string(), "tutorials".to_string()]); + } } diff --git a/src/utils.rs b/src/utils.rs index 13e1c684..bb2c9836 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,6 +4,7 @@ use std::path::Path; use errors::{Result, ResultExt}; +/// Create a file with the content given pub fn create_file>(path: P, content: &str) -> Result<()> { let mut file = File::create(&path)?; file.write_all(content.as_bytes())?; @@ -32,38 +33,3 @@ pub fn read_file>(path: P) -> Result { Ok(content) } - - -/// Takes a full path to a .md and returns only the components after the first `content` directory -/// Will not return the filename as last component -pub fn find_content_components>(path: P) -> Vec { - let path = path.as_ref(); - let mut is_in_content = false; - let mut components = vec![]; - - for section in path.parent().unwrap().components() { - let component = section.as_ref().to_string_lossy(); - - if is_in_content { - components.push(component.to_string()); - continue; - } - - if component == "content" { - is_in_content = true; - } - } - - components -} - -#[cfg(test)] -mod tests { - use super::{find_content_components}; - - #[test] - fn test_find_content_components() { - let res = find_content_components("/home/vincent/code/site/content/posts/tutorials/python.md"); - assert_eq!(res, ["posts".to_string(), "tutorials".to_string()]); - } -} From b2c3adff370947a3748d1d41ada1001c41606131 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 15 May 2017 16:56:16 +0900 Subject: [PATCH 02/18] Move page tests inside content mod --- src/config.rs | 20 +++- src/content/page.rs | 141 ++++++++++++++++++++++ src/markdown.rs | 45 ++++--- src/templates/filters.rs | 6 +- tests/page.rs | 251 --------------------------------------- 5 files changed, 184 insertions(+), 279 deletions(-) delete mode 100644 tests/page.rs diff --git a/src/config.rs b/src/config.rs index 5c23a0c4..308f6dcf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -87,7 +87,9 @@ impl Config { /// Makes a url, taking into account that the base url might have a trailing slash pub fn make_permalink(&self, path: &str) -> String { - if self.base_url.ends_with('/') { + if self.base_url.ends_with('/') && path.starts_with('/') { + format!("{}{}", self.base_url, &path[1..]) + } else if self.base_url.ends_with('/') { format!("{}{}", self.base_url, path) } else { format!("{}/{}", self.base_url, path) @@ -95,8 +97,9 @@ impl Config { } } +/// Exists only for testing purposes +#[doc(hidden)] impl Default for Config { - /// Exists for testing purposes fn default() -> Config { Config { title: "".to_string(), @@ -181,4 +184,17 @@ hello = "world" assert_eq!(config.unwrap().extra.unwrap().get("hello").unwrap().as_str().unwrap(), "world"); } + #[test] + fn can_make_url_with_non_trailing_slash_base_url() { + let mut config = Config::default(); + config.base_url = "http://vincent.is".to_string(); + assert_eq!(config.make_permalink("hello"), "http://vincent.is/hello"); + } + + #[test] + fn can_make_url_with_trailing_slash_path() { + let mut config = Config::default(); + config.base_url = "http://vincent.is/".to_string(); + assert_eq!(config.make_permalink("/hello"), "http://vincent.is/hello"); + } } diff --git a/src/content/page.rs b/src/content/page.rs index ee6faf03..40623743 100644 --- a/src/content/page.rs +++ b/src/content/page.rs @@ -226,3 +226,144 @@ impl ser::Serialize for Page { state.end() } } + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + use std::fs::{File, create_dir}; + use std::path::Path; + + use tera::Tera; + use tempdir::TempDir; + + use config::Config; + use super::Page; + + + #[test] + fn test_can_parse_a_valid_page() { + let content = r#" ++++ +title = "Hello" +description = "hey there" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::parse(Path::new("post.md"), content, &Config::default()); + assert!(res.is_ok()); + let mut page = res.unwrap(); + page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); + + assert_eq!(page.meta.title.unwrap(), "Hello".to_string()); + assert_eq!(page.meta.slug.unwrap(), "hello-world".to_string()); + assert_eq!(page.raw_content, "Hello world".to_string()); + assert_eq!(page.content, "

Hello world

\n".to_string()); + } + + #[test] + fn test_can_make_url_from_sections_and_slug() { + let content = r#" + +++ + slug = "hello-world" + +++ + Hello world"#; + let mut conf = Config::default(); + conf.base_url = "http://hello.com/".to_string(); + let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &conf); + assert!(res.is_ok()); + let mut page = res.unwrap(); + page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); + assert_eq!(page.path, "posts/intro/hello-world"); + assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world"); + } + + #[test] + fn can_make_url_from_slug_only() { + let content = r#" + +++ + slug = "hello-world" + +++ + Hello world"#; + let config = Config::default(); + let res = Page::parse(Path::new("start.md"), content, &config); + assert!(res.is_ok()); + let mut page = res.unwrap(); + page.render_markdown(&HashMap::default(), &Tera::default(), &config).unwrap(); + assert_eq!(page.path, "hello-world"); + assert_eq!(page.permalink, config.make_permalink("hello-world")); + } + + #[test] + fn errors_on_invalid_front_matter_format() { + // missing starting +++ + let content = r#" + title = "Hello" + description = "hey there" + slug = "hello-world" + +++ + Hello world"#; + let res = Page::parse(Path::new("start.md"), content, &Config::default()); + assert!(res.is_err()); + } + + #[test] + fn can_make_slug_from_non_slug_filename() { + let config = Config::default(); + let res = Page::parse(Path::new(" file with space.md"), "+++\n+++", &config); + assert!(res.is_ok()); + let mut page = res.unwrap(); + page.render_markdown(&HashMap::default(), &Tera::default(), &config).unwrap(); + assert_eq!(page.slug, "file-with-space"); + assert_eq!(page.permalink, config.make_permalink(&page.slug)); + } + + #[test] + fn can_specify_summary() { + let config = Config::default(); + let content = r#" ++++ ++++ +Hello world +"#.to_string(); + let res = Page::parse(Path::new("hello.md"), &content, &config); + assert!(res.is_ok()); + let mut page = res.unwrap(); + page.render_markdown(&HashMap::default(), &Tera::default(), &config).unwrap(); + assert_eq!(page.summary, Some("

Hello world

\n".to_string())); + } + + #[test] + fn page_with_assets_gets_right_parent_path() { + let tmp_dir = TempDir::new("example").expect("create temp dir"); + let path = tmp_dir.path(); + create_dir(&path.join("content")).expect("create content temp dir"); + create_dir(&path.join("content").join("posts")).expect("create posts temp dir"); + let nested_path = path.join("content").join("posts").join("assets"); + create_dir(&nested_path).expect("create nested temp dir"); + File::create(nested_path.join("index.md")).unwrap(); + File::create(nested_path.join("example.js")).unwrap(); + File::create(nested_path.join("graph.jpg")).unwrap(); + File::create(nested_path.join("fail.png")).unwrap(); + + let res = Page::parse( + nested_path.join("index.md").as_path(), + "+++\nurl=\"hey\"+++\n", + &Config::default() + ); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.parent_path, path.join("content").join("posts")); + } + + #[test] + fn errors_file_not_named_index_with_assets() { + let tmp_dir = TempDir::new("example").expect("create temp dir"); + File::create(tmp_dir.path().join("something.md")).unwrap(); + File::create(tmp_dir.path().join("example.js")).unwrap(); + File::create(tmp_dir.path().join("graph.jpg")).unwrap(); + File::create(tmp_dir.path().join("fail.png")).unwrap(); + + let page = Page::from_file(tmp_dir.path().join("something.md"), &Config::default()); + assert!(page.is_err()); + } +} diff --git a/src/markdown.rs b/src/markdown.rs index f32cf898..f4a236bf 100644 --- a/src/markdown.rs +++ b/src/markdown.rs @@ -347,14 +347,14 @@ mod tests { use super::{markdown_to_html, parse_shortcode}; #[test] - fn test_parse_simple_shortcode_one_arg() { + fn can_parse_simple_shortcode_one_arg() { let (name, args) = parse_shortcode(r#"{{ youtube(id="w7Ft2ymGmfc") }}"#); assert_eq!(name, "youtube"); assert_eq!(args["id"], "w7Ft2ymGmfc"); } #[test] - fn test_parse_simple_shortcode_several_arg() { + fn can_parse_simple_shortcode_several_arg() { let (name, args) = parse_shortcode(r#"{{ youtube(id="w7Ft2ymGmfc", autoplay=true) }}"#); assert_eq!(name, "youtube"); assert_eq!(args["id"], "w7Ft2ymGmfc"); @@ -362,7 +362,7 @@ mod tests { } #[test] - fn test_parse_block_shortcode_several_arg() { + fn can_parse_block_shortcode_several_arg() { let (name, args) = parse_shortcode(r#"{% youtube(id="w7Ft2ymGmfc", autoplay=true) %}"#); assert_eq!(name, "youtube"); assert_eq!(args["id"], "w7Ft2ymGmfc"); @@ -370,13 +370,13 @@ mod tests { } #[test] - fn test_markdown_to_html_simple() { + fn can_do_markdown_to_html_simple() { let res = markdown_to_html("hello", &HashMap::new(), &Tera::default(), &Config::default()).unwrap(); assert_eq!(res, "

hello

\n"); } #[test] - fn test_markdown_to_html_code_block_highlighting_off() { + fn doesnt_highlight_code_block_with_highlighting_off() { let mut config = Config::default(); config.highlight_code = Some(false); let res = markdown_to_html("```\n$ gutenberg server\n```", &HashMap::new(), &Tera::default(), &config).unwrap(); @@ -387,7 +387,7 @@ mod tests { } #[test] - fn test_markdown_to_html_code_block_no_lang() { + fn can_highlight_code_block_no_lang() { let res = markdown_to_html("```\n$ gutenberg server\n$ ping\n```", &HashMap::new(), &Tera::default(), &Config::default()).unwrap(); assert_eq!( res, @@ -396,7 +396,7 @@ mod tests { } #[test] - fn test_markdown_to_html_code_block_with_lang() { + fn can_highlight_code_block_with_lang() { let res = markdown_to_html("```python\nlist.append(1)\n```", &HashMap::new(), &Tera::default(), &Config::default()).unwrap(); assert_eq!( res, @@ -405,7 +405,7 @@ mod tests { } #[test] - fn test_markdown_to_html_code_block_with_unknown_lang() { + fn can_higlight_code_block_with_unknown_lang() { let res = markdown_to_html("```yolo\nlist.append(1)\n```", &HashMap::new(), &Tera::default(), &Config::default()).unwrap(); // defaults to plain text assert_eq!( @@ -415,7 +415,7 @@ mod tests { } #[test] - fn test_markdown_to_html_with_shortcode() { + fn can_render_shortcode() { let res = markdown_to_html(r#" Hello @@ -426,7 +426,7 @@ Hello } #[test] - fn test_markdown_to_html_with_several_shortcode_in_row() { + fn can_render_several_shortcode_in_row() { let res = markdown_to_html(r#" Hello @@ -446,13 +446,13 @@ Hello } #[test] - fn test_markdown_to_html_shortcode_in_code_block() { + fn doesnt_render_shortcode_in_code_block() { let res = markdown_to_html(r#"```{{ youtube(id="w7Ft2ymGmfc") }}```"#, &HashMap::new(), &GUTENBERG_TERA, &Config::default()).unwrap(); assert_eq!(res, "

{{ youtube(id="w7Ft2ymGmfc") }}

\n"); } #[test] - fn test_markdown_to_html_shortcode_with_body() { + fn can_render_shortcode_with_body() { let mut tera = Tera::default(); tera.extend(&GUTENBERG_TERA).unwrap(); tera.add_raw_template("shortcodes/quote.html", "
{{ body }} - {{ author}}
").unwrap(); @@ -466,13 +466,13 @@ A quote } #[test] - fn test_markdown_to_html_unknown_shortcode() { + fn errors_rendering_unknown_shortcode() { let res = markdown_to_html("{{ hello(flash=true) }}", &HashMap::new(), &Tera::default(), &Config::default()); assert!(res.is_err()); } #[test] - fn test_markdown_to_html_relative_link_exists() { + fn can_make_valid_relative_link() { let mut permalinks = HashMap::new(); permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string()); let res = markdown_to_html( @@ -488,7 +488,7 @@ A quote } #[test] - fn test_markdown_to_html_relative_links_with_anchors() { + fn can_make_relative_links_with_anchors() { let mut permalinks = HashMap::new(); permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string()); let res = markdown_to_html( @@ -504,25 +504,25 @@ A quote } #[test] - fn test_markdown_to_html_relative_link_inexistant() { + fn errors_relative_link_inexistant() { let res = markdown_to_html("[rel link](./pages/about.md)", &HashMap::new(), &Tera::default(), &Config::default()); assert!(res.is_err()); } #[test] - fn test_markdown_to_html_add_id_to_headers() { + fn can_add_id_to_headers() { let res = markdown_to_html(r#"# Hello"#, &HashMap::new(), &GUTENBERG_TERA, &Config::default()).unwrap(); assert_eq!(res, "

Hello

\n"); } #[test] - fn test_markdown_to_html_add_id_to_headers_same_slug() { + fn can_add_id_to_headers_same_slug() { let res = markdown_to_html("# Hello\n# Hello", &HashMap::new(), &GUTENBERG_TERA, &Config::default()).unwrap(); assert_eq!(res, "

Hello

\n

Hello

\n"); } #[test] - fn test_markdown_to_html_insert_anchor() { + fn can_insert_anchor() { let mut config = Config::default(); config.insert_anchor_links = Some(true); let res = markdown_to_html("# Hello", &HashMap::new(), &GUTENBERG_TERA, &config).unwrap(); @@ -534,7 +534,7 @@ A quote // See https://github.com/Keats/gutenberg/issues/42 #[test] - fn test_markdown_to_html_insert_anchor_with_exclamation_mark() { + fn can_insert_anchor_with_exclamation_mark() { let mut config = Config::default(); config.insert_anchor_links = Some(true); let res = markdown_to_html("# Hello!", &HashMap::new(), &GUTENBERG_TERA, &config).unwrap(); @@ -546,7 +546,7 @@ A quote // See https://github.com/Keats/gutenberg/issues/53 #[test] - fn test_markdown_to_html_insert_anchor_with_link() { + fn can_insert_anchor_with_link() { let mut config = Config::default(); config.insert_anchor_links = Some(true); let res = markdown_to_html("## [](#xresources)Xresources", &HashMap::new(), &GUTENBERG_TERA, &config).unwrap(); @@ -556,9 +556,8 @@ A quote ); } - #[test] - fn test_markdown_to_html_insert_anchor_with_other_special_chars() { + fn can_insert_anchor_with_other_special_chars() { let mut config = Config::default(); config.insert_anchor_links = Some(true); let res = markdown_to_html("# Hello*_()", &HashMap::new(), &GUTENBERG_TERA, &config).unwrap(); diff --git a/src/templates/filters.rs b/src/templates/filters.rs index f40cb04c..8ebc40e6 100644 --- a/src/templates/filters.rs +++ b/src/templates/filters.rs @@ -45,14 +45,14 @@ mod tests { use super::{markdown, base64_decode, base64_encode}; #[test] - fn test_markdown() { + fn markdown_filter() { let result = markdown(to_value(&"# Hey").unwrap(), HashMap::new()); assert!(result.is_ok()); assert_eq!(result.unwrap(), to_value(&"

Hey

\n").unwrap()); } #[test] - fn test_base64_encode() { + fn base64_encode_filter() { // from https://tools.ietf.org/html/rfc4648#section-10 let tests = vec![ ("", ""), @@ -73,7 +73,7 @@ mod tests { #[test] - fn test_base64_decode() { + fn base64_decode_filter() { let tests = vec![ ("", ""), ("Zg==", "f"), diff --git a/tests/page.rs b/tests/page.rs deleted file mode 100644 index aa7e1c7a..00000000 --- a/tests/page.rs +++ /dev/null @@ -1,251 +0,0 @@ -extern crate gutenberg; -extern crate tera; -extern crate tempdir; - -use std::collections::HashMap; -use std::fs::{File, create_dir}; -use std::path::Path; - -use tempdir::TempDir; -use tera::Tera; - -use gutenberg::{Page, Config}; - - -#[test] -fn test_can_parse_a_valid_page() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse(Path::new("post.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - - assert_eq!(page.meta.title.unwrap(), "Hello".to_string()); - assert_eq!(page.meta.slug.unwrap(), "hello-world".to_string()); - assert_eq!(page.raw_content, "Hello world".to_string()); - assert_eq!(page.content, "

Hello world

\n".to_string()); -} - -#[test] -fn test_can_find_one_parent_directory() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse(Path::new("content/posts/intro.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.components, vec!["posts".to_string()]); -} - -#[test] -fn test_can_find_multiple_parent_directories() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.components, vec!["posts".to_string(), "intro".to_string()]); -} - -#[test] -fn test_can_make_url_from_sections_and_slug() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let mut conf = Config::default(); - conf.base_url = "http://hello.com/".to_string(); - let res = Page::parse(Path::new("content/posts/intro/start.md"), content, &conf); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.path, "posts/intro/hello-world"); - assert_eq!(page.permalink, "http://hello.com/posts/intro/hello-world"); -} - -#[test] -fn test_can_make_permalink_with_non_trailing_slash_base_url() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let mut conf = Config::default(); - conf.base_url = "http://hello.com".to_string(); - let res = Page::parse(Path::new("content/posts/intro/hello-world.md"), content, &conf); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.path, "posts/intro/hello-world"); - assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world")); -} - -#[test] -fn test_can_make_url_from_slug_only() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse(Path::new("start.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.path, "hello-world"); - assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "hello-world")); -} - -#[test] -fn test_errors_on_invalid_front_matter_format() { - let content = r#" -title = "Hello" -description = "hey there" -slug = "hello-world" -+++ -Hello world"#; - let res = Page::parse(Path::new("start.md"), content, &Config::default()); - assert!(res.is_err()); -} - -#[test] -fn test_can_make_slug_from_non_slug_filename() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -+++ -Hello world"#; - let res = Page::parse(Path::new("file with space.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.slug, "file-with-space"); - assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); -} - -#[test] -fn test_trim_slug_if_needed() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -+++ -Hello world"#; - let res = Page::parse(Path::new(" file with space.md"), content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.slug, "file-with-space"); - assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); -} - -#[test] -fn test_automatic_summary_is_empty_string() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -+++ -Hello world"#.to_string(); - let res = Page::parse(Path::new("hello.md"), &content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.summary, None); -} - -#[test] -fn test_can_specify_summary() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -+++ -Hello world - -"#.to_string(); - let res = Page::parse(Path::new("hello.md"), &content, &Config::default()); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert_eq!(page.summary, Some("

Hello world

\n".to_string())); -} - -#[test] -fn test_can_auto_detect_when_highlighting_needed() { - let content = r#" -+++ -title = "Hello" -description = "hey there" -+++ -``` -Hey there -``` -"#.to_string(); - let mut config = Config::default(); - config.highlight_code = Some(true); - let res = Page::parse(Path::new("hello.md"), &content, &config); - assert!(res.is_ok()); - let mut page = res.unwrap(); - page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap(); - assert!(page.content.starts_with(" Date: Mon, 15 May 2017 17:11:14 +0900 Subject: [PATCH 03/18] Minify livereload.js --- src/bin/cmd/livereload.js | 1157 +------------------------------------ src/bin/cmd/serve.rs | 4 + tests/site.rs | 1 - 3 files changed, 5 insertions(+), 1157 deletions(-) diff --git a/src/bin/cmd/livereload.js b/src/bin/cmd/livereload.js index eaa78b00..6dd6d198 100644 --- a/src/bin/cmd/livereload.js +++ b/src/bin/cmd/livereload.js @@ -1,1156 +1 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tag"); - return; - } - this.reloader = new Reloader(this.window, this.console, Timer); - this.connector = new Connector(this.options, this.WebSocket, Timer, { - connecting: (function(_this) { - return function() {}; - })(this), - socketConnected: (function(_this) { - return function() {}; - })(this), - connected: (function(_this) { - return function(protocol) { - var _base; - if (typeof (_base = _this.listeners).connect === "function") { - _base.connect(); - } - _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ")."); - return _this.analyze(); - }; - })(this), - error: (function(_this) { - return function(e) { - console.log(e); - // if (e instanceof ProtocolError) { - // if (typeof console !== "undefined" && console !== null) { - // return console.log("" + e.message + "."); - // } - // } else { - // if (typeof console !== "undefined" && console !== null) { - // return console.log("LiveReload internal error: " + e.message); - // } - // } - }; - })(this), - disconnected: (function(_this) { - return function(reason, nextDelay) { - var _base; - if (typeof (_base = _this.listeners).disconnect === "function") { - _base.disconnect(); - } - switch (reason) { - case 'cannot-connect': - return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec."); - case 'broken': - return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec."); - case 'handshake-timeout': - return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec."); - case 'handshake-failed': - return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec."); - case 'manual': - break; - case 'error': - break; - default: - return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec."); - } - }; - })(this), - message: (function(_this) { - return function(message) { - switch (message.command) { - case 'reload': - return _this.performReload(message); - case 'alert': - return _this.performAlert(message); - } - }; - })(this) - }); - } - - LiveReload.prototype.on = function(eventName, handler) { - return this.listeners[eventName] = handler; - }; - - LiveReload.prototype.log = function(message) { - return this.console.log("" + message); - }; - - LiveReload.prototype.performReload = function(message) { - var _ref, _ref1; - this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2))); - return this.reloader.reload(message.path, { - liveCSS: (_ref = message.liveCSS) != null ? _ref : true, - liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true, - originalPath: message.originalPath || '', - overrideURL: message.overrideURL || '', - serverURL: "http://" + this.options.host + ":" + this.options.port - }); - }; - - LiveReload.prototype.performAlert = function(message) { - return alert(message.message); - }; - - LiveReload.prototype.shutDown = function() { - var _base; - this.connector.disconnect(); - this.log("LiveReload disconnected."); - return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0; - }; - - LiveReload.prototype.hasPlugin = function(identifier) { - return !!this.pluginIdentifiers[identifier]; - }; - - LiveReload.prototype.addPlugin = function(pluginClass) { - var plugin; - if (this.hasPlugin(pluginClass.identifier)) { - return; - } - this.pluginIdentifiers[pluginClass.identifier] = true; - plugin = new pluginClass(this.window, { - _livereload: this, - _reloader: this.reloader, - _connector: this.connector, - console: this.console, - Timer: Timer, - generateCacheBustUrl: (function(_this) { - return function(url) { - return _this.reloader.generateCacheBustUrl(url); - }; - })(this) - }); - this.plugins.push(plugin); - this.reloader.addPlugin(plugin); - }; - - LiveReload.prototype.analyze = function() { - var plugin, pluginData, pluginsData, _i, _len, _ref; - if (!(this.connector.protocol >= 7)) { - return; - } - pluginsData = {}; - _ref = this.plugins; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - plugin = _ref[_i]; - pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {}; - pluginData.version = plugin.constructor.version; - } - this.connector.sendCommand({ - command: 'info', - plugins: pluginsData, - url: this.window.location.href - }); - }; - - return LiveReload; - - })(); - -}).call(this); - -},{"./connector":1,"./options":5,"./reloader":7,"./timer":9}],5:[function(require,module,exports){ -(function() { - var Options; - - exports.Options = Options = (function() { - function Options() { - this.host = null; - this.port = 35729; - this.snipver = null; - this.ext = null; - this.extver = null; - this.mindelay = 1000; - this.maxdelay = 60000; - this.handshake_timeout = 5000; - } - - Options.prototype.set = function(name, value) { - if (typeof value === 'undefined') { - return; - } - if (!isNaN(+value)) { - value = +value; - } - return this[name] = value; - }; - - return Options; - - })(); - - Options.extract = function(document) { - var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1; - _ref = document.getElementsByTagName('script'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - element = _ref[_i]; - if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { - options = new Options(); - if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { - options.host = mm[1]; - if (mm[2]) { - options.port = parseInt(mm[2], 10); - } - } - if (m[2]) { - _ref1 = m[2].split('&'); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - pair = _ref1[_j]; - if ((keyAndValue = pair.split('=')).length > 1) { - options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); - } - } - } - return options; - } - } - return null; - }; - -}).call(this); - -},{}],6:[function(require,module,exports){ -(function() { - var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError, - __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - exports.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; - - exports.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; - - exports.ProtocolError = ProtocolError = (function() { - function ProtocolError(reason, data) { - this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; - } - - return ProtocolError; - - })(); - - exports.Parser = Parser = (function() { - function Parser(handlers) { - this.handlers = handlers; - this.reset(); - } - - Parser.prototype.reset = function() { - return this.protocol = null; - }; - - Parser.prototype.process = function(data) { - var command, e, message, options, _ref; - try { - if (this.protocol == null) { - if (data.match(/^!!ver:([\d.]+)$/)) { - this.protocol = 6; - } else if (message = this._parseMessage(data, ['hello'])) { - if (!message.protocols.length) { - throw new ProtocolError("no protocols specified in handshake message"); - } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { - this.protocol = 7; - } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { - this.protocol = 6; - } else { - throw new ProtocolError("no supported protocols found"); - } - } - return this.handlers.connected(this.protocol); - } else if (this.protocol === 6) { - message = JSON.parse(data); - if (!message.length) { - throw new ProtocolError("protocol 6 messages must be arrays"); - } - command = message[0], options = message[1]; - if (command !== 'refresh') { - throw new ProtocolError("unknown protocol 6 command"); - } - return this.handlers.message({ - command: 'reload', - path: options.path, - liveCSS: (_ref = options.apply_css_live) != null ? _ref : true - }); - } else { - message = this._parseMessage(data, ['reload', 'alert']); - return this.handlers.message(message); - } - } catch (_error) { - e = _error; - if (e instanceof ProtocolError) { - return this.handlers.error(e); - } else { - throw e; - } - } - }; - - Parser.prototype._parseMessage = function(data, validCommands) { - var e, message, _ref; - try { - message = JSON.parse(data); - } catch (_error) { - e = _error; - throw new ProtocolError('unparsable JSON', data); - } - if (!message.command) { - throw new ProtocolError('missing "command" key', data); - } - if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { - throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); - } - return message; - }; - - return Parser; - - })(); - -}).call(this); - -},{}],7:[function(require,module,exports){ -(function() { - var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; - - splitUrl = function(url) { - var hash, index, params; - if ((index = url.indexOf('#')) >= 0) { - hash = url.slice(index); - url = url.slice(0, index); - } else { - hash = ''; - } - if ((index = url.indexOf('?')) >= 0) { - params = url.slice(index); - url = url.slice(0, index); - } else { - params = ''; - } - return { - url: url, - params: params, - hash: hash - }; - }; - - pathFromUrl = function(url) { - var path; - url = splitUrl(url).url; - if (url.indexOf('file://') === 0) { - path = url.replace(/^file:\/\/(localhost)?/, ''); - } else { - path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); - } - return decodeURIComponent(path); - }; - - pickBestMatch = function(path, objects, pathFunc) { - var bestMatch, object, score, _i, _len; - bestMatch = { - score: 0 - }; - for (_i = 0, _len = objects.length; _i < _len; _i++) { - object = objects[_i]; - score = numberOfMatchingSegments(path, pathFunc(object)); - if (score > bestMatch.score) { - bestMatch = { - object: object, - score: score - }; - } - } - if (bestMatch.score > 0) { - return bestMatch; - } else { - return null; - } - }; - - numberOfMatchingSegments = function(path1, path2) { - var comps1, comps2, eqCount, len; - path1 = path1.replace(/^\/+/, '').toLowerCase(); - path2 = path2.replace(/^\/+/, '').toLowerCase(); - if (path1 === path2) { - return 10000; - } - comps1 = path1.split('/').reverse(); - comps2 = path2.split('/').reverse(); - len = Math.min(comps1.length, comps2.length); - eqCount = 0; - while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { - ++eqCount; - } - return eqCount; - }; - - pathsMatch = function(path1, path2) { - return numberOfMatchingSegments(path1, path2) > 0; - }; - - IMAGE_STYLES = [ - { - selector: 'background', - styleNames: ['backgroundImage'] - }, { - selector: 'border', - styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] - } - ]; - - exports.Reloader = Reloader = (function() { - function Reloader(window, console, Timer) { - this.window = window; - this.console = console; - this.Timer = Timer; - this.document = this.window.document; - this.importCacheWaitPeriod = 200; - this.plugins = []; - } - - Reloader.prototype.addPlugin = function(plugin) { - return this.plugins.push(plugin); - }; - - Reloader.prototype.analyze = function(callback) { - return results; - }; - - Reloader.prototype.reload = function(path, options) { - var plugin, _base, _i, _len, _ref; - this.options = options; - if ((_base = this.options).stylesheetReloadTimeout == null) { - _base.stylesheetReloadTimeout = 15000; - } - _ref = this.plugins; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - plugin = _ref[_i]; - if (plugin.reload && plugin.reload(path, options)) { - return; - } - } - if (options.liveCSS) { - if (path.match(/\.css$/i)) { - if (this.reloadStylesheet(path)) { - return; - } - } - } - if (options.liveImg) { - if (path.match(/\.(jpe?g|png|gif)$/i)) { - this.reloadImages(path); - return; - } - } - return this.reloadPage(); - }; - - Reloader.prototype.reloadPage = function() { - return this.window.document.location.reload(); - }; - - Reloader.prototype.reloadImages = function(path) { - var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; - expando = this.generateUniqueString(); - _ref = this.document.images; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - img = _ref[_i]; - if (pathsMatch(path, pathFromUrl(img.src))) { - img.src = this.generateCacheBustUrl(img.src, expando); - } - } - if (this.document.querySelectorAll) { - for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { - _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; - _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - img = _ref2[_k]; - this.reloadStyleImages(img.style, styleNames, path, expando); - } - } - } - if (this.document.styleSheets) { - _ref3 = this.document.styleSheets; - _results = []; - for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { - styleSheet = _ref3[_l]; - _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); - } - return _results; - } - }; - - Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { - var e, rule, rules, styleNames, _i, _j, _len, _len1; - try { - rules = styleSheet != null ? styleSheet.cssRules : void 0; - } catch (_error) { - e = _error; - } - if (!rules) { - return; - } - for (_i = 0, _len = rules.length; _i < _len; _i++) { - rule = rules[_i]; - switch (rule.type) { - case CSSRule.IMPORT_RULE: - this.reloadStylesheetImages(rule.styleSheet, path, expando); - break; - case CSSRule.STYLE_RULE: - for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { - styleNames = IMAGE_STYLES[_j].styleNames; - this.reloadStyleImages(rule.style, styleNames, path, expando); - } - break; - case CSSRule.MEDIA_RULE: - this.reloadStylesheetImages(rule, path, expando); - } - } - }; - - Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { - var newValue, styleName, value, _i, _len; - for (_i = 0, _len = styleNames.length; _i < _len; _i++) { - styleName = styleNames[_i]; - value = style[styleName]; - if (typeof value === 'string') { - newValue = value.replace(/\burl\s*\(([^)]*)\)/, (function(_this) { - return function(match, src) { - if (pathsMatch(path, pathFromUrl(src))) { - return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; - } else { - return match; - } - }; - })(this)); - if (newValue !== value) { - style[styleName] = newValue; - } - } - } - }; - - Reloader.prototype.reloadStylesheet = function(path) { - var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1; - links = (function() { - var _i, _len, _ref, _results; - _ref = this.document.getElementsByTagName('link'); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link.rel.match(/^stylesheet$/i) && !link.__LiveReload_pendingRemoval) { - _results.push(link); - } - } - return _results; - }).call(this); - imported = []; - _ref = this.document.getElementsByTagName('style'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - style = _ref[_i]; - if (style.sheet) { - this.collectImportedStylesheets(style, style.sheet, imported); - } - } - for (_j = 0, _len1 = links.length; _j < _len1; _j++) { - link = links[_j]; - this.collectImportedStylesheets(link, link.sheet, imported); - } - if (this.window.StyleFix && this.document.querySelectorAll) { - _ref1 = this.document.querySelectorAll('style[data-href]'); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - style = _ref1[_k]; - links.push(style); - } - } - this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); - match = pickBestMatch(path, links.concat(imported), (function(_this) { - return function(l) { - return pathFromUrl(_this.linkHref(l)); - }; - })(this)); - if (match) { - if (match.object.rule) { - this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); - this.reattachImportedRule(match.object); - } else { - this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); - this.reattachStylesheetLink(match.object); - } - } else { - this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); - for (_l = 0, _len3 = links.length; _l < _len3; _l++) { - link = links[_l]; - this.reattachStylesheetLink(link); - } - } - return true; - }; - - Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { - var e, index, rule, rules, _i, _len; - try { - rules = styleSheet != null ? styleSheet.cssRules : void 0; - } catch (_error) { - e = _error; - } - if (rules && rules.length) { - for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { - rule = rules[index]; - switch (rule.type) { - case CSSRule.CHARSET_RULE: - continue; - case CSSRule.IMPORT_RULE: - result.push({ - link: link, - rule: rule, - index: index, - href: rule.href - }); - this.collectImportedStylesheets(link, rule.styleSheet, result); - break; - default: - break; - } - } - } - }; - - Reloader.prototype.waitUntilCssLoads = function(clone, func) { - var callbackExecuted, executeCallback, poll; - callbackExecuted = false; - executeCallback = (function(_this) { - return function() { - if (callbackExecuted) { - return; - } - callbackExecuted = true; - return func(); - }; - })(this); - clone.onload = (function(_this) { - return function() { - _this.console.log("LiveReload: the new stylesheet has finished loading"); - _this.knownToSupportCssOnLoad = true; - return executeCallback(); - }; - })(this); - if (!this.knownToSupportCssOnLoad) { - (poll = (function(_this) { - return function() { - if (clone.sheet) { - _this.console.log("LiveReload is polling until the new CSS finishes loading..."); - return executeCallback(); - } else { - return _this.Timer.start(50, poll); - } - }; - })(this))(); - } - return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); - }; - - Reloader.prototype.linkHref = function(link) { - return link.href || link.getAttribute('data-href'); - }; - - Reloader.prototype.reattachStylesheetLink = function(link) { - var clone, parent; - if (link.__LiveReload_pendingRemoval) { - return; - } - link.__LiveReload_pendingRemoval = true; - if (link.tagName === 'STYLE') { - clone = this.document.createElement('link'); - clone.rel = 'stylesheet'; - clone.media = link.media; - clone.disabled = link.disabled; - } else { - clone = link.cloneNode(false); - } - clone.href = this.generateCacheBustUrl(this.linkHref(link)); - parent = link.parentNode; - if (parent.lastChild === link) { - parent.appendChild(clone); - } else { - parent.insertBefore(clone, link.nextSibling); - } - return this.waitUntilCssLoads(clone, (function(_this) { - return function() { - var additionalWaitingTime; - if (/AppleWebKit/.test(navigator.userAgent)) { - additionalWaitingTime = 5; - } else { - additionalWaitingTime = 200; - } - return _this.Timer.start(additionalWaitingTime, function() { - var _ref; - if (!link.parentNode) { - return; - } - link.parentNode.removeChild(link); - clone.onreadystatechange = null; - return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; - }); - }; - })(this)); - }; - - Reloader.prototype.reattachImportedRule = function(_arg) { - var href, index, link, media, newRule, parent, rule, tempLink; - rule = _arg.rule, index = _arg.index, link = _arg.link; - parent = rule.parentStyleSheet; - href = this.generateCacheBustUrl(rule.href); - media = rule.media.length ? [].join.call(rule.media, ', ') : ''; - newRule = "@import url(\"" + href + "\") " + media + ";"; - rule.__LiveReload_newHref = href; - tempLink = this.document.createElement("link"); - tempLink.rel = 'stylesheet'; - tempLink.href = href; - tempLink.__LiveReload_pendingRemoval = true; - if (link.parentNode) { - link.parentNode.insertBefore(tempLink, link); - } - return this.Timer.start(this.importCacheWaitPeriod, (function(_this) { - return function() { - if (tempLink.parentNode) { - tempLink.parentNode.removeChild(tempLink); - } - if (rule.__LiveReload_newHref !== href) { - return; - } - parent.insertRule(newRule, index); - parent.deleteRule(index + 1); - rule = parent.cssRules[index]; - rule.__LiveReload_newHref = href; - return _this.Timer.start(_this.importCacheWaitPeriod, function() { - if (rule.__LiveReload_newHref !== href) { - return; - } - parent.insertRule(newRule, index); - return parent.deleteRule(index + 1); - }); - }; - })(this)); - }; - - Reloader.prototype.generateUniqueString = function() { - return 'livereload=' + Date.now(); - }; - - Reloader.prototype.generateCacheBustUrl = function(url, expando) { - var hash, oldParams, originalUrl, params, _ref; - if (expando == null) { - expando = this.generateUniqueString(); - } - _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; - if (this.options.overrideURL) { - if (url.indexOf(this.options.serverURL) < 0) { - originalUrl = url; - url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); - this.console.log("LiveReload is overriding source URL " + originalUrl + " with " + url); - } - } - params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { - return "" + sep + expando; - }); - if (params === oldParams) { - if (oldParams.length === 0) { - params = "?" + expando; - } else { - params = "" + oldParams + "&" + expando; - } - } - return url + params + hash; - }; - - return Reloader; - - })(); - -}).call(this); - -},{}],8:[function(require,module,exports){ -(function() { - var CustomEvents, LiveReload, k; - - CustomEvents = require('./customevents'); - - LiveReload = window.LiveReload = new (require('./livereload').LiveReload)(window); - - for (k in window) { - if (k.match(/^LiveReloadPlugin/)) { - LiveReload.addPlugin(window[k]); - } - } - - LiveReload.addPlugin(require('./less')); - - LiveReload.on('shutdown', function() { - return delete window.LiveReload; - }); - - LiveReload.on('connect', function() { - return CustomEvents.fire(document, 'LiveReloadConnect'); - }); - - LiveReload.on('disconnect', function() { - return CustomEvents.fire(document, 'LiveReloadDisconnect'); - }); - - CustomEvents.bind(document, 'LiveReloadShutDown', function() { - return LiveReload.shutDown(); - }); - -}).call(this); - -},{"./customevents":2,"./less":3,"./livereload":4}],9:[function(require,module,exports){ -(function() { - var Timer; - - exports.Timer = Timer = (function() { - function Timer(func) { - this.func = func; - this.running = false; - this.id = null; - this._handler = (function(_this) { - return function() { - _this.running = false; - _this.id = null; - return _this.func(); - }; - })(this); - } - - Timer.prototype.start = function(timeout) { - if (this.running) { - clearTimeout(this.id); - } - this.id = setTimeout(this._handler, timeout); - return this.running = true; - }; - - Timer.prototype.stop = function() { - if (this.running) { - clearTimeout(this.id); - this.running = false; - return this.id = null; - } - }; - - return Timer; - - })(); - - Timer.start = function(timeout, func) { - return setTimeout(func, timeout); - }; - -}).call(this); - -},{}]},{},[8]); +!function e(t,n,o){function i(s,l){if(!n[s]){if(!t[s]){var c="function"==typeof require&&require;if(!l&&c)return c(s,!0);if(r)return r(s,!0);var a=Error("Cannot find module '"+s+"'");throw a.code="MODULE_NOT_FOUND",a}var h=n[s]={exports:{}};t[s][0].call(h.exports,function(e){var n=t[s][1][e];return i(n?n:e)},h,h.exports,e,t,n,o)}return n[s].exports}for(var r="function"==typeof require&&require,s=0;st;t++)e=o[t],(e.href&&e.rel.match(/^stylesheet\/less$/i)||e.rel.match(/stylesheet/i)&&e.type.match(/^text\/(x-)?less$/i))&&i.push(e);return i}(),0===t.length)return!1;for(n=0,o=t.length;o>n;n++)e=t[n],e.href=this.host.generateCacheBustUrl(e.href);return this.host.console.log("LiveReload is asking LESS to recompile all stylesheets"),this.window.less.refresh(!0),!0},e.prototype.analyze=function(){return{disable:!(!this.window.less||!this.window.less.refresh)}},e}()}).call(this)},{}],4:[function(e,t,n){(function(){var t,o,i,r,s;t=e("./connector").Connector,s=e("./timer").Timer,i=e("./options").Options,r=e("./reloader").Reloader,n.LiveReload=o=function(){function e(e){return this.window=e,this.listeners={},this.plugins=[],this.pluginIdentifiers={},this.console=this.window.location.href.match(/LR-verbose/)&&this.window.console&&this.window.console.log&&this.window.console.error?this.window.console:{log:function(){},error:function(){}},(this.WebSocket=this.window.WebSocket||this.window.MozWebSocket)?(this.options=i.extract(this.window.document))?(this.reloader=new r(this.window,this.console,s),void(this.connector=new t(this.options,this.WebSocket,s,{connecting:function(){return function(){}}(this),socketConnected:function(){return function(){}}(this),connected:function(e){return function(t){var n;return"function"==typeof(n=e.listeners).connect&&n.connect(),e.log("LiveReload is connected to "+e.options.host+":"+e.options.port+" (protocol v"+t+")."),e.analyze()}}(this),error:function(){return function(e){console.log(e)}}(this),disconnected:function(e){return function(t,n){var o;switch("function"==typeof(o=e.listeners).disconnect&&o.disconnect(),t){case"cannot-connect":return e.log("LiveReload cannot connect to "+e.options.host+":"+e.options.port+", will retry in "+n+" sec.");case"broken":return e.log("LiveReload disconnected from "+e.options.host+":"+e.options.port+", reconnecting in "+n+" sec.");case"handshake-timeout":return e.log("LiveReload cannot connect to "+e.options.host+":"+e.options.port+" (handshake timeout), will retry in "+n+" sec.");case"handshake-failed":return e.log("LiveReload cannot connect to "+e.options.host+":"+e.options.port+" (handshake failed), will retry in "+n+" sec.");case"manual":break;case"error":break;default:return e.log("LiveReload disconnected from "+e.options.host+":"+e.options.port+" ("+t+"), reconnecting in "+n+" sec.")}}}(this),message:function(e){return function(t){switch(t.command){case"reload":return e.performReload(t);case"alert":return e.performAlert(t)}}}(this)}))):void this.console.error("LiveReload disabled because it could not find its own