use std::io;
use std::io::{Read, Write};

fn main() {
    let mut is_in_code_block = false;
    let mut is_in_inline_code = false;
    let mut is_in_html_tag = false;

    let mut buffer = String::new();
    if let Err(e) = io::stdin().read_to_string(&mut buffer) {
	panic!("{}", e);
    }

    for line in buffer.lines() {
	if line.is_empty() {
	    is_in_inline_code = false;
	}
	if line.starts_with("```") {
	    is_in_code_block = !is_in_code_block;
	}
	if is_in_code_block {
	    is_in_inline_code = false;
	    is_in_html_tag = false;
	    write!(io::stdout(), "{}\n", line).unwrap();
	} else {
	    let modified_line = &mut String::new();
	    let mut previous_char = std::char::REPLACEMENT_CHARACTER;
	    let mut chars_in_line = line.chars();

	    while let Some(possible_match) = chars_in_line.next() {
		// Check if inside inline code.
		if possible_match == '`' {
		    is_in_inline_code = !is_in_inline_code;
		}
		// Check if inside HTML tag.
		if possible_match == '<' && !is_in_inline_code {
		    is_in_html_tag = true;
		}
		if possible_match == '>' && !is_in_inline_code {
		    is_in_html_tag = false;
		}

		// Replace with right/left apostrophe/quote.
		let char_to_push = if possible_match == '\''
		    && !is_in_inline_code
		    && !is_in_html_tag
		{
		    if (previous_char != std::char::REPLACEMENT_CHARACTER
			&& !previous_char.is_whitespace())
			|| previous_char == '‘'
		    {
			'’'
		    } else {
			'‘'
		    }
		} else if possible_match == '"'
		    && !is_in_inline_code
		    && !is_in_html_tag
		{
		    if (previous_char != std::char::REPLACEMENT_CHARACTER
			&& !previous_char.is_whitespace())
			|| previous_char == '“'
		    {
			'”'
		    } else {
			'“'
		    }
		} else {
		    // Leave untouched.
		    possible_match
		};
		modified_line.push(char_to_push);
		previous_char = char_to_push;
	    }
	    write!(io::stdout(), "{}\n", modified_line).unwrap();
	}
    }
}
