/// <summary>
		/// Code Settings
		/// </summary>
		/// <param name="editorMode">Editor mode</param>
		/// <param name="preElement">Html Element</param>
		/// <param name="classAttrParts">Class attribute parts dictionary</param>
		/// <param name="styleAttr">Style dictionary</param>
		/// <param name="options">Effective options dictionary</param>
		private void ApplyCodeSettings(bool editorMode, HtmlElement preElement, OrderedDictionary classAttrParts, OrderedDictionary styleAttr, EffectiveOption[] options)
		{
			EffectiveOption option = null;
			string groupName = "Code";

			// EnablePlainCodeView
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnablePlainCodeView"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["plain"] = val.ToString().ToLowerInvariant();
			}

			// PlainCodeViewDisplayTrigger
			option = options.SingleOrDefault(o => o.IsOption(groupName, "PlainCodeViewDisplayTrigger"));
			if (option != null)
			{
				PlainCodeViewDisplayMouseTrigger val = (PlainCodeViewDisplayMouseTrigger)option.Value;
				classAttrParts["show-plain"] = ((int)val).ToString(CultureInfo.InvariantCulture);
			}

			// EnablePlainCodeToggling
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnablePlainCodeToggling"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["plain-toggle"] = val.ToString().ToLowerInvariant();
			}

			// ShowPlainCodeByDefault
			option = options.SingleOrDefault(o => o.IsOption(groupName, "ShowPlainCodeByDefault"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["show-plain-default"] = val.ToString().ToLowerInvariant();
			}

			// EnableCopyPaste
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableCopyPaste"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["copy"] = val.ToString().ToLowerInvariant();
			}

			// EnableOpenInNewWindow
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableOpenInNewWindow"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["popup"] = val.ToString().ToLowerInvariant();
			}

			// AlwaysDisplayScrollbars
			option = options.SingleOrDefault(o => o.IsOption(groupName, "AlwaysDisplayScrollbars"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["scroll"] = val.ToString().ToLowerInvariant();
			}

			// MinimizeCode
			option = options.SingleOrDefault(o => o.IsOption(groupName, "MinimizeCode"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["minimize"] = val.ToString().ToLowerInvariant();
			}

			// ExpandCodeBeyondPageBorderOnMouseHover
			option = options.SingleOrDefault(o => o.IsOption(groupName, "ExpandCodeBeyondPageBorderOnMouseHover"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["expand"] = val.ToString().ToLowerInvariant();
			}

			// EnableCodeExpandingToggling
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableCodeExpandingToggling"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["expand-toggle"] = val.ToString().ToLowerInvariant();
			}

			// DecodeHtmlEntitiesInAttributes
			option = options.SingleOrDefault(o => o.IsOption(groupName, "DecodeHtmlEntitiesInAttributes"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["decode-attributes"] = val.ToString().ToLowerInvariant();
			}

			// RemoveWhitespacesSurroundingShortcodeContent
			option = options.SingleOrDefault(o => o.IsOption(groupName, "RemoveWhitespacesSurroundingShortcodeContent"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["trim-whitespace"] = val.ToString().ToLowerInvariant();
			}

			// RemoveCodeTagsSurroundingShortcodeContent
			option = options.SingleOrDefault(o => o.IsOption(groupName, "RemoveCodeTagsSurroundingShortcodeContent"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["trim-code-tag"] = val.ToString().ToLowerInvariant();
			}

			// AllowMixedLanguageHighlightingWithDelimitersAndTags
			option = options.SingleOrDefault(o => o.IsOption(groupName, "AllowMixedLanguageHighlightingWithDelimitersAndTags"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["mixed"] = val.ToString().ToLowerInvariant();
			}

			// ShowMixedLanguageIcon
			option = options.SingleOrDefault(o => o.IsOption(groupName, "ShowMixedLanguageIcon"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["show_mixed"] = val.ToString().ToLowerInvariant();
			}

			// TabSizeInSpaces
			option = options.SingleOrDefault(o => o.IsOption(groupName, "TabSizeInSpaces"));
			if (option != null)
			{
				int val = (int)option.Value;
				classAttrParts["tab-size"] = val.ToString(CultureInfo.InvariantCulture);
			}

			// BlankLinesBeforeCode
			option = options.SingleOrDefault(o => o.IsOption(groupName, "BlankLinesBeforeCode"));
			if (option != null)
			{
				int val = (int)option.Value;
				classAttrParts["whitespace-before"] = val.ToString(CultureInfo.InvariantCulture);
			}

			// BlankLinesAfterCode
			option = options.SingleOrDefault(o => o.IsOption(groupName, "BlankLinesAfterCode"));
			if (option != null)
			{
				int val = (int)option.Value;
				classAttrParts["whitespace-after"] = val.ToString(CultureInfo.InvariantCulture);
			}
		}
		/// <summary>
		/// Lines Settings
		/// </summary>
		/// <param name="editorMode">Editor mode</param>
		/// <param name="preElement">Html Element</param>
		/// <param name="classAttrParts">Class attribute parts dictionary</param>
		/// <param name="styleAttr">Style dictionary</param>
		/// <param name="options">Effective options dictionary</param>
		private void ApplyLinesSettings(bool editorMode, HtmlElement preElement, OrderedDictionary classAttrParts, OrderedDictionary styleAttr, EffectiveOption[] options)
		{
			EffectiveOption option = null;
			string groupName = "Lines";

			// StripedLines
			option = options.SingleOrDefault(o => o.IsOption(groupName, "StripedLines"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["striped"] = val.ToString().ToLowerInvariant();
			}

			// EnableLineMarking
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableLineMarking"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["marking"] = val.ToString().ToLowerInvariant();
			}

			// EnableLineRanges
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableLineRanges"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["ranges"] = val.ToString().ToLowerInvariant();
			}

			// DisplayNumbersByDefault
			option = options.SingleOrDefault(o => o.IsOption(groupName, "DisplayNumbersByDefault"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["nums"] = val.ToString().ToLowerInvariant();
			}

			// EnableLineNumberToggling
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableLineNumberToggling"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["nums-toggle"] = val.ToString().ToLowerInvariant();
			}

			// WrapLinesByDefault
			option = options.SingleOrDefault(o => o.IsOption(groupName, "WrapLinesByDefault"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["wrap"] = val.ToString().ToLowerInvariant();
			}

			// EnableLineWrapToggling
			option = options.SingleOrDefault(o => o.IsOption(groupName, "EnableLineWrapToggling"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["wrap-toggle"] = val.ToString().ToLowerInvariant();
			}

			// StartingLineNumber
			option = options.SingleOrDefault(o => o.IsOption(groupName, "StartingLineNumber"));
			if (option != null)
			{
				int val = (int)option.Value;
				classAttrParts["start-line"] = val.ToString(CultureInfo.InvariantCulture);
			}
		}
		/// <summary>
		/// ToolBar Settings
		/// </summary>
		/// <param name="editorMode">Editor mode</param>
		/// <param name="preElement">Html Element</param>
		/// <param name="classAttrParts">Class attribute parts dictionary</param>
		/// <param name="styleAttr">Style dictionary</param>
		/// <param name="options">Effective options dictionary</param>
		private void ApplyToolbarSettings(bool editorMode, HtmlElement preElement, OrderedDictionary classAttrParts, OrderedDictionary styleAttr, EffectiveOption[] options)
		{
			EffectiveOption option = null;
			string groupName = "Toolbar";

			// Display
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Display"));
			if (option != null)
			{
				ToolbarDisplay val = (ToolbarDisplay) option.Value;
				classAttrParts["toolbar"] = ((int) val).ToString(CultureInfo.InvariantCulture);
			}

			// OverlayOnCode
			option = options.SingleOrDefault(o => o.IsOption(groupName, "OverlayOnCode"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["toolbar-overlay"] = val.ToString().ToLowerInvariant();
			}

			// ToggleOnSingleClickWhenOverlayed
			option = options.SingleOrDefault(o => o.IsOption(groupName, "ToggleOnSingleClickWhenOverlayed"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["toolbar-hide"] = val.ToString().ToLowerInvariant();
			}

			// DelayHideOnMouseOut
			option = options.SingleOrDefault(o => o.IsOption(groupName, "DelayHideOnMouseOut"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["toolbar-delay"] = val.ToString().ToLowerInvariant();
			}

			// ShowTitle
			option = options.SingleOrDefault(o => o.IsOption(groupName, "ShowTitle"));
			if (option != null)
			{
				bool val = (bool)option.Value;
				classAttrParts["show-title"] = val.ToString().ToLowerInvariant();
			}

			// LanguageDisplay
			option = options.SingleOrDefault(o => o.IsOption(groupName, "LanguageDisplay"));
			if (option != null)
			{
				LanguageDisplay val = (LanguageDisplay)option.Value;
				classAttrParts["show-lang"] = ((int)val).ToString(CultureInfo.InvariantCulture);
			}
		}
		/// <summary>
		/// Metrics Settings
		/// </summary>
		/// <param name="editorMode">Editor mode</param>
		/// <param name="preElement">Html Element</param>
		/// <param name="classAttrParts">Class attribute parts dictionary</param>
		/// <param name="styleAttr">Style dictionary</param>
		/// <param name="options">Effective options dictionary</param>
		private void ApplyMetricsSettings(bool editorMode, HtmlElement preElement, OrderedDictionary classAttrParts, OrderedDictionary styleAttr, EffectiveOption[] options)
		{
			EffectiveOption option = null;
			string groupName = "Metrics";

			// Defaults
			styleAttr["box-sizing"] = "border-box";
			styleAttr["-moz-box-sizing"] = "border-box";
			styleAttr["margin"] = "0";
			styleAttr["padding"] = "0";
			styleAttr["border"] = "0 none transparent";

			// Width
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Width"));
			if (option != null)
			{
				WidthOrHeight val = option.Value as WidthOrHeight;
				if (val != null)
				{
					classAttrParts["width-set"] = "true";
					classAttrParts["width-mode"] = ((int)val.Type).ToString(CultureInfo.InvariantCulture);
					classAttrParts["width-unit"] = ((int)val.Unit).ToString(CultureInfo.InvariantCulture);

					if (val.Type == WidthOrHeightType.Min)
					{
						styleAttr["min-width"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
					else if (val.Type == WidthOrHeightType.Max)
					{
						styleAttr["max-width"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
					else
					{
						styleAttr["width"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
				}
			}

			// Height
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Height"));
			if (option != null)
			{
				WidthOrHeight val = option.Value as WidthOrHeight;
				if (val != null)
				{
					classAttrParts["height-set"] = "true";
					classAttrParts["height-mode"] = ((int)val.Type).ToString(CultureInfo.InvariantCulture);
					classAttrParts["height-unit"] = ((int)val.Unit).ToString(CultureInfo.InvariantCulture);

					if (val.Type == WidthOrHeightType.Min)
					{
						styleAttr["min-height"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
					else if (val.Type == WidthOrHeightType.Max)
					{
						styleAttr["max-height"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
					else
					{
						styleAttr["height"] = val.Value + ((val.Unit == WidthOrHeightUnit.Percent) ? "%" : "px");
					}
				}
			}

			// Margins, Paddings & Borders
			var marginTypes = new[] {"top", "right", "bottom", "left"};
			var marginOptions = marginTypes
				.Select(m => new { Type = m, Option = options.SingleOrDefault(o => o.IsOption(groupName, m.Substring(0, 1).ToUpperInvariant() + m.Substring(1) + "Margin")) })
				.Where(o => o.Option != null)
				.ToArray();
			marginOptions.ToList().ForEach(o =>
			{
				classAttrParts[o.Type + "-margin"] = ((int) o.Option.Value).ToString(CultureInfo.InvariantCulture);
				styleAttr["margin-" + o.Type] = ((int)o.Option.Value).ToString(CultureInfo.InvariantCulture) + "px";
			});

			// Horizontal Alignment
			option = options.SingleOrDefault(o => o.IsOption(groupName, "HorizontalAlignment"));
			if (option != null)
			{
				HorizontalAlignment val = (HorizontalAlignment) option.Value;
				if (val != HorizontalAlignment.None)
				{
					classAttrParts["h-align"] = ((int)val).ToString(CultureInfo.InvariantCulture);
					if (val == HorizontalAlignment.Left)
					{
						styleAttr["text-align"] = "left";
					}
					else if (val == HorizontalAlignment.Right)
					{
						styleAttr["text-align"] = "right";
					}
					else if (val == HorizontalAlignment.Center)
					{
						styleAttr["text-align"] = "center";
					}
				}
			}

			// AllowFloatingElementsToSurroundCrayon
			option = options.SingleOrDefault(o => o.IsOption(groupName, "HorizontalAlignment"));
			if (option != null)
			{
				bool val = (bool) option.Value;
				classAttrParts["float-enable"] = val.ToString().ToLowerInvariant();
			}

			// InlineMargin
			option = options.SingleOrDefault(o => o.IsOption(groupName, "InlineMargin"));
			if (option != null)
			{
				int val = (int)option.Value;
				classAttrParts["inline-margin"] = val.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
			}
		}
		/// <summary>
		/// Content Settings
		/// </summary>
		/// <param name="editorMode">Editor mode</param>
		/// <param name="preElement">Html Element</param>
		/// <param name="classAttrParts">Class attribute parts dictionary</param>
		/// <param name="styleAttr">Style dictionary</param>
		/// <param name="options">Effective options dictionary</param>
		private void ApplyContentSettings(bool editorMode, HtmlElement preElement, OrderedDictionary classAttrParts, OrderedDictionary styleAttr, EffectiveOption[] options)
		{
			EffectiveOption option = null;
			string groupName = "Content";

			// Title
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Title"));
			if (option != null)
			{
				string valText = option.Value.ToString().Trim();
				if (valText.Length > 0)
				{
					preElement.Attributes["title"] = valText;
				}
			}

			// Inline & Url
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Inline"));
			if ((option == null) || !(bool)option.Value)
			{
				option = options.SingleOrDefault(o => o.IsOption(groupName, "Url"));
				if (option != null)
				{
					string valText = option.Value.ToString().Trim();
					if (valText.Length > 0)
					{
						preElement.Attributes["data-url"] = valText;
					}
				}
			}

			// DontHighlight
			option = options.SingleOrDefault(o => o.IsOption(groupName, "DontHighlight"));
			if (option != null)
			{
				classAttrParts["highlight"] = (!((bool) option.Value)).ToString().ToLowerInvariant();
			}

			// Language
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Language"));
			if (option != null)
			{
				string valText = option.Value.ToString().Trim();
				if (valText.Length > 0)
				{
					classAttrParts["lang"] = valText;
				}
			}

			// Line Range
			option = options.SingleOrDefault(o => o.IsOption(groupName, "LineRange"));
			if (option != null)
			{
				string valText = _whiteSpaceRegex.Replace(option.Value.ToString().Trim(), string.Empty);
				if (valText.Length > 0)
				{
					classAttrParts["range"] = valText;
				}
			}

			// Marked Lines
			option = options.SingleOrDefault(o => o.IsOption(groupName, "MarkedLines"));
			if (option != null)
			{
				string valText = _whiteSpaceRegex.Replace(option.Value.ToString().Trim(), string.Empty);
				if (valText.Length > 0)
				{
					classAttrParts["mark"] = valText;
				}
			}

			// Content
			option = options.SingleOrDefault(o => o.IsOption(groupName, "Content"));
			if (option != null)
			{
				preElement.Text = option.Value.ToString().Trim();
			}

			// Theme
			option = options.SingleOrDefault(o => o.IsOption("Theme", "Name"));
			if (option != null)
			{
				string valText = option.Value.ToString().Trim();
				if (valText.Length > 0)
				{
					classAttrParts["theme"] = valText;
				}
			}

			// Font Name
			option = options.SingleOrDefault(o => o.IsOption("Font", "Name"));
			if (option != null)
			{
				string valText = option.Value.ToString().Trim();
				if (valText.Length > 0)
				{
					classAttrParts["font"] = valText;
					styleAttr["font-family"] = valText;
				}
			}

			// Font Size
			option = options.SingleOrDefault(o => o.IsOption("Font", "FontSize"));
			if (option != null)
			{
				FontSize fontSize = option.Value as FontSize;
				if (fontSize != null)
				{
					classAttrParts["font-size"] = fontSize.Size.ToString(CultureInfo.InvariantCulture);
					styleAttr["font-size"] = fontSize.Size.ToString(CultureInfo.InvariantCulture) + "px";

					classAttrParts["line-height"] = fontSize.LineHeight.ToString(CultureInfo.InvariantCulture);
					styleAttr["line-height"] = fontSize.LineHeight.ToString(CultureInfo.InvariantCulture) + "px";
				}
			}
		}
		/// <summary>
		/// Retrieves a list of all effective options
		/// </summary>
		/// <param name="contentProperties">Content properties dictionary</param>
		/// <param name="options">Plugin options dictionary</param>
		/// <returns>Effective options</returns>
		public static EffectiveOption[] GetEffectiveOptions(IProperties contentProperties, IProperties options)
		{
			// Standard options
			return ContentOnlyOptions.Union(AllOptions)
				.Select(o =>
				{
					var effectiveOption = new EffectiveOption();
					Utils.CopyProperties(o, effectiveOption);

					// Try from Content Properties, if this property is available
					if (o.HasValue(contentProperties))
					{
						effectiveOption.Value = o.GetValue(contentProperties);
						effectiveOption.Location = OptionLocation.Content;
						if (IsDefault(effectiveOption.Value))
						{
							effectiveOption.Location = OptionLocation.Default;
						}
					}
					else if (o.HasValue(options))
					{
						effectiveOption.Value = o.GetValue(options);
						effectiveOption.Location = OptionLocation.Plugin;
					}
					else
					{
						effectiveOption.Value = o.DefaultValue;
						effectiveOption.Location = OptionLocation.Default;
					}
					return effectiveOption;
				}).ToArray();
		}