From 78a003eec68e5149b8377b69e87d42af5a83076f Mon Sep 17 00:00:00 2001 From: Mads Kristensen Date: Mon, 17 Jun 2013 22:51:45 -0700 Subject: [PATCH] Initial commit --- .gitattributes | 22 + .gitignore | 215 + CssSorter.dll | Bin 0 -> 19968 bytes .../Adornments/Color/ColorAdornment.cs | 70 + .../Adornments/Color/ColorAdornmentTagger.cs | 97 + .../Color/ColorAdornmentTaggerProvider.cs | 50 + EditorExtensions/Adornments/Color/ColorTag.cs | 37 + .../Adornments/Color/ColorTagger.cs | 139 + .../Adornments/Color/ColorTaggerProvider.cs | 22 + .../Color/IntraTextAdornmentTagger.cs | 268 + .../Classifications/Base64TaggerProvider.cs | 90 + .../Classifications/BraceMatching.cs | 242 + .../Classifications/CssHighlightWordTagger.cs | 225 + .../JavaScriptArrayOutlining.cs | 244 + .../JavaScriptHighlightWordTagger.cs | 213 + .../Classifications/JavaScriptOutlining.cs | 247 + .../Classifications/JavaScriptRegionTagger.cs | 244 + .../Markdown/MarkdownClassificationTypes.cs | 77 + .../Markdown/MarkdownClassifier.cs | 70 + .../Markdown/MarkdownContentTypeDefinition.cs | 39 + .../Classifications/ModernizrClassifier.cs | 160 + .../SCSS/ScssClassifierProvider.cs | 27 + .../SCSS/ScssContentTypeDefinition.cs | 31 + .../Classifications/ValueTaggerProvider.cs | 156 + .../Classifications/VendorClassifier.cs | 235 + .../Commands/ArrowsCommandTarget.cs | 273 + .../Commands/CommandTargetBase.cs | 67 + .../Css/CssAddMissingStandardCommandTarget.cs | 105 + .../Css/CssAddVendorStandardCommandTarget.cs | 100 + .../Commands/Css/CssCreationListener.cs | 53 + .../Css/CssExtractToFileCommandTarget.cs | 118 + .../Css/CssFindReferencesCommandTarget.cs | 98 + .../Commands/Css/CssFormatCommandTarget.cs | 56 + .../Css/CssRemoveDuplicatesCommandTarget.cs | 98 + .../Commands/Css/CssSaveListener.cs | 70 + .../Commands/Css/CssSelectBrowsers.cs | 71 + .../Css/CssSortPropertiesCommandTarget.cs | 69 + .../Commands/Css/F1HelpCommandTarget.cs | 111 + .../Commands/Css/RetriggerCommandTarget.cs | 62 + EditorExtensions/Commands/Css/SpeedTyping.cs | 389 ++ EditorExtensions/Commands/FeatureEnabler.cs | 29 + .../Commands/HTML/ContractSelectionTarget.cs | 91 + .../Commands/HTML/ExpandSelectionTarget.cs | 70 + .../Commands/HTML/HtmlCreationListener.cs | 54 + .../Commands/HTML/SurroundWithTarget.cs | 90 + .../Commands/HTML/ZenCodingCommandTarget.cs | 301 ++ .../JavaScript/JavaScriptCreationListener.cs | 42 + .../JavaScriptFindReferencesCommandTarget.cs | 65 + .../JavaScript/JavaScriptSaveListener.cs | 128 + .../Commands/JavaScript/JsHintCompiler.cs | 84 + .../JavaScript/JsHintProjectRunner.cs | 64 + .../Commands/JavaScript/JsHintRunner.cs | 246 + .../JavaScriptSmartIndentCommandTarget.cs | 113 + EditorExtensions/Commands/JsDocRegistry.cs | 86 + .../Commands/LESS/LessCreationListener.cs | 27 + .../LESS/LessExtractMixinCommandTarget.cs | 61 + .../LESS/LessExtractVariableCommandTarget.cs | 73 + .../Commands/MoveRuleCommandTarget.cs | 382 ++ .../Commands/PasteJsonAsTypeScript.cs | 136 + .../Shared/EncodeSelectionCommandTarget.cs | 81 + .../Shared/MinifySelectionCommandTarget.cs | 48 + .../Commands/Shared/TextCreationListener.cs | 28 + .../CSSTypeThroughControllerProvider.cs | 84 + ...JavaScriptTypeThroughControllerProvider.cs | 76 + .../LESSTypeThroughControllerProvider.cs | 58 + .../Commands/TypeThrough/ProvisionalText.cs | 264 + .../TypeThrough/TypeThroughController.cs | 252 + .../Completion/CompletionListEntry.cs | 77 + .../AnimationNameCompletionProvider.cs | 42 + .../ClassCompletionProvider.cs | 42 + .../ColorCompletionProvider.cs | 49 + .../FontCompletionProvider.cs | 120 + .../FontFamilyCompletionProvider.cs | 57 + .../IdCompletionProvider.cs | 42 + .../ImportantCompletionProvider.cs | 34 + .../RegionCompletionProvider.cs | 44 + .../TagCompletionProvider.cs | 154 + .../UrlPickerCompletionProvider.cs | 74 + .../ContextProviders/ClassContextProvider.cs | 32 + .../ContextProviders/IdContextProvider.cs | 32 + .../LessPseudoContextProvider.cs | 43 + .../ContextProviders/TagContextProvider.cs | 32 + .../UrlPickerContextProvider.cs | 50 + .../Completion/CustomCompletionListEntry.cs | 72 + .../Filter/GradientCompletionListFilter.cs | 97 + .../HideInheritInitialCompletionListFilter.cs | 28 + .../HideUnsupportedCompletionListFilter.cs | 41 + .../WebkitScrollbarCompletionListFilter.cs | 56 + .../FontFamilyCompletionListEntry.cs | 112 + .../Completion/RegionCompletionListEntry.cs | 69 + .../UrlPickerCompletionListEntry.cs | 89 + EditorExtensions/DropTargets/BundleDrop.cs | 83 + EditorExtensions/DropTargets/FontDrop.cs | 251 + EditorExtensions/DropTargets/ImageDrop.cs | 84 + .../DropTargets/StylesheetDrop.cs | 84 + .../DropTargets/TypeScriptDrop.cs | 86 + EditorExtensions/EditorExtensions.vsct | 753 +++ EditorExtensions/EditorExtensionsPackage.cs | 227 + .../Filters/Backslash9CssErrorFilter.cs | 27 + .../ErrorTags/Filters/CustomCssErrorFilter.cs | 50 + .../Filters/MsFilterCssErrorFilter.cs | 33 + .../Filters/MsKeyframesCssErrorFilter.cs | 33 + .../ErrorTags/Filters/ScssErrorFilter.cs | 33 + .../ColorValuesInRangeErrorTagProvider.cs | 86 + .../DisplayInlineErrorTagProvider.cs | 150 + .../DuplicatePropertyErrorTagProvider.cs | 64 + .../DuplicateSelectorErrorTagProvider.cs | 112 + .../Providers/EmbedImagesErrorTagProvider.cs | 46 + .../Providers/HoverOrderErrorTagProvider.cs | 79 + .../Providers/Ie10PrefixErrorTagProvider.cs | 41 + .../InvalidVendorErrorTagProvider.cs | 126 + ...issingStandardDirectiveErrorTagProvider.cs | 47 + .../MissingVendorDirectiveErrorTagProvider.cs | 45 + .../MissingVendorErrorTagProvider.cs | 53 + .../MissingVendorPseudoErrorTagProvider.cs | 116 + .../ErrorTags/Providers/MsViewState.cs | 45 + .../OverQualifiedSelectorErrorTagProvider.cs | 44 + .../OverriddenPropertyErrorTagProvider.cs | 55 + .../Providers/ShorthandErrorTagProvider.cs | 60 + .../Providers/StarSelectorErrorTagProvider.cs | 44 + .../Providers/UnknownTagErrorTagProvider.cs | 163 + .../Providers/VendorOrderErrorTagProvider.cs | 63 + .../Providers/W3cOnlyErrorTagProvider.cs | 109 + .../Providers/ZeroUnitErrorTagProvider.cs | 46 + .../ErrorTags/SelectorErrorTag.cs | 62 + EditorExtensions/ErrorTags/SimpleErrorTag.cs | 79 + .../ExtensionMethods/AtDirectiveExtensions.cs | 64 + .../ExtensionMethods/ColorModelExtensions.cs | 56 + .../ExtensionMethods/DeclarationExtensions.cs | 62 + .../ExtensionMethods/IVsExtensions.cs | 38 + .../ExtensionMethods/PseudoExtensions.cs | 18 + EditorExtensions/GlobalSuppressions.cs | 1 + EditorExtensions/Guids.cs | 30 + EditorExtensions/HTML/Base64ChromeAction.cs | 71 + .../HTML/MathMlSchemaFileInfoProvider.cs | 33 + EditorExtensions/Helpers/CssItemCollector.cs | 36 + EditorExtensions/Helpers/FileHelpers.cs | 92 + EditorExtensions/Helpers/OptionHelpers.cs | 87 + EditorExtensions/Helpers/ProjectHelpers.cs | 229 + EditorExtensions/Helpers/VendorHelpers.cs | 139 + EditorExtensions/Key.snk | Bin 0 -> 596 bytes EditorExtensions/License.txt | 33 + EditorExtensions/Logger.cs | 59 + .../Margin/CoffeeScriptCompiler.cs | 39 + EditorExtensions/Margin/CoffeeScriptMargin.cs | 178 + EditorExtensions/Margin/CompilerError.cs | 11 + EditorExtensions/Margin/CompilerResult.cs | 16 + .../Margin/EditorMarginFactory.cs | 55 + EditorExtensions/Margin/LessCompiler.cs | 147 + EditorExtensions/Margin/LessMargin.cs | 89 + .../Margin/LessProjectCompiler.cs | 116 + EditorExtensions/Margin/MarginBase.cs | 448 ++ EditorExtensions/Margin/MarkdownMargin.cs | 150 + EditorExtensions/Margin/ScriptRunnerBase.cs | 77 + EditorExtensions/Margin/ScssMargin.cs | 158 + EditorExtensions/Margin/TypeScriptMargin.cs | 314 ++ EditorExtensions/MenuItems/BuildMenu.cs | 145 + EditorExtensions/MenuItems/BundleFiles.cs | 400 ++ EditorExtensions/MenuItems/Diff.cs | 66 + EditorExtensions/MenuItems/Encoding.cs | 62 + EditorExtensions/MenuItems/JsHint.cs | 52 + .../MenuItems/MarkdownStylesheet.cs | 45 + EditorExtensions/MenuItems/MinifyFile.cs | 224 + EditorExtensions/MenuItems/ProjectSettings.cs | 95 + EditorExtensions/MenuItems/SolutionColors.cs | 39 + EditorExtensions/MenuItems/Transform.cs | 99 + .../NavigateTo/GoToLineProviderFactory.cs | 189 + EditorExtensions/Options/CoffeeScript.cs | 72 + EditorExtensions/Options/Css.cs | 135 + EditorExtensions/Options/General.cs | 45 + EditorExtensions/Options/JavaScript.cs | 59 + EditorExtensions/Options/JsHint.cs | 466 ++ EditorExtensions/Options/Less.cs | 58 + .../Options/ProjectSettingsStore.cs | 349 ++ .../ProjectSettingsTextViewListener.cs | 36 + EditorExtensions/Options/Scss.cs | 58 + EditorExtensions/Options/TypeScript.cs | 88 + .../Options/WebEssentialsSettings.cs | 185 + EditorExtensions/PkgCmdID.cs | 58 + EditorExtensions/Properties/AssemblyInfo.cs | 35 + .../Declaration/DeclarationQuickInfo.cs | 293 ++ .../DeclarationQuickInfoController.cs | 61 + .../DeclarationQuickInfoControllerProvider.cs | 23 + .../DeclarationQuickInfoSourceProvider.cs | 26 + .../QuickInfo/Font/FontQuickInfo.cs | 106 + .../QuickInfo/Font/FontQuickInfoController.cs | 62 + .../Font/FontQuickInfoControllerProvider.cs | 23 + .../Font/FontQuickInfoSourceProvider.cs | 26 + .../QuickInfo/Image/ImageQuickInfo.cs | 159 + .../Image/ImageQuickInfoController.cs | 69 + .../Image/ImageQuickInfoControllerProvider.cs | 23 + .../Image/ImageQuickInfoSourceProvider.cs | 19 + .../QuickInfo/Selector/SelectorQuickInfo.cs | 94 + .../Selector/SelectorQuickInfoController.cs | 62 + .../SelectorQuickInfoControllerProvider.cs | 23 + .../SelectorQuickInfoSourceProvider.cs | 26 + .../QuickInfo/Selector/SelectorSpecificity.cs | 84 + .../RemoveCssSignatureHelpSource.cs | 63 + .../QuickInfo/ValueOrder/ValueOrderFactory.cs | 204 + .../ValueOrder/ValueOrderSignature.cs | 199 + .../ValueOrderSignatureHelpSource.cs | 83 + .../ValueOrderSignatureHelpSourceProvider.cs | 32 + .../QuickLaunch/Nuget/NugetSearchProvider.cs | 86 + .../QuickLaunch/Nuget/NugetSearchResult.cs | 68 + .../QuickLaunch/Nuget/NugetSearchTask.cs | 99 + .../QuickLaunch/VSGallery/VSSearchProvider.cs | 93 + .../QuickLaunch/VSGallery/VSSearchResult.cs | 68 + .../QuickLaunch/VSGallery/VSSearchTask.cs | 96 + EditorExtensions/Resources.Designer.cs | 378 ++ EditorExtensions/Resources.resx | 225 + EditorExtensions/Resources/Browsers/c.png | Bin 0 -> 1781 bytes .../Resources/Browsers/c_gray.png | Bin 0 -> 1415 bytes EditorExtensions/Resources/Browsers/ff.png | Bin 0 -> 2264 bytes .../Resources/Browsers/ff_gray.png | Bin 0 -> 1861 bytes EditorExtensions/Resources/Browsers/ie.png | Bin 0 -> 2362 bytes .../Resources/Browsers/ie_gray.png | Bin 0 -> 2023 bytes EditorExtensions/Resources/Browsers/o.png | Bin 0 -> 1881 bytes .../Resources/Browsers/o_gray.png | Bin 0 -> 1682 bytes EditorExtensions/Resources/Browsers/s.png | Bin 0 -> 2248 bytes .../Resources/Browsers/s_gray.png | Bin 0 -> 1789 bytes EditorExtensions/Resources/Images.png | Bin 0 -> 1217 bytes EditorExtensions/Resources/Package.ico | Bin 0 -> 7278 bytes .../Resources/Scripts/CoffeeScript-1.4.js | 8 + .../Scripts/IcedCoffeeScript-1.3.3.js | 8 + .../Resources/Scripts/JSDocComments.js | 185 + EditorExtensions/Resources/Scripts/jshint.js | 4538 +++++++++++++++++ .../Resources/Scripts/less-1.3.0.js | 9 + EditorExtensions/Resources/Scripts/lessc.wsf | 250 + EditorExtensions/Resources/alphabatize.png | Bin 0 -> 254 bytes EditorExtensions/Resources/cross_browser.png | Bin 0 -> 674 bytes EditorExtensions/Resources/embed.png | Bin 0 -> 768 bytes EditorExtensions/Resources/extract.png | Bin 0 -> 430 bytes EditorExtensions/Resources/graph_atdir.png | Bin 0 -> 161 bytes EditorExtensions/Resources/graph_class.png | Bin 0 -> 144 bytes EditorExtensions/Resources/graph_id.png | Bin 0 -> 207 bytes EditorExtensions/Resources/graph_parent.png | Bin 0 -> 106 bytes EditorExtensions/Resources/no_skull.png | Bin 0 -> 872 bytes EditorExtensions/Resources/nopreview.png | Bin 0 -> 3058 bytes EditorExtensions/Resources/nuget.png | Bin 0 -> 158 bytes EditorExtensions/Resources/numbers.png | Bin 0 -> 415 bytes EditorExtensions/Resources/palette.png | Bin 0 -> 724 bytes EditorExtensions/Resources/skull.png | Bin 0 -> 857 bytes EditorExtensions/Resources/sort.png | Bin 0 -> 272 bytes EditorExtensions/Resources/vsgallery.png | Bin 0 -> 122 bytes EditorExtensions/Resources/warning.png | Bin 0 -> 166 bytes .../Schemas/Browsers/BrowserSchemaFilter.cs | 46 + .../Schemas/Browsers/BrowserSelector.xaml | 19 + .../Schemas/Browsers/BrowserSelector.xaml.cs | 115 + .../Schemas/Browsers/BrowserStore.cs | 107 + .../Schemas/ColorPaletteProvider.cs | 24 + EditorExtensions/Schemas/CssSchemaUpdater.cs | 167 + EditorExtensions/Schemas/ModernizrProvider.cs | 73 + .../Schemas/W3cOnlySchemaFilter.cs | 32 + EditorExtensions/Schemas/WE-Palette.css | 28 + .../Schemas/XmlColorPaletteProvider.cs | 195 + EditorExtensions/Schemas/css-we-settings.xml | 53 + .../Actions/ColorConverterSmartTagAction.cs | 148 + .../CSS/Actions/EmbedSmartTagAction.cs | 94 + .../LessExtractVariableSmartTagAction.cs | 77 + .../Actions/MissingPseudoSmartTagAction.cs | 51 + .../MissingStandardDirectiveSmartTagAction.cs | 52 + .../Actions/MissingStandardSmartTagAction.cs | 63 + .../OverQualifySelectorSmartTagAction.cs | 41 + .../RemoveSelectorHackSmartTagAction.cs | 38 + .../CSS/Actions/ReverseEmbedSmartTagAction.cs | 138 + .../CSS/Actions/SelectorHackSmartTagAction.cs | 40 + .../CSS/Actions/SortSmartTagAction.cs | 111 + .../CSS/Actions/UpdateEmbedSmartTagAction.cs | 67 + .../Actions/VendorDirectiveSmartTagAction.cs | 48 + .../CSS/Actions/VendorOrderSmartTagAction.cs | 61 + .../CSS/Actions/VendorSmartTagAction.cs | 56 + EditorExtensions/SmartTags/CSS/CssSmartTag.cs | 13 + .../SmartTags/CSS/CssSmartTagActionBase.cs | 28 + .../SmartTags/CSS/CssSmartTagProvider.cs | 21 + .../SmartTags/CSS/CssSmartTagger.cs | 216 + .../SmartTags/CSS/ICssSmartTagProvider.cs | 15 + .../ColorConverterSmartTagProvider.cs | 126 + .../CSS/Providers/EmbedSmartTagProvider.cs | 37 + .../LessExtractVariableSmartTagProvider.cs | 77 + .../MissingPseudoSmartTagProvider.cs | 64 + ...issingStandardDirectiveSmartTagProvider.cs | 43 + .../MissingVendorDirectiveSmartTagProvider.cs | 40 + .../MissingVendorSmartTagProvider.cs | 49 + .../OverQualifiedSelectorSmartTagProvider.cs | 35 + .../Providers/ReverseEmbedSmartTagProvider.cs | 33 + .../Providers/SelectorHackSmartTagProvider.cs | 63 + .../CSS/Providers/SortSmartTagProvider.cs | 30 + .../Providers/UpdateEmbedSmartTagProvider.cs | 61 + .../Providers/VendorOrderSmartTagProvider.cs | 56 + .../HTML/HtmlConvertToFigureSmartTag.cs | 78 + .../HTML/HtmlMinifyLanguageSmartTag.cs | 72 + .../SmartTags/HTML/HtmlUnMinifySmartTag.cs | 112 + .../SolutionExplorer/CssGraphNavigator.cs | 33 + .../SolutionExplorer/CssGraphProvider.cs | 202 + .../SolutionExplorer/CssGraphSchema.cs | 67 + .../SolutionExplorer/GraphProviderBase.cs | 160 + .../SolutionExplorer/LessGraphProvider.cs | 187 + .../SolutionExplorer/LessGraphSchema.cs | 48 + .../Source.extension.vsixmanifest | 27 + EditorExtensions/VSPackage.resx | 140 + EditorExtensions/WebEssentials2012logo.png | Bin 0 -> 3027 bytes EditorExtensions/WebEssentials2013.csproj | 673 +++ EditorExtensions/app.config | 11 + EditorExtensions/packages.config | 6 + EditorExtensions/preview.png | Bin 0 -> 9087 bytes EditorExtensions/registry.pkgdef | 91 + MarkdownSharp.dll | Bin 0 -> 61440 bytes ...VisualStudio.JavaScript.Web.Extensions.dll | Bin 0 -> 102512 bytes WebEssentials2012logo.pdn | Bin 0 -> 24202 bytes WebEssentials2013.sln | 31 + ZenCoding.dll | Bin 0 -> 41472 bytes .../AjaxMin.4.67.4639.17289.nupkg | Bin 0 -> 733657 bytes .../AjaxMin.4.90.4864.13402.nupkg | Bin 0 -> 664480 bytes .../AjaxMin.4.90.4864.13402.nuspec | 19 + .../lib/net20/AjaxMin.dll | Bin 0 -> 419840 bytes .../lib/net35/AjaxMin.dll | Bin 0 -> 415232 bytes .../lib/net40/AjaxMin.dll | Bin 0 -> 425984 bytes .../tools/net40/AjaxMin.dll | Bin 0 -> 425984 bytes .../tools/net40/AjaxMin.tasks | 4 + .../tools/net40/AjaxMinTask.dll | Bin 0 -> 39424 bytes .../tools/net40/AjaxMinTask.targets | 19 + .../MarkdownSharp.1.13.0.0.nupkg | Bin 0 -> 47410 bytes .../MarkdownSharp.1.13.0.0.nuspec | 16 + .../lib/35/MarkdownSharp.dll | Bin 0 -> 62464 bytes .../lib/35/MarkdownSharp.xml | 433 ++ packages/repositories.config | 4 + 326 files changed, 32121 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 CssSorter.dll create mode 100644 EditorExtensions/Adornments/Color/ColorAdornment.cs create mode 100644 EditorExtensions/Adornments/Color/ColorAdornmentTagger.cs create mode 100644 EditorExtensions/Adornments/Color/ColorAdornmentTaggerProvider.cs create mode 100644 EditorExtensions/Adornments/Color/ColorTag.cs create mode 100644 EditorExtensions/Adornments/Color/ColorTagger.cs create mode 100644 EditorExtensions/Adornments/Color/ColorTaggerProvider.cs create mode 100644 EditorExtensions/Adornments/Color/IntraTextAdornmentTagger.cs create mode 100644 EditorExtensions/Classifications/Base64TaggerProvider.cs create mode 100644 EditorExtensions/Classifications/BraceMatching.cs create mode 100644 EditorExtensions/Classifications/CssHighlightWordTagger.cs create mode 100644 EditorExtensions/Classifications/JavaScriptArrayOutlining.cs create mode 100644 EditorExtensions/Classifications/JavaScriptHighlightWordTagger.cs create mode 100644 EditorExtensions/Classifications/JavaScriptOutlining.cs create mode 100644 EditorExtensions/Classifications/JavaScriptRegionTagger.cs create mode 100644 EditorExtensions/Classifications/Markdown/MarkdownClassificationTypes.cs create mode 100644 EditorExtensions/Classifications/Markdown/MarkdownClassifier.cs create mode 100644 EditorExtensions/Classifications/Markdown/MarkdownContentTypeDefinition.cs create mode 100644 EditorExtensions/Classifications/ModernizrClassifier.cs create mode 100644 EditorExtensions/Classifications/SCSS/ScssClassifierProvider.cs create mode 100644 EditorExtensions/Classifications/SCSS/ScssContentTypeDefinition.cs create mode 100644 EditorExtensions/Classifications/ValueTaggerProvider.cs create mode 100644 EditorExtensions/Classifications/VendorClassifier.cs create mode 100644 EditorExtensions/Commands/ArrowsCommandTarget.cs create mode 100644 EditorExtensions/Commands/CommandTargetBase.cs create mode 100644 EditorExtensions/Commands/Css/CssAddMissingStandardCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssAddVendorStandardCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssCreationListener.cs create mode 100644 EditorExtensions/Commands/Css/CssExtractToFileCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssFindReferencesCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssFormatCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssRemoveDuplicatesCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/CssSaveListener.cs create mode 100644 EditorExtensions/Commands/Css/CssSelectBrowsers.cs create mode 100644 EditorExtensions/Commands/Css/CssSortPropertiesCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/F1HelpCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/RetriggerCommandTarget.cs create mode 100644 EditorExtensions/Commands/Css/SpeedTyping.cs create mode 100644 EditorExtensions/Commands/FeatureEnabler.cs create mode 100644 EditorExtensions/Commands/HTML/ContractSelectionTarget.cs create mode 100644 EditorExtensions/Commands/HTML/ExpandSelectionTarget.cs create mode 100644 EditorExtensions/Commands/HTML/HtmlCreationListener.cs create mode 100644 EditorExtensions/Commands/HTML/SurroundWithTarget.cs create mode 100644 EditorExtensions/Commands/HTML/ZenCodingCommandTarget.cs create mode 100644 EditorExtensions/Commands/JavaScript/JavaScriptCreationListener.cs create mode 100644 EditorExtensions/Commands/JavaScript/JavaScriptFindReferencesCommandTarget.cs create mode 100644 EditorExtensions/Commands/JavaScript/JavaScriptSaveListener.cs create mode 100644 EditorExtensions/Commands/JavaScript/JsHintCompiler.cs create mode 100644 EditorExtensions/Commands/JavaScript/JsHintProjectRunner.cs create mode 100644 EditorExtensions/Commands/JavaScript/JsHintRunner.cs create mode 100644 EditorExtensions/Commands/JavaScriptSmartIndentCommandTarget.cs create mode 100644 EditorExtensions/Commands/JsDocRegistry.cs create mode 100644 EditorExtensions/Commands/LESS/LessCreationListener.cs create mode 100644 EditorExtensions/Commands/LESS/LessExtractMixinCommandTarget.cs create mode 100644 EditorExtensions/Commands/LESS/LessExtractVariableCommandTarget.cs create mode 100644 EditorExtensions/Commands/MoveRuleCommandTarget.cs create mode 100644 EditorExtensions/Commands/PasteJsonAsTypeScript.cs create mode 100644 EditorExtensions/Commands/Shared/EncodeSelectionCommandTarget.cs create mode 100644 EditorExtensions/Commands/Shared/MinifySelectionCommandTarget.cs create mode 100644 EditorExtensions/Commands/Shared/TextCreationListener.cs create mode 100644 EditorExtensions/Commands/TypeThrough/CSSTypeThroughControllerProvider.cs create mode 100644 EditorExtensions/Commands/TypeThrough/JavaScriptTypeThroughControllerProvider.cs create mode 100644 EditorExtensions/Commands/TypeThrough/LESSTypeThroughControllerProvider.cs create mode 100644 EditorExtensions/Commands/TypeThrough/ProvisionalText.cs create mode 100644 EditorExtensions/Commands/TypeThrough/TypeThroughController.cs create mode 100644 EditorExtensions/Completion/CompletionListEntry.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/AnimationNameCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/ClassCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/ColorCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/FontCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/FontFamilyCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/IdCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/ImportantCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/RegionCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/TagCompletionProvider.cs create mode 100644 EditorExtensions/Completion/CompletionProviders/UrlPickerCompletionProvider.cs create mode 100644 EditorExtensions/Completion/ContextProviders/ClassContextProvider.cs create mode 100644 EditorExtensions/Completion/ContextProviders/IdContextProvider.cs create mode 100644 EditorExtensions/Completion/ContextProviders/LessPseudoContextProvider.cs create mode 100644 EditorExtensions/Completion/ContextProviders/TagContextProvider.cs create mode 100644 EditorExtensions/Completion/ContextProviders/UrlPickerContextProvider.cs create mode 100644 EditorExtensions/Completion/CustomCompletionListEntry.cs create mode 100644 EditorExtensions/Completion/Filter/GradientCompletionListFilter.cs create mode 100644 EditorExtensions/Completion/Filter/HideInheritInitialCompletionListFilter.cs create mode 100644 EditorExtensions/Completion/Filter/HideUnsupportedCompletionListFilter.cs create mode 100644 EditorExtensions/Completion/Filter/WebkitScrollbarCompletionListFilter.cs create mode 100644 EditorExtensions/Completion/FontFamilyCompletionListEntry.cs create mode 100644 EditorExtensions/Completion/RegionCompletionListEntry.cs create mode 100644 EditorExtensions/Completion/UrlPickerCompletionListEntry.cs create mode 100644 EditorExtensions/DropTargets/BundleDrop.cs create mode 100644 EditorExtensions/DropTargets/FontDrop.cs create mode 100644 EditorExtensions/DropTargets/ImageDrop.cs create mode 100644 EditorExtensions/DropTargets/StylesheetDrop.cs create mode 100644 EditorExtensions/DropTargets/TypeScriptDrop.cs create mode 100644 EditorExtensions/EditorExtensions.vsct create mode 100644 EditorExtensions/EditorExtensionsPackage.cs create mode 100644 EditorExtensions/ErrorTags/Filters/Backslash9CssErrorFilter.cs create mode 100644 EditorExtensions/ErrorTags/Filters/CustomCssErrorFilter.cs create mode 100644 EditorExtensions/ErrorTags/Filters/MsFilterCssErrorFilter.cs create mode 100644 EditorExtensions/ErrorTags/Filters/MsKeyframesCssErrorFilter.cs create mode 100644 EditorExtensions/ErrorTags/Filters/ScssErrorFilter.cs create mode 100644 EditorExtensions/ErrorTags/Providers/ColorValuesInRangeErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/DisplayInlineErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/DuplicatePropertyErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/DuplicateSelectorErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/EmbedImagesErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/HoverOrderErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/Ie10PrefixErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/InvalidVendorErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/MissingStandardDirectiveErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/MissingVendorDirectiveErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/MissingVendorErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/MissingVendorPseudoErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/MsViewState.cs create mode 100644 EditorExtensions/ErrorTags/Providers/OverQualifiedSelectorErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/OverriddenPropertyErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/ShorthandErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/StarSelectorErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/UnknownTagErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/VendorOrderErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/W3cOnlyErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/Providers/ZeroUnitErrorTagProvider.cs create mode 100644 EditorExtensions/ErrorTags/SelectorErrorTag.cs create mode 100644 EditorExtensions/ErrorTags/SimpleErrorTag.cs create mode 100644 EditorExtensions/ExtensionMethods/AtDirectiveExtensions.cs create mode 100644 EditorExtensions/ExtensionMethods/ColorModelExtensions.cs create mode 100644 EditorExtensions/ExtensionMethods/DeclarationExtensions.cs create mode 100644 EditorExtensions/ExtensionMethods/IVsExtensions.cs create mode 100644 EditorExtensions/ExtensionMethods/PseudoExtensions.cs create mode 100644 EditorExtensions/GlobalSuppressions.cs create mode 100644 EditorExtensions/Guids.cs create mode 100644 EditorExtensions/HTML/Base64ChromeAction.cs create mode 100644 EditorExtensions/HTML/MathMlSchemaFileInfoProvider.cs create mode 100644 EditorExtensions/Helpers/CssItemCollector.cs create mode 100644 EditorExtensions/Helpers/FileHelpers.cs create mode 100644 EditorExtensions/Helpers/OptionHelpers.cs create mode 100644 EditorExtensions/Helpers/ProjectHelpers.cs create mode 100644 EditorExtensions/Helpers/VendorHelpers.cs create mode 100644 EditorExtensions/Key.snk create mode 100644 EditorExtensions/License.txt create mode 100644 EditorExtensions/Logger.cs create mode 100644 EditorExtensions/Margin/CoffeeScriptCompiler.cs create mode 100644 EditorExtensions/Margin/CoffeeScriptMargin.cs create mode 100644 EditorExtensions/Margin/CompilerError.cs create mode 100644 EditorExtensions/Margin/CompilerResult.cs create mode 100644 EditorExtensions/Margin/EditorMarginFactory.cs create mode 100644 EditorExtensions/Margin/LessCompiler.cs create mode 100644 EditorExtensions/Margin/LessMargin.cs create mode 100644 EditorExtensions/Margin/LessProjectCompiler.cs create mode 100644 EditorExtensions/Margin/MarginBase.cs create mode 100644 EditorExtensions/Margin/MarkdownMargin.cs create mode 100644 EditorExtensions/Margin/ScriptRunnerBase.cs create mode 100644 EditorExtensions/Margin/ScssMargin.cs create mode 100644 EditorExtensions/Margin/TypeScriptMargin.cs create mode 100644 EditorExtensions/MenuItems/BuildMenu.cs create mode 100644 EditorExtensions/MenuItems/BundleFiles.cs create mode 100644 EditorExtensions/MenuItems/Diff.cs create mode 100644 EditorExtensions/MenuItems/Encoding.cs create mode 100644 EditorExtensions/MenuItems/JsHint.cs create mode 100644 EditorExtensions/MenuItems/MarkdownStylesheet.cs create mode 100644 EditorExtensions/MenuItems/MinifyFile.cs create mode 100644 EditorExtensions/MenuItems/ProjectSettings.cs create mode 100644 EditorExtensions/MenuItems/SolutionColors.cs create mode 100644 EditorExtensions/MenuItems/Transform.cs create mode 100644 EditorExtensions/NavigateTo/GoToLineProviderFactory.cs create mode 100644 EditorExtensions/Options/CoffeeScript.cs create mode 100644 EditorExtensions/Options/Css.cs create mode 100644 EditorExtensions/Options/General.cs create mode 100644 EditorExtensions/Options/JavaScript.cs create mode 100644 EditorExtensions/Options/JsHint.cs create mode 100644 EditorExtensions/Options/Less.cs create mode 100644 EditorExtensions/Options/ProjectSettingsStore.cs create mode 100644 EditorExtensions/Options/ProjectSettingsTextViewListener.cs create mode 100644 EditorExtensions/Options/Scss.cs create mode 100644 EditorExtensions/Options/TypeScript.cs create mode 100644 EditorExtensions/Options/WebEssentialsSettings.cs create mode 100644 EditorExtensions/PkgCmdID.cs create mode 100644 EditorExtensions/Properties/AssemblyInfo.cs create mode 100644 EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfo.cs create mode 100644 EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoController.cs create mode 100644 EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoControllerProvider.cs create mode 100644 EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoSourceProvider.cs create mode 100644 EditorExtensions/QuickInfo/Font/FontQuickInfo.cs create mode 100644 EditorExtensions/QuickInfo/Font/FontQuickInfoController.cs create mode 100644 EditorExtensions/QuickInfo/Font/FontQuickInfoControllerProvider.cs create mode 100644 EditorExtensions/QuickInfo/Font/FontQuickInfoSourceProvider.cs create mode 100644 EditorExtensions/QuickInfo/Image/ImageQuickInfo.cs create mode 100644 EditorExtensions/QuickInfo/Image/ImageQuickInfoController.cs create mode 100644 EditorExtensions/QuickInfo/Image/ImageQuickInfoControllerProvider.cs create mode 100644 EditorExtensions/QuickInfo/Image/ImageQuickInfoSourceProvider.cs create mode 100644 EditorExtensions/QuickInfo/Selector/SelectorQuickInfo.cs create mode 100644 EditorExtensions/QuickInfo/Selector/SelectorQuickInfoController.cs create mode 100644 EditorExtensions/QuickInfo/Selector/SelectorQuickInfoControllerProvider.cs create mode 100644 EditorExtensions/QuickInfo/Selector/SelectorQuickInfoSourceProvider.cs create mode 100644 EditorExtensions/QuickInfo/Selector/SelectorSpecificity.cs create mode 100644 EditorExtensions/QuickInfo/ValueOrder/RemoveCssSignatureHelpSource.cs create mode 100644 EditorExtensions/QuickInfo/ValueOrder/ValueOrderFactory.cs create mode 100644 EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignature.cs create mode 100644 EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSource.cs create mode 100644 EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSourceProvider.cs create mode 100644 EditorExtensions/QuickLaunch/Nuget/NugetSearchProvider.cs create mode 100644 EditorExtensions/QuickLaunch/Nuget/NugetSearchResult.cs create mode 100644 EditorExtensions/QuickLaunch/Nuget/NugetSearchTask.cs create mode 100644 EditorExtensions/QuickLaunch/VSGallery/VSSearchProvider.cs create mode 100644 EditorExtensions/QuickLaunch/VSGallery/VSSearchResult.cs create mode 100644 EditorExtensions/QuickLaunch/VSGallery/VSSearchTask.cs create mode 100644 EditorExtensions/Resources.Designer.cs create mode 100644 EditorExtensions/Resources.resx create mode 100644 EditorExtensions/Resources/Browsers/c.png create mode 100644 EditorExtensions/Resources/Browsers/c_gray.png create mode 100644 EditorExtensions/Resources/Browsers/ff.png create mode 100644 EditorExtensions/Resources/Browsers/ff_gray.png create mode 100644 EditorExtensions/Resources/Browsers/ie.png create mode 100644 EditorExtensions/Resources/Browsers/ie_gray.png create mode 100644 EditorExtensions/Resources/Browsers/o.png create mode 100644 EditorExtensions/Resources/Browsers/o_gray.png create mode 100644 EditorExtensions/Resources/Browsers/s.png create mode 100644 EditorExtensions/Resources/Browsers/s_gray.png create mode 100644 EditorExtensions/Resources/Images.png create mode 100644 EditorExtensions/Resources/Package.ico create mode 100644 EditorExtensions/Resources/Scripts/CoffeeScript-1.4.js create mode 100644 EditorExtensions/Resources/Scripts/IcedCoffeeScript-1.3.3.js create mode 100644 EditorExtensions/Resources/Scripts/JSDocComments.js create mode 100644 EditorExtensions/Resources/Scripts/jshint.js create mode 100644 EditorExtensions/Resources/Scripts/less-1.3.0.js create mode 100644 EditorExtensions/Resources/Scripts/lessc.wsf create mode 100644 EditorExtensions/Resources/alphabatize.png create mode 100644 EditorExtensions/Resources/cross_browser.png create mode 100644 EditorExtensions/Resources/embed.png create mode 100644 EditorExtensions/Resources/extract.png create mode 100644 EditorExtensions/Resources/graph_atdir.png create mode 100644 EditorExtensions/Resources/graph_class.png create mode 100644 EditorExtensions/Resources/graph_id.png create mode 100644 EditorExtensions/Resources/graph_parent.png create mode 100644 EditorExtensions/Resources/no_skull.png create mode 100644 EditorExtensions/Resources/nopreview.png create mode 100644 EditorExtensions/Resources/nuget.png create mode 100644 EditorExtensions/Resources/numbers.png create mode 100644 EditorExtensions/Resources/palette.png create mode 100644 EditorExtensions/Resources/skull.png create mode 100644 EditorExtensions/Resources/sort.png create mode 100644 EditorExtensions/Resources/vsgallery.png create mode 100644 EditorExtensions/Resources/warning.png create mode 100644 EditorExtensions/Schemas/Browsers/BrowserSchemaFilter.cs create mode 100644 EditorExtensions/Schemas/Browsers/BrowserSelector.xaml create mode 100644 EditorExtensions/Schemas/Browsers/BrowserSelector.xaml.cs create mode 100644 EditorExtensions/Schemas/Browsers/BrowserStore.cs create mode 100644 EditorExtensions/Schemas/ColorPaletteProvider.cs create mode 100644 EditorExtensions/Schemas/CssSchemaUpdater.cs create mode 100644 EditorExtensions/Schemas/ModernizrProvider.cs create mode 100644 EditorExtensions/Schemas/W3cOnlySchemaFilter.cs create mode 100644 EditorExtensions/Schemas/WE-Palette.css create mode 100644 EditorExtensions/Schemas/XmlColorPaletteProvider.cs create mode 100644 EditorExtensions/Schemas/css-we-settings.xml create mode 100644 EditorExtensions/SmartTags/CSS/Actions/ColorConverterSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/EmbedSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/LessExtractVariableSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/MissingPseudoSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/MissingStandardDirectiveSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/MissingStandardSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/OverQualifySelectorSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/RemoveSelectorHackSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/ReverseEmbedSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/SelectorHackSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/SortSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/UpdateEmbedSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/VendorDirectiveSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/VendorOrderSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/Actions/VendorSmartTagAction.cs create mode 100644 EditorExtensions/SmartTags/CSS/CssSmartTag.cs create mode 100644 EditorExtensions/SmartTags/CSS/CssSmartTagActionBase.cs create mode 100644 EditorExtensions/SmartTags/CSS/CssSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/CssSmartTagger.cs create mode 100644 EditorExtensions/SmartTags/CSS/ICssSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/ColorConverterSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/EmbedSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/LessExtractVariableSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/MissingPseudoSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/MissingStandardDirectiveSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/MissingVendorDirectiveSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/MissingVendorSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/OverQualifiedSelectorSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/ReverseEmbedSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/SelectorHackSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/SortSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/UpdateEmbedSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/CSS/Providers/VendorOrderSmartTagProvider.cs create mode 100644 EditorExtensions/SmartTags/HTML/HtmlConvertToFigureSmartTag.cs create mode 100644 EditorExtensions/SmartTags/HTML/HtmlMinifyLanguageSmartTag.cs create mode 100644 EditorExtensions/SmartTags/HTML/HtmlUnMinifySmartTag.cs create mode 100644 EditorExtensions/SolutionExplorer/CssGraphNavigator.cs create mode 100644 EditorExtensions/SolutionExplorer/CssGraphProvider.cs create mode 100644 EditorExtensions/SolutionExplorer/CssGraphSchema.cs create mode 100644 EditorExtensions/SolutionExplorer/GraphProviderBase.cs create mode 100644 EditorExtensions/SolutionExplorer/LessGraphProvider.cs create mode 100644 EditorExtensions/SolutionExplorer/LessGraphSchema.cs create mode 100644 EditorExtensions/Source.extension.vsixmanifest create mode 100644 EditorExtensions/VSPackage.resx create mode 100644 EditorExtensions/WebEssentials2012logo.png create mode 100644 EditorExtensions/WebEssentials2013.csproj create mode 100644 EditorExtensions/app.config create mode 100644 EditorExtensions/packages.config create mode 100644 EditorExtensions/preview.png create mode 100644 EditorExtensions/registry.pkgdef create mode 100644 MarkdownSharp.dll create mode 100644 Microsoft.VisualStudio.JavaScript.Web.Extensions.dll create mode 100644 WebEssentials2012logo.pdn create mode 100644 WebEssentials2013.sln create mode 100644 ZenCoding.dll create mode 100644 packages/AjaxMin.4.67.4639.17289/AjaxMin.4.67.4639.17289.nupkg create mode 100644 packages/AjaxMin.4.90.4864.13402/AjaxMin.4.90.4864.13402.nupkg create mode 100644 packages/AjaxMin.4.90.4864.13402/AjaxMin.4.90.4864.13402.nuspec create mode 100644 packages/AjaxMin.4.90.4864.13402/lib/net20/AjaxMin.dll create mode 100644 packages/AjaxMin.4.90.4864.13402/lib/net35/AjaxMin.dll create mode 100644 packages/AjaxMin.4.90.4864.13402/lib/net40/AjaxMin.dll create mode 100644 packages/AjaxMin.4.90.4864.13402/tools/net40/AjaxMin.dll create mode 100644 packages/AjaxMin.4.90.4864.13402/tools/net40/AjaxMin.tasks create mode 100644 packages/AjaxMin.4.90.4864.13402/tools/net40/AjaxMinTask.dll create mode 100644 packages/AjaxMin.4.90.4864.13402/tools/net40/AjaxMinTask.targets create mode 100644 packages/MarkdownSharp.1.13.0.0/MarkdownSharp.1.13.0.0.nupkg create mode 100644 packages/MarkdownSharp.1.13.0.0/MarkdownSharp.1.13.0.0.nuspec create mode 100644 packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.dll create mode 100644 packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.xml create mode 100644 packages/repositories.config diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b9d6bd92f --- /dev/null +++ b/.gitignore @@ -0,0 +1,215 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg diff --git a/CssSorter.dll b/CssSorter.dll new file mode 100644 index 0000000000000000000000000000000000000000..fb8ae830683b69db6c120c6738372000f777e54f GIT binary patch literal 19968 zcmeHv3wT_`mFBs(-z{}pt+ph~vaA+HSV(TkwrsGCF_z^A0zbf#Z5$iqR`-?McB`*c z-Lfr1j2v(hmZt-RR~#^p5D(!skOvbS@C+o&ta&ZTCWK5DlaK^L0u0M+HVH8Qsp_k~ zt%u|9+i$;bzi*~ZpZnLTQ>RXyI(4e5ea)KB-9!!|a^m~hXGGt_lRrx(JvkXhb+G0i zg7l>C#oF&_t6!|`+@8!t`i0pmVttW#ES)y9k!~X*2GfybI&k9s#BD3)6hu#Yr3=?_T5u-o%5EX;BAWk%Gblu6y5$Lnkdr>~$R&L4~d$K4$ zw;Tj@a;&i1{)rH6YZ4iOu9a=W08V`EicnmN|C)r6G9k#e(mnXHuGRS3K1+#~*@_b0 zgYol+RqEuTC+84djjvB~^W>t4<@!8tJfwa6#9hBWvG~>hF?3g;V_?hi>P3%)etq7b zFMRl_FMM14vgq}d!*{-X<6k~({;ch$z@hse{QV<63p;`OAYU9cT~OljdRaSyuav?yRVIWT~xik@P9SzzbW?3 zyQWpXKK<>jzkcaomi^)Sz(v#b%S(y;4X5dj&*wmSeV92tdi`WP!7t-SrW~}sf@{LF zb!x(3G@_7W5Du<-fQjFI9Y1DG(d(x`%xzY3yUV$CRIg|##~-5bYzLWW2zQ4Z^&SMG z-zgtOZcqJGh|cmkoKx$ofEpb2hzNJFQ$7L?foAh+Co>Ghe_QiDxw zimgqw$ZDgPHP{qK?LxEiLKO{`{8mS~IUTBN8k&kM*wr${Il>KCu&W7!whEB8Af&B^ z4NURd9uzA=g~A zENhUyufx1y*@pCy4s^XiuUTY9(A4iPo8!~V-DWL2Z!)F}ZJcyHo|xHDZ7Q!vZyL<2 zX*lGosOdW7n^F@w(<3w>-KBv|P;0ZO>I}u(k*c~~B z0bGxO(ERRl0Z#wD?h1iW#&e3mDDbQljq*8FER@eG(I%hMM2CDW+8#n}pk#To@Bi!BP2i2()5 z#kC4lhzAvzBA!v8QoO9dRPkE{s)R$AeN7X!3RH`86qqj7DNrK}1tMZdfm(5+0;h?) z6qq57C~&%XN`X4@69vu?A1W|Y1RS!jdeNxBnPQ;=4Pui5jbgU~v&2CKqT(S1n#A)8 zG>bPBm@Ph0V2-G9O3iacs{$=zivsh+eg)=>2NgI=yr{t0;vEGRh>%M*UnmwTut>xd zI7bXAuvi>Y;9PM`fhFQ?1}@HM3G0fS}Eoz zuu5!F;CykV0`1~K1uhUTC~%>8UxC%4!YiAv5$7ndR>T!pCvH^WB5_oKi^YcutQRwU zvQ>vzs6eN9Sb+`VWd$~h4;9!Xs{K;<60t&o&0;`-&xu0{Y!OEl*eXsaaH+s4gCqPh zQKvwcSf{`?VJHw20}6DDYZZu#2NXz%qY4<}H3fRaUliySRmD>Cc5$u(NpYb9JH!?R zc8V(%NQt`?=o3#VkQOg1V2bw@=oga$QsIDTR6vN$3S`871+wCZ0)yh10=vW;3hWji zE3ij|gHq3sn5n>C(Wb!VVnBf_#BBlD6`@qC4EVtk*%2N^%E@K+c=qwvj)UsU)O#wQfMmGS!uf0eN#B>P1I zB~hmE?TlwCdkm%?{3zE$C`F+QsBA;xbj{B_3vN8!5}SCz`X?qS@l@L|Sl z6uy^nM&bJyA5!>!#;+>;0OJo8{s!Z^u+;e=<24F@lkrZ4k1#%<@ZT}ML*a)QA5r*Q zjE^ad{e#3C3O~a5V}&1O9GEQodW`W5g&${pj>3P>xJ%(D7+`A z86TB6Q-?jgzKFMJYZGtK2XSoBCV%Q^SXqAts&#WF3)O=_NERCWI{ybfd?sns&>nlc z_z85%CXV_uAuUdD8B%_K20J>=3hoMX7C^DrjN(yl;^gW#o0-f8+2_RRAsU+esT=13 zcLpbU|1h&8zaE`5?!$pWN#IoL&a|)uvn0P>heTkk>iMi1_Nj)I-0&=J$SldPcc3Ak zg!bW(qNH&8b!X0IDP~E22G481kLSK(%NiW^+?jT; zhM6V#^%z|vADJ7?3%PaC0$z`yB6BsDTp^dqlWDF2saV444xF{jS;zHmlr938vN`PW z0?*`{iS-duGc6ezC=90~<0YWz%1969}A zpC0nnPlCN+zc1ttdCX35&j1u}Bg8}g`VA(JT)*mw@vN zpSc+iEC;QG?_3#rwnf9piR`|Pz}Ij>DDyeU=6!ARY;i?q3+e(MpYp5E+=}A9faTT* zyY*7AhM6V#yucgl(O08+87jj51z%&|`OPjaA@Jq$Gq<5M<-Gk|<+QmK*B0s4ip}sa zZZIJ?Uq;;=_7!tC<~U*IctV~EdA1K1g^J2$Cb&0LRAI)r8?PSn)??)Eun&`iwwsj~ zQBYp=*}dpjUc5wk(GM^Bl^4Cri^_+W(W3$7!>{OrweW0osy?`YpQZZXLVo)7L99EO z%_`t}s=}SOA5X+sDASE6(%Wo2_605fK}|0AFiY}f?%`i3{KbtmUNZqumlrwA6hPS3n7{()11$E6-y%lMG;qKx z{$Sy-(jz}2`2eQ>Zx zZ$_lMFh{Q3cpGvtUP1%=)z3QC?y{`of@K>2TA}QwUGth|H?_=enS_k?au`Fd`YUKxe zg0`vRUY`#cl>S`TLgiopA}IJiN|{2Uzt=M_*lIW(@_rZMMf&>)?sH|l=+o&FMN*r7T6)FA09 zNqZ!{QqtQceL~WgBy~G~3;C&%);qavtE2N#`w2KmAzJf0Z=g;@)dq z2SDdanw9ixplDGO$UXu zb6!@lQ$kay5qXkJ8h#?3FG~(+=Q(N5m3U@KXrnASX%b5B(JatP?K}$6ty(|meXf7g zLUh9A)weTY%qymgY)lX%`{do<5E14$=~B zBS!Q=uCx{<4_z~Z>y%C}9h9Z7dV94k*r9LFm3C=ylxc!cX$pN`+If)v;^}l$(hqZ`Mc$1xm0rq~hES@at#S+p=@suaj%oB?-YH$X^;MI+mmOzrkTlBSr6Y>F_;A{>AhOJw%%&jY*o6bU@M}N%u>7 zjid)9y#us`4oiGQ(#Iuz3iL600rWfcDrhskF6m^sdL{$6VD&J6vRqZua+o83GVyAd zMOCi7+Bj3Ck+O?oZR`m?(QRP!v9xJ|Fs*pgbU%5#B!rgn~Jy}p>v_w?uswJn~M z-mYEg5&ClI*{^Tb9`$@lU!B9>_B^b&YEOHP>z$IbHOGI;^8qB^@{~E|(Yu}#u;C+5 zv*R85p0^Y9zj>SWL{9P}Puk(565m~pr0jh_S~8$r;Je!~q;2%I(0*_p!oJ2H^U;@m z4?9xQKiQmy8-4%exPl(=z2Uf;p78zAaUDJ5`>W%i_Afqi`sf2-AAJHkpn3h*5ckgh zInD2O?$_%5B~JFk6yRomjq`}M!GD+Iaczgc8M7n&&H7W)o?B$^x5$3KCi}f#_V_K? z{~ADvb7SI2&BY0+`#akOow<5JI$WvgFEKl2rT*lG7=(mEnTWL(dG1WR})UZuYz7hzXC0y8K7b61FfPfKxatWC~1r2pF>{& zzfE#FB;A4)(?mPzIoDFDxmD7br28d3Ea@>xPe`h1Y(uT2OC@cUbep6xN%u>7SkhyX zzNvF7axjfZx>V9_k`7CHkEG8^`lh7hl=6}eYmaFEsQpy?y*A%*xnrjD4(DsmKjSE^ zV;wt@C5UEgt3V&ucB6!@@YO+eWMCI?5onmYwWQXsWwd*>OZ7ea{rXS!-|5|s2OLj0 zUUR(d_{b4=?r`pLUg`Xj^QiMV=UdKqo&V}|y8JHZFy{;P;pg|UBg#`}j>omQFyOTeq1DMumXsn|lZ*>9WA@~7o z+)aiuBd9Bxj;96_M%(seDj|$CHSx$u_Q101jm%&wtID)kwqCNct7};-z7xmbl}RI& zAf+?cA+0j9*0|Tk`V20wHAP=6mE3D2B*$h>PBLjIn{36VxHM#CGL@3OV?e%& z+E=6p`wS85P8k?6``k7$nK6vHlGBkLN*Nv74MWY+Y9o`e%@cev7)y0z2NOxNX_L|2 zv|>-zNN3pHHYskTrjyZngbz;s@tuXk@8rL%ZcXeM%w$&^>E7&iQrC%O&k*g3r3MWe zJsk+7Tx{&2Axh+f%#Je@hs7y2TcBggWMd+Wvg$zwQq%gubT-*%G;K5ln~uq&&X_<* zti(G8#%@#WY|Y|o(><6qthicl^l+dJ+hr(HFB1#_DGb;tIJKlT%_4#cQTdC+FWj_ zli4GdHEe@KBC)ay7F25@kqcQe`@2>QU|~Q}jwO|gWCrol!4a6*lthFpuF+}A{L{7_ z0Zr}cgt2E`4|NQ7XXJgFm`|M|*(Y1l;?XO2Nq1M*Y>Ly$!E}7vTx#n$eesfoU0rRl z_;y&EHq%3W=3r)xk=<@4mK!Of7o(Uzz8YlhQ)zvcJ*AJYX)YyBP1o7uw{JPM)(ggO zJ@3?7FQhh1L7$P%(u(x1q%hMG^JcKt*u6TLHsr*})P$uPk7elsGnwYCO>RusX7cG# za@1CqSRYIG8o6A~`K|-$leOk>W@Nvid^Y5Il@~cIQpO(MJMtT#%=9cXvK{5(Uhb1Q z43h^i6f4csrtJnc(GE;HHcD<>kn!8si3I8s`34AM$y+wW;Vef%oo1^Lv7xb!p38w3 zJ2g)yCTQM$YR!!an#WJAc@MQ`)()mp>%^w*$*j@QAB!7uMJcuUN#qgDnN8x<)XvGB z8!{WQ)Uns+!vbg}Z|qs*P07!dkh9jwtw2S9h55{}-sm%T8LMNNY=_a8jGHM=6>5Ky z@uzmfWrH}2Kxb<_ZuDnqy|D{>mNBxmtCQC%Bb%F2KCj4_85B6cs1Rr~vE7l3G#O!? z=1wCm5lgP?H_~l`A~m#3u#=e8+JjN7NGD_=w>PWt&+a=3M>c%sLZR&6% z*P5tf&4RRWp4$)IaoqB>BIcPW!IGl5)ER>;*)+stuf4EP3z@V_>Qb$CLvA!D%3~OZ zJ4Bj~^(WacW$X*KoxQdf-!#0W1^QqI7Jw{MnY|Q+ee6-KvXGniuU1u9WB0aJQCMgB zUYo>zNJtN|1yoU39_h7eG~d>5_2{~So-0S!j`SVwljDriZafnh-*))T;%$eQt;o?J z8I#^BlvKO|$)daj1?)96$)rK_!TwJ}H&qpu3#=GZmqE)R85`P|x;W;ABM9+TJzA%U z2=Boh8)&b|__tz_s@Y3ciQ|C%6qnW^5^4%-RUf<_`lU9lvamis>d`ee%SW}b*)5|n zZ%Z!HY76^N+yXyMAYtos0ts8+qpY&URb65K`I-V7P9kNq<0MixTdE3sX|VlwX9*8A+_C4E`px&<-m~EIXr! zan3L~>E`jJ?Q>foKfh3(OV*6AW-CLC>ZRpmttPN+R2(L;N5zm44H`Z3`5Ioeyy6Ac zE#yYUSfL!}oxdezTg9WI!>&u^m|RXdi5%~U{rK|ErcJO8^Lj^HZ}+WDYE*xP^I?;l zFsf`aqjYh+37MOPJP(Zczp-#O$3~b<=LFF>!DvnzClj=pQ)o@02lBCHvkBQ%oi%zf zKAt^3=}@Kz5s|{&@X2HmW{T^0=TD%toG!uNHd-F&L|qK6GT2MlM}2rRe~pYMZo@Ii z=cp!Xg}#35qA^?B)u`q5$Gs4uV5}uk#O25iHi3j~G?blglx1<=!Y(>q|JEr?LzIqJ&pzhN!Y74^bf|M1R{aDz3Rd5l93|?c z%BNJ;&;C+p*2hk)sA0pi>1H- zRs&~r{LG1a0FRR6Mnwg;FsObVm4o#e|{ z>mKMX;MR=CReoj`PT%8Bd7@$Sr%N!w@ZWO8g@?rd6- zm$U9#a*ZOMEI;gkw^?%%`2?%SR-+<}=abLQT6MlnR*v7Eo3wDgcDJm>t;Ob-(f1|0 zUq;tO(HqAq-gnzP-5 za3@s~1?#mk&)tP+p+-c3IAUI4 zZg?G2IE_*5!pvAJ1ULDB#T$fHZA2n}I?zIvgo-i#mB8Xy=K&4b#@fSezmn9B$K~HM zIO;jGYxBpK;5EwL=Ln5rwQ`oU{rZ92F}63>%VW*&JlX_u>MX)JTp$`?1y;1BkE4Q5 zAY`-M;zecM$j%w&C{)?r+Uux#EH4TvjwQrb-FUTQtUhx*DeKoFwK8~&(AP4aDacw15^~7n7qqI&SQ=q?gd_A_FkT(T9$Y%&ShXFM^d?v(<`u1WB^0(9w z-xTl}gxGx(g%zL}qcSfWtSbq{+j<9@QpdyZ^T@=APHRSj_zsBKe=C@Z}4R{-e z9Qc<8^wS@0{`rxOKWlyZi`w_Etv|k$ypNsNb!F%${zcyJ?%leva^9QQxXMaHTF@Jz zveGgwOumSwDWtn~M}#yd7`i*6g(^#39=EFU*5{;M5#1XMI!Ox#@fJu~X*DzvD*$l7 zA~zZUdc3L*%BzEArL|fRTDgfMSX$@x;_2mQaRe<?KKfb_R`0~4d zyu0=Mi*J1BgT4Rz;o}>AyXEZK_x||OlIfrQQN z_TdBbes%oKdGEi6cUfRqS*aIpl;aMQF3|uOJd!XuJq$_L<>2AE&=3Zvvpc*@99~QZ z90qA`n7kf$5Ff9Xs~zw)pu?kiQ5&r0ve&^?L9fr_@&>)tj%tURzFO5)b^fSHU1pUl8*T6)-mFV=CtbuQIbyo`_yLd}~nm zbKnf$p_L9F@>&4)!FX4MN{0_idW5T#0TErBHl?CO(^=Vcv{e+f(@A&wwNjTQ8=O+2 zD=8TjEGwm^Yc4;=63q8}z^By1d^f7_@JL25SW}`q03RRS({!i|Y11{QAH%AY{fs9B z8ztr;e|ipI>-d9u^rZ3@XqkzNlDYla`r%@*9$3L!m0y~ zI2mGfR*2Q$SL_Nr{#+-JI zrZ%lz(YexkNoQ8>eUfwWj}_)?)ES&SQpJCnn2HVYD^{i4CNfeJfoxDCAO6NR_ZAwt z;V0@-?D(uwDH;GvPS~I<35C4rW-V*BE zF3jB-X#2!I=+L^z3S^nieJ+XPWbHi)=dS86e)(!Y8 z*UZ+wSR%7?>vA)WcLCDb%vSZLRz$t3C5N&VFA?zzbeXLqW49r*d&gG1En~zoMxNW$ zpXg@O|Ns8np2*wx2;)e;Y)AKu$aUczish-)8vJ#vddtu-dPF)MCVDW-jcPcmE7f^8np8Le0y`Ya{Z@(K}vblzQ^NNOCuA z;NuNAdHPnj9QGlOb|Y;!qAlOZb8ix$%^du;J$vNKeFY)Uqf;9A{+NRQ)GcznKALb( z;@^>YUP{q+HTvM&3El&SCH=VL=I`^|el#yaM<{|nb799EP{J?tY{R--JN6c9vpjFz zXisj-Jn6HGpo4F8gYpKSAH{fWiRMXP6}B1evC;loAltM`&-1U6{Oj=$M)SAYVVM6h UKiky5!+VyO>wkX!!+GG}0WWc3Z~y=R literal 0 HcmV?d00001 diff --git a/EditorExtensions/Adornments/Color/ColorAdornment.cs b/EditorExtensions/Adornments/Color/ColorAdornment.cs new file mode 100644 index 000000000..406924b46 --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorAdornment.cs @@ -0,0 +1,70 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using MadsKristensen.EditorExtensions; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.CSS.Editor.Intellisense; + +namespace IntraTextAdornmentSample +{ + internal sealed class ColorAdornment : Border + { + internal ColorAdornment(ColorTag colorTag, IWpfTextView view) + { + this.Padding = new Thickness(0); + this.BorderThickness = new Thickness(1); + this.Margin = new Thickness(0, 0, 2, 3); + this.Width = OptionHelpers.FontSize; + this.Height = this.Width; + this.Cursor = System.Windows.Input.Cursors.Arrow; + this.MouseUp += delegate { ColorAdornmentMouseUp(view); }; + + Update(colorTag); + } + + private static void ColorAdornmentMouseUp(IWpfTextView view) + { + try + { + CssCompletionController.FromView(view).OnShowMemberList(filterList: true); + } + catch + { } + } + + internal void Update(ColorTag colorTag) + { + this.Background = new SolidColorBrush(colorTag.Color); + if (!HasContrastToBackground(colorTag.Color)) + { + this.BorderThickness = new Thickness(1); + this.BorderBrush = _borderColor; + } + else + { + this.BorderThickness = new Thickness(0); + this.BorderBrush = this.Background; + } + } + + private static SolidColorBrush _borderColor = OptionHelpers.BackgroundColor.Invert().ToBrush(); + + private static bool HasContrastToBackground(Color color) + { + // The color is very transparent (alpha channel) + if (color.A < 13) + { + return false; + } + + var b = OptionHelpers.BackgroundColor; + double bBrightness = b.Red * 299 + b.Green * 587 + b.Blue * 114; + double cBrightness = color.R * 299 + color.G * 587 + color.B * 114; + double distance = Math.Abs(cBrightness - bBrightness) / 1000; + + return distance > 20; + } + } +} diff --git a/EditorExtensions/Adornments/Color/ColorAdornmentTagger.cs b/EditorExtensions/Adornments/Color/ColorAdornmentTagger.cs new file mode 100644 index 000000000..fd8c13c67 --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorAdornmentTagger.cs @@ -0,0 +1,97 @@ +//*************************************************************************** +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// This code is licensed under the Visual Studio SDK license terms. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//*************************************************************************** + +// This controls whether the adornments are positioned next to the hex values or instead of them. +#define HIDING_TEXT + +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Tagging; + +namespace IntraTextAdornmentSample +{ + /// + /// Provides color swatch adornments in place of color constants. + /// + /// + /// + /// This is a sample usage of the utility class. + /// + /// + internal sealed class ColorAdornmentTagger : IntraTextAdornmentTagger + { + internal static ITagger GetTagger(IWpfTextView view, Lazy> colorTagger) + { + return view.Properties.GetOrCreateSingletonProperty( + () => new ColorAdornmentTagger(view, colorTagger.Value)); + } + + private ITagAggregator colorTagger; + + private ColorAdornmentTagger(IWpfTextView view, ITagAggregator colorTagger) + : base(view) + { + this.colorTagger = colorTagger; + } + + public void Dispose() + { + this.colorTagger.Dispose(); + + base.view.Properties.RemoveProperty(typeof(ColorAdornmentTagger)); + } + + // To produce adornments that don't obscure the text, the adornment tags + // should have zero length spans. Overriding this method allows control + // over the tag spans. + protected override IEnumerable> GetAdornmentData(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0) + yield break; + + ITextSnapshot snapshot = spans[0].Snapshot; + + var colorTags = this.colorTagger.GetTags(spans); + + foreach (IMappingTagSpan dataTagSpan in colorTags) + { + NormalizedSnapshotSpanCollection colorTagSpans = dataTagSpan.Span.GetSpans(snapshot); + + // Ignore data tags that are split by projection. + // This is theoretically possible but unlikely in current scenarios. + if (colorTagSpans.Count != 1) + continue; + + SnapshotSpan adornmentSpan = new SnapshotSpan(colorTagSpans[0].Start, 0); + + yield return Tuple.Create(adornmentSpan, (PositionAffinity?)PositionAffinity.Successor, dataTagSpan.Tag); + } + } + + protected override ColorAdornment CreateAdornment(ColorTag dataTag, SnapshotSpan span) + { + return new ColorAdornment(dataTag, view); + } + + protected override bool UpdateAdornment(ColorAdornment adornment, ColorTag dataTag) + { + if (adornment != null) + { + adornment.Update(dataTag); + } + + return true; + } + } +} diff --git a/EditorExtensions/Adornments/Color/ColorAdornmentTaggerProvider.cs b/EditorExtensions/Adornments/Color/ColorAdornmentTaggerProvider.cs new file mode 100644 index 000000000..c14470778 --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorAdornmentTaggerProvider.cs @@ -0,0 +1,50 @@ +//*************************************************************************** +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// This code is licensed under the Visual Studio SDK license terms. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//*************************************************************************** + +using System; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; + +namespace IntraTextAdornmentSample +{ + [Export(typeof(IViewTaggerProvider))] + [ContentType("css")] + [TagType(typeof(IntraTextAdornmentTag))] + internal sealed class ColorAdornmentTaggerProvider : IViewTaggerProvider + { + #pragma warning disable 649 // "field never assigned to" -- field is set by MEF. + [Import] + internal IBufferTagAggregatorFactoryService BufferTagAggregatorFactoryService; + #pragma warning restore 649 + + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (textView == null) + throw new ArgumentNullException("textView"); + + if (buffer == null) + throw new ArgumentNullException("buffer"); + + if (buffer != textView.TextBuffer) + return null; + + return ColorAdornmentTagger.GetTagger( + (IWpfTextView)textView, + new Lazy>( + () => BufferTagAggregatorFactoryService.CreateTagAggregator(textView.TextBuffer))) + as ITagger; + } + } +} diff --git a/EditorExtensions/Adornments/Color/ColorTag.cs b/EditorExtensions/Adornments/Color/ColorTag.cs new file mode 100644 index 000000000..e21cd83cc --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorTag.cs @@ -0,0 +1,37 @@ +//*************************************************************************** +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// This code is licensed under the Visual Studio SDK license terms. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//*************************************************************************** + +using System.Windows.Media; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; + +namespace IntraTextAdornmentSample +{ + /// + /// Data tag indicating that the tagged text represents a color. + /// + /// + /// Note that this tag has nothing directly to do with adornments or other UI. + /// This sample's adornments will be produced based on the data provided in these tags. + /// This separation provides the potential for other extensions to consume color tags + /// and provide alternative UI or other derived functionality over this data. + /// + internal class ColorTag : ITag + { + internal ColorTag(Color color) + { + this.Color = color; + } + + internal readonly Color Color; + } +} diff --git a/EditorExtensions/Adornments/Color/ColorTagger.cs b/EditorExtensions/Adornments/Color/ColorTagger.cs new file mode 100644 index 000000000..9bde2a3ca --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorTagger.cs @@ -0,0 +1,139 @@ +using MadsKristensen.EditorExtensions; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.Less.Core; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.Web.Editor; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Threading; + +namespace IntraTextAdornmentSample +{ + internal sealed class ColorTagger : ITagger + { + private ITextBuffer _buffer; + private CssTree _tree; + + internal ColorTagger(ITextBuffer buffer) + { + _buffer = buffer; + _buffer.ChangedLowPriority += BufferChanged; + } + + public event EventHandler TagsChanged; + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0 || spans[0].Length == 0 || spans[0].Length >= _buffer.CurrentSnapshot.Length || !EnsureInitialized()) + yield break; + + IEnumerable items = GetColors(spans[0]); + + foreach (var item in items.Where(i => (i.Start + i.Length) <= _buffer.CurrentSnapshot.Length)) + { + SnapshotSpan span = new SnapshotSpan(_buffer.CurrentSnapshot, item.Start, item.Length); + ColorModel colorModel = ColorParser.TryParseColor(item, ColorParser.Options.AllowAlpha | ColorParser.Options.AllowNames); + if (colorModel != null) + { + yield return new TagSpan(span, new ColorTag(colorModel.Color)); + } + } + } + + private IEnumerable GetColors(SnapshotSpan span) + { + List items = new List(); + + // TODO: Refine this so it goes directly to the individual HexColorValue, FunctionColor and TokenItem + ParseItem complexItem = _tree.StyleSheet.ItemFromRange(span.Start, span.Length); + if (complexItem == null || (!(complexItem is AtDirective) && !(complexItem is RuleBlock) && !(complexItem is LessVariableDeclaration))) + return items; + + IEnumerable declarations = new ParseItem[0]; + + var lessVar = complexItem as LessVariableDeclaration; + + if (lessVar != null) + { + declarations = new List() { lessVar.Value }; + + } + else + { + var visitorRules = new CssItemCollector(); + complexItem.Accept(visitorRules); + + declarations = from d in visitorRules.Items + where d.Values.TextAfterEnd > span.Start && d.Values.TextStart < span.End && d.Length > 2 + select d; + } + + foreach (var declaration in declarations.Where(d => d != null)) + { + var visitorHex = new CssItemCollector(); + declaration.Accept(visitorHex); + items.AddRange(visitorHex.Items); + + var visitorFunc = new CssItemCollector(); + declaration.Accept(visitorFunc); + items.AddRange(visitorFunc.Items); + + var visitorName = new CssItemCollector(); + declaration.Accept(visitorName); + items.AddRange(visitorName.Items.Where(i => (i.PreviousSibling == null || (i.PreviousSibling.Text != "@" && i.PreviousSibling.Text != "$")) && i.TokenType == CssTokenType.Identifier && Color.FromName(i.Text).IsNamedColor)); + } + + return items; + } + + public bool EnsureInitialized() + { + if (_tree == null && WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + + private void BufferChanged(object sender, TextContentChangedEventArgs e) + { + if (e.Changes.Count == 0) + return; + + var temp = TagsChanged; + if (temp == null) + return; + + // Combine all changes into a single span so that + // the ITagger<>.TagsChanged event can be raised just once for a compound edit + // with many parts. + + ITextSnapshot snapshot = e.After; + + int start = e.Changes[0].NewPosition; + int end = e.Changes[e.Changes.Count - 1].NewEnd; + + SnapshotSpan totalAffectedSpan = new SnapshotSpan( + snapshot.GetLineFromPosition(start).Start, + snapshot.GetLineFromPosition(end).End); + + //temp(this, new SnapshotSpanEventArgs(totalAffectedSpan)); + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => temp(this, new SnapshotSpanEventArgs(totalAffectedSpan))), DispatcherPriority.ApplicationIdle); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Adornments/Color/ColorTaggerProvider.cs b/EditorExtensions/Adornments/Color/ColorTaggerProvider.cs new file mode 100644 index 000000000..f1ab791fa --- /dev/null +++ b/EditorExtensions/Adornments/Color/ColorTaggerProvider.cs @@ -0,0 +1,22 @@ +using System; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; + +namespace IntraTextAdornmentSample +{ + [Export(typeof(ITaggerProvider))] + [ContentType("css")] + [TagType(typeof(ColorTag))] + internal sealed class ColorTaggerProvider : ITaggerProvider + { + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + return buffer.Properties.GetOrCreateSingletonProperty(() => new ColorTagger(buffer)) as ITagger; + } + } +} diff --git a/EditorExtensions/Adornments/Color/IntraTextAdornmentTagger.cs b/EditorExtensions/Adornments/Color/IntraTextAdornmentTagger.cs new file mode 100644 index 000000000..21e86c890 --- /dev/null +++ b/EditorExtensions/Adornments/Color/IntraTextAdornmentTagger.cs @@ -0,0 +1,268 @@ +//*************************************************************************** +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// This code is licensed under the Visual Studio SDK license terms. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//*************************************************************************** + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Tagging; + +namespace IntraTextAdornmentSample +{ + /// + /// Helper class for interspersing adornments into text. + /// + /// + /// To avoid an issue around intra-text adornment support and its interaction with text buffer changes, + /// this tagger reacts to text and color tag changes with a delay. It waits to send out its own TagsChanged + /// event until the WPF Dispatcher is running again and it takes care to report adornments + /// that are consistent with the latest sent TagsChanged event by storing that particular snapshot + /// and using it to query for the data tags. + /// + internal abstract class IntraTextAdornmentTagger + : ITagger + where TAdornment : UIElement + { + protected readonly IWpfTextView view; + private Dictionary adornmentCache = new Dictionary(); + protected ITextSnapshot snapshot { get; private set; } + private readonly List invalidatedSpans = new List(); + private bool _isProcessing; + + protected IntraTextAdornmentTagger(IWpfTextView view) + { + this.view = view; + this.snapshot = view.TextBuffer.CurrentSnapshot; + + //this.view.LayoutChanged += HandleLayoutChanged; + this.view.TextBuffer.Changed += HandleBufferChanged; + } + + /// The span of text that this adornment will elide. + /// Adornment corresponding to given data. May be null. + protected abstract TAdornment CreateAdornment(TData data, SnapshotSpan span); + + /// True if the adornment was updated and should be kept. False to have the adornment removed from the view. + protected abstract bool UpdateAdornment(TAdornment adornment, TData data); + + /// Spans to provide adornment data for. These spans do not necessarily correspond to text lines. + /// + /// If adornments need to be updated, call or . + /// This will, indirectly, cause to be called. + /// + /// + /// A sequence of: + /// * adornment data for each adornment to be displayed + /// * the span of text that should be elided for that adornment (zero length spans are acceptable) + /// * and affinity of the adornment (this should be null if and only if the elided span has a length greater than zero) + /// + protected abstract IEnumerable> GetAdornmentData(NormalizedSnapshotSpanCollection spans); + + private void HandleBufferChanged(object sender, TextContentChangedEventArgs args) + { + if (!_isProcessing) + { + _isProcessing = true; + var editedSpans = args.Changes.Select(change => new SnapshotSpan(args.After, change.NewSpan)).ToList(); + InvalidateSpans(editedSpans); + } + + _isProcessing = false; + } + + /// + /// Causes intra-text adornments to be updated asynchronously. + /// + protected void InvalidateSpans(IList spans) + { + lock (this.invalidatedSpans) + { + bool wasEmpty = this.invalidatedSpans.Count == 0; + this.invalidatedSpans.AddRange(spans); + + if (wasEmpty && this.invalidatedSpans.Count > 0) + this.view.VisualElement.Dispatcher.BeginInvoke(new Action(AsyncUpdate)); + } + } + + private void AsyncUpdate() + { + // Store the snapshot that we're now current with and send an event + // for the text that has changed. + if (this.snapshot != this.view.TextBuffer.CurrentSnapshot) + { + this.snapshot = this.view.TextBuffer.CurrentSnapshot; + + Dictionary translatedAdornmentCache = new Dictionary(); + + foreach (var keyValuePair in this.adornmentCache) + { + var key = keyValuePair.Key.TranslateTo(this.snapshot, SpanTrackingMode.EdgeExclusive); + if (!translatedAdornmentCache.ContainsKey(key)) + translatedAdornmentCache.Add(key, keyValuePair.Value); + } + + this.adornmentCache = translatedAdornmentCache; + } + + List translatedSpans; + lock (this.invalidatedSpans) + { + translatedSpans = this.invalidatedSpans.Select(s => s.TranslateTo(this.snapshot, SpanTrackingMode.EdgeInclusive)).ToList(); + this.invalidatedSpans.Clear(); + } + + if (translatedSpans.Count == 0) + return; + + var start = translatedSpans.Select(span => span.Start).Min(); + var end = translatedSpans.Select(span => span.End).Max(); + + RaiseTagsChanged(new SnapshotSpan(start, end)); + } + + /// + /// Causes intra-text adornments to be updated synchronously. + /// + protected void RaiseTagsChanged(SnapshotSpan span) + { + var handler = this.TagsChanged; + if (handler != null) + handler(this, new SnapshotSpanEventArgs(span)); + } + + private void HandleLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) + { + if (!_isProcessing) + { + _isProcessing = true; + SnapshotSpan visibleSpan = this.view.TextViewLines.FormattedSpan; + + // Filter out the adornments that are no longer visible. + HashSet toRemove = new HashSet( + from keyValuePair + in this.adornmentCache + where !keyValuePair.Key.TranslateTo(visibleSpan.Snapshot, SpanTrackingMode.EdgeExclusive).IntersectsWith(visibleSpan) + select keyValuePair.Key); + + foreach (var span in toRemove) + this.adornmentCache.Remove(span); + } + + _isProcessing = false; + } + + + // Produces tags on the snapshot that the tag consumer asked for. + public virtual IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans == null || spans.Count == 0) + yield break; + + // Translate the request to the snapshot that this tagger is current with. + + ITextSnapshot requestedSnapshot = spans[0].Snapshot; + + var translatedSpans = new NormalizedSnapshotSpanCollection(spans.Select(span => span.TranslateTo(this.snapshot, SpanTrackingMode.EdgeExclusive))); + + // Grab the adornments. + var tags = GetAdornmentTagsOnSnapshot(translatedSpans).GetEnumerator(); + while (tags.MoveNext()) + { + var current = tags.Current; + SnapshotSpan span = current.Span.TranslateTo(requestedSnapshot, SpanTrackingMode.EdgeExclusive); + + IntraTextAdornmentTag tag = new IntraTextAdornmentTag(current.Tag.Adornment, current.Tag.RemovalCallback, current.Tag.Affinity); + yield return new TagSpan(span, tag); + } + } + + // Produces tags on the snapshot that this tagger is current with. + private IEnumerable> GetAdornmentTagsOnSnapshot(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0) + yield break; + + ITextSnapshot snapshot = spans[0].Snapshot; + + // Since WPF UI objects have state (like mouse hover or animation) and are relatively expensive to create and lay out, + // this code tries to reuse controls as much as possible. + // The controls are stored in this.adornmentCache between the calls. + + // Mark which adornments fall inside the requested spans with Keep=false + // so that they can be removed from the cache if they no longer correspond to data tags. + HashSet toRemove = new HashSet(); + foreach (var ar in this.adornmentCache) + if (spans.IntersectsWith(new NormalizedSnapshotSpanCollection(ar.Key))) + toRemove.Add(ar.Key); + + foreach (var spanDataPair in GetAdornmentData(spans).Distinct(new Comparer())) + { + // Look up the corresponding adornment or create one if it's new. + TAdornment adornment; + SnapshotSpan snapshotSpan = spanDataPair.Item1; + PositionAffinity? affinity = spanDataPair.Item2; + TData adornmentData = spanDataPair.Item3; + if (this.adornmentCache.TryGetValue(snapshotSpan, out adornment)) + { + if (UpdateAdornment(adornment, adornmentData)) + toRemove.Remove(snapshotSpan); + } + else + { + adornment = CreateAdornment(adornmentData, snapshotSpan); + + if (adornment == null) + continue; + + // Get the adornment to measure itself. Its DesiredSize property is used to determine + // how much space to leave between text for this adornment. + // Note: If the size of the adornment changes, the line will be reformatted to accommodate it. + // Note: Some adornments may change size when added to the view's visual tree due to inherited + // dependency properties that affect layout. Such options can include SnapsToDevicePixels, + // UseLayoutRounding, TextRenderingMode, TextHintingMode, and TextFormattingMode. Making sure + // that these properties on the adornment match the view's values before calling Measure here + // can help avoid the size change and the resulting unnecessary re-format. + adornment.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); + + this.adornmentCache.Add(snapshotSpan, adornment); + } + + yield return new TagSpan(snapshotSpan, new IntraTextAdornmentTag(adornment, null, affinity)); + } + + foreach (var snapshotSpan in toRemove) + this.adornmentCache.Remove(snapshotSpan); + } + + public event EventHandler TagsChanged; + + private class Comparer : IEqualityComparer> + { + public bool Equals(Tuple x, Tuple y) + { + if (x == null && y == null) + return true; + if (x == null || y == null) + return false; + return x.Item1.Equals(y.Item1); + } + + public int GetHashCode(Tuple obj) + { + return obj.Item1.GetHashCode(); + } + } + + } +} diff --git a/EditorExtensions/Classifications/Base64TaggerProvider.cs b/EditorExtensions/Classifications/Base64TaggerProvider.cs new file mode 100644 index 000000000..c848726a5 --- /dev/null +++ b/EditorExtensions/Classifications/Base64TaggerProvider.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System.Text.RegularExpressions; +using MadsKristensen.EditorExtensions.QuickInfo; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.Web.Editor; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ITaggerProvider))] + [TagType(typeof(IOutliningRegionTag))] + [ContentType("CSS")] + internal sealed class Base64TaggerProvider : ITaggerProvider + { + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new Base64Tagger(buffer)) as ITagger; + //return new Base64Tagger(buffer) as ITagger; + } + } + + internal sealed class Base64Tagger : ITagger + { + private ITextBuffer buffer; + private ITextSnapshot snapshot; + private string text; + private CssTree _tree; + + public Base64Tagger(ITextBuffer buffer) + { + this.buffer = buffer; + this.snapshot = buffer.CurrentSnapshot; + this.text = snapshot.GetText(); + this.buffer.Changed += BufferChanged; + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0 || !EnsureInitialized()) + yield break; + + var visitor = new CssItemCollector(); + _tree.StyleSheet.Accept(visitor); + + foreach (UrlItem url in visitor.Items.Where(u => u.UrlString != null && u.Start >= spans[0].Start)) + { + if (url.UrlString.Text.IndexOf("base64,") > -1 && buffer.CurrentSnapshot.Length >= url.UrlString.AfterEnd) + { + var image = ImageQuickInfo.CreateImage(url.UrlString.Text.Trim('"', '\'')); + var span = new SnapshotSpan(new SnapshotPoint(buffer.CurrentSnapshot, url.UrlString.Start), url.UrlString.Length); + var tag = new OutliningRegionTag(true, true, url.UrlString.Length + " characters", image); + yield return new TagSpan(span, tag); + } + } + } + + public bool EnsureInitialized() + { + if (_tree == null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(buffer); + _tree = document.Tree; + } + catch (Exception) + { + } + } + + return _tree != null; + } + + public event EventHandler TagsChanged; + + void BufferChanged(object sender, TextContentChangedEventArgs e) + { + // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event). + if (e.After != buffer.CurrentSnapshot) + return; + //this.ReParse(); + } + } +} diff --git a/EditorExtensions/Classifications/BraceMatching.cs b/EditorExtensions/Classifications/BraceMatching.cs new file mode 100644 index 000000000..cec029711 --- /dev/null +++ b/EditorExtensions/Classifications/BraceMatching.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.WebEssentials.Css.BraceMatching +{ + [Export(typeof(IViewTaggerProvider))] + [ContentType("CSS")] + [ContentType("LESS")] + [TagType(typeof(TextMarkerTag))] + internal class BraceMatchingTaggerProvider : IViewTaggerProvider + { + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (textView == null) + return null; + + //provide highlighting only on the top-level buffer + if (textView.TextBuffer != buffer) + return null; + + return new BraceMatchingTagger(textView, buffer) as ITagger; + } + } + + public class BraceMatchingTagger : ITagger + { + internal BraceMatchingTagger(ITextView view, ITextBuffer sourceBuffer) + { + //here the keys are the open braces, and the values are the close braces + m_braceList = new Dictionary(); + m_braceList.Add('{', '}'); + m_braceList.Add('[', ']'); + m_braceList.Add('(', ')'); + this.View = view; + this.SourceBuffer = sourceBuffer; + this.CurrentChar = null; + + this.View.Caret.PositionChanged += CaretPositionChanged; + this.View.LayoutChanged += ViewLayoutChanged; + } + + + ITextView View { get; set; } + ITextBuffer SourceBuffer { get; set; } + SnapshotPoint? CurrentChar { get; set; } + private Dictionary m_braceList; + + public event EventHandler TagsChanged; + + void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) + { + if (e.NewSnapshot != e.OldSnapshot) //make sure that there has really been a change + { + UpdateAtCaretPosition(View.Caret.Position); + } + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0) //there is no content in the buffer + yield break; + + //don't do anything if the current SnapshotPoint is not initialized or at the end of the buffer + if (!CurrentChar.HasValue || CurrentChar.Value.Position >= CurrentChar.Value.Snapshot.Length) + yield break; + + //hold on to a snapshot of the current character + SnapshotPoint currentChar = CurrentChar.Value; + + //if the requested snapshot isn't the same as the one the brace is on, translate our spans to the expected snapshot + if (spans[0].Snapshot != currentChar.Snapshot) + { + currentChar = currentChar.TranslateTo(spans[0].Snapshot, PointTrackingMode.Positive); + } + + //get the current char and the previous char + char currentText = currentChar.GetChar(); + SnapshotPoint lastChar = currentChar == 0 ? currentChar : currentChar - 1; //if currentChar is 0 (beginning of buffer), don't move it back + char lastText = lastChar.GetChar(); + SnapshotSpan pairSpan = new SnapshotSpan(); + + if (m_braceList.ContainsKey(currentText)) //the key is the open brace + { + char closeChar; + m_braceList.TryGetValue(currentText, out closeChar); + if (BraceMatchingTagger.FindMatchingCloseChar(currentChar, currentText, closeChar, View.TextViewLines.Count, out pairSpan) == true) + { + yield return new TagSpan(new SnapshotSpan(currentChar, 1), new TextMarkerTag("MarkerFormatDefinition/HighlightWordFormatDefinition")); + yield return new TagSpan(pairSpan, new TextMarkerTag("MarkerFormatDefinition/HighlightWordFormatDefinition")); + } + } + else if (m_braceList.ContainsValue(lastText)) //the value is the close brace, which is the *previous* character + { + var open = from n in m_braceList + where n.Value.Equals(lastText) + select n.Key; + if (BraceMatchingTagger.FindMatchingOpenChar(lastChar, (char)open.ElementAt(0), lastText, View.TextViewLines.Count, out pairSpan) == true) + { + yield return new TagSpan(new SnapshotSpan(lastChar, 1), new TextMarkerTag("MarkerFormatDefinition/HighlightWordFormatDefinition")); + yield return new TagSpan(pairSpan, new TextMarkerTag("MarkerFormatDefinition/HighlightWordFormatDefinition")); + } + } + } + + private static bool FindMatchingCloseChar(SnapshotPoint startPoint, char open, char close, int maxLines, out SnapshotSpan pairSpan) + { + pairSpan = new SnapshotSpan(startPoint.Snapshot, 1, 1); + ITextSnapshotLine line = startPoint.GetContainingLine(); + string lineText = line.GetText(); + int lineNumber = line.LineNumber; + int offset = startPoint.Position - line.Start.Position + 1; + + int stopLineNumber = startPoint.Snapshot.LineCount - 1; + if (maxLines > 0) + stopLineNumber = Math.Min(stopLineNumber, lineNumber + maxLines); + + int openCount = 0; + while (true) + { + //walk the entire line + while (offset < line.Length) + { + char currentChar = lineText[offset]; + if (currentChar == close) //found the close character + { + if (openCount > 0) + { + openCount--; + } + else //found the matching close + { + pairSpan = new SnapshotSpan(startPoint.Snapshot, line.Start + offset, 1); + return true; + } + } + else if (currentChar == open) // this is another open + { + openCount++; + } + offset++; + } + + //move on to the next line + if (++lineNumber > stopLineNumber) + break; + + line = line.Snapshot.GetLineFromLineNumber(lineNumber); + lineText = line.GetText(); + offset = 0; + } + + return false; + } + + private static bool FindMatchingOpenChar(SnapshotPoint startPoint, char open, char close, int maxLines, out SnapshotSpan pairSpan) + { + pairSpan = new SnapshotSpan(startPoint, startPoint); + + ITextSnapshotLine line = startPoint.GetContainingLine(); + + int lineNumber = line.LineNumber; + int offset = startPoint - line.Start - 1; //move the offset to the character before this one + + //if the offset is negative, move to the previous line + if (offset < 0 && lineNumber > 0) + { + line = line.Snapshot.GetLineFromLineNumber(--lineNumber); + offset = line.Length - 1; + } + + string lineText = line.GetText(); + + int stopLineNumber = 0; + if (maxLines > 0) + stopLineNumber = Math.Max(stopLineNumber, lineNumber - maxLines); + + int closeCount = 0; + + while (true) + { + // Walk the entire line + while (offset >= 0) + { + char currentChar = lineText[offset]; + + if (currentChar == open) + { + if (closeCount > 0) + { + closeCount--; + } + else // We've found the open character + { + pairSpan = new SnapshotSpan(line.Start + offset, 1); //we just want the character itself + return true; + } + } + else if (currentChar == close) + { + closeCount++; + } + offset--; + } + + // Move to the previous line + if (--lineNumber < stopLineNumber) + break; + + line = line.Snapshot.GetLineFromLineNumber(lineNumber); + lineText = line.GetText(); + offset = line.Length - 1; + } + return false; + } + + void CaretPositionChanged(object sender, CaretPositionChangedEventArgs e) + { + UpdateAtCaretPosition(e.NewPosition); + } + + void UpdateAtCaretPosition(CaretPosition caretPosition) + { + CurrentChar = caretPosition.Point.GetPoint(SourceBuffer, caretPosition.Affinity); + + if (!CurrentChar.HasValue) + return; + + var tempEvent = TagsChanged; + if (tempEvent != null) + tempEvent(this, new SnapshotSpanEventArgs(new SnapshotSpan(SourceBuffer.CurrentSnapshot, 0, + SourceBuffer.CurrentSnapshot.Length))); + } + + } + +} diff --git a/EditorExtensions/Classifications/CssHighlightWordTagger.cs b/EditorExtensions/Classifications/CssHighlightWordTagger.cs new file mode 100644 index 000000000..75a427a91 --- /dev/null +++ b/EditorExtensions/Classifications/CssHighlightWordTagger.cs @@ -0,0 +1,225 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IViewTaggerProvider))] + [ContentType("CSS")] + [TagType(typeof(TextMarkerTag))] + internal class CssHighlightWordTaggerProvider : IViewTaggerProvider + { + [Import] + internal ITextSearchService TextSearchService { get; set; } + + [Import] + internal ITextStructureNavigatorSelectorService TextStructureNavigatorSelector { get; set; } + + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (textView.TextBuffer != buffer) + return null; + + ITextStructureNavigator textStructureNavigator = TextStructureNavigatorSelector.GetTextStructureNavigator(buffer); + //return new HighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator) as ITagger; + return buffer.Properties.GetOrCreateSingletonProperty(() => new CssHighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator)) as ITagger; + } + } + + internal class HighlightWordTag : TextMarkerTag + { + public HighlightWordTag() : base("MarkerFormatDefinition/HighlightWordFormatDefinition") { } + } + + internal class CssHighlightWordTagger : ITagger + { + ITextView _view { get; set; } + ITextBuffer _buffer { get; set; } + ITextSearchService _textSearchService { get; set; } + ITextStructureNavigator _textStructureNavigator { get; set; } + NormalizedSnapshotSpanCollection _wordSpans { get; set; } + SnapshotSpan? _currentWord { get; set; } + SnapshotPoint _requestedPoint { get; set; } + object _syncLock = new object(); + private CssTree _tree; + + public CssHighlightWordTagger(ITextView view, ITextBuffer sourceBuffer, ITextSearchService textSearchService, ITextStructureNavigator textStructureNavigator) + { + this._view = view; + this._buffer = sourceBuffer; + this._textSearchService = textSearchService; + this._textStructureNavigator = textStructureNavigator; + this._wordSpans = new NormalizedSnapshotSpanCollection(); + this._currentWord = null; + this._view.Caret.PositionChanged += CaretPositionChanged; + this._view.LayoutChanged += ViewLayoutChanged; + } + + private void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) + { + if (e.NewSnapshot != e.OldSnapshot) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => UpdateAtCaretPosition(_view.Caret.Position)), DispatcherPriority.ApplicationIdle, null); + } + } + + private void CaretPositionChanged(object sender, CaretPositionChangedEventArgs e) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => UpdateAtCaretPosition(e.NewPosition)), DispatcherPriority.ApplicationIdle, null); + } + + public event EventHandler TagsChanged; + + private void UpdateAtCaretPosition(CaretPosition caretPosition) + { + if (!WESettings.GetBoolean(WESettings.Keys.EnableCssSelectorHighligting)) + return; + + SnapshotPoint? point = caretPosition.Point.GetPoint(_buffer, caretPosition.Affinity); + + if (!point.HasValue || !EnsureInitialized()) + return; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position); + if (item == null) + return; + + ParseItem validItem = item.FindType(); + + if (validItem == null) + validItem = item.FindType(); + + if (validItem == null) + validItem = item.FindType(); + + // If the new caret position is still within the current word (and on the same snapshot), we don't need to check it + if (_currentWord.HasValue + && _currentWord.Value.Snapshot == _view.TextSnapshot + && point.Value >= _currentWord.Value.Start + && point.Value <= _currentWord.Value.End) + { + return; + } + + _requestedPoint = point.Value; + Task.Run(new Action(() => UpdateWordAdornments(validItem))); + //UpdateWordAdornments(validItem); + } + + void UpdateWordAdornments(ParseItem item) + { + SnapshotPoint currentRequest = _requestedPoint; + List wordSpans = new List(); + SnapshotSpan currentWord; + + if (item != null) + { + currentWord = new SnapshotSpan(new SnapshotPoint(_buffer.CurrentSnapshot, item.Start), item.Length);// word.Span; + //If this is the current word, and the caret moved within a word, we're done. + if (_currentWord.HasValue && currentWord == _currentWord) + return; + + //Find the new spans + FindData findData = new FindData(item.Text, currentWord.Snapshot); + findData.FindOptions = FindOptions.WholeWord | FindOptions.MatchCase; + + wordSpans.AddRange(_textSearchService.FindAll(findData)); + + if (wordSpans.Count == 1) + wordSpans.Clear(); + } + else + { + TextExtent word = _textStructureNavigator.GetExtentOfWord(currentRequest); + currentWord = word.Span; + } + + //If another change hasn't happened, do a real update + if (currentRequest == _requestedPoint) + { + //Task.Run(new Action(() => SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord))); + SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord); + } + } + + private void SynchronousUpdate(SnapshotPoint currentRequest, NormalizedSnapshotSpanCollection newSpans, SnapshotSpan? newCurrentWord) + { + lock (_syncLock) + { + if (currentRequest != _requestedPoint) + return; + + _wordSpans = newSpans; + _currentWord = newCurrentWord; + + var tempEvent = TagsChanged; + if (tempEvent != null) + tempEvent(this, new SnapshotSpanEventArgs(new SnapshotSpan(_buffer.CurrentSnapshot, 0, _buffer.CurrentSnapshot.Length))); + } + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (_currentWord == null) + yield break; + + // Hold on to a "snapshot" of the word spans and current word, so that we maintain the same + // collection throughout + SnapshotSpan currentWord = _currentWord.Value; + NormalizedSnapshotSpanCollection wordSpans = _wordSpans; + + if (spans.Count == 0 || _wordSpans.Count == 0) + yield break; + + // If the requested snapshot isn't the same as the one our words are on, translate our spans to the expected snapshot + if (spans[0].Snapshot != wordSpans[0].Snapshot) + { + wordSpans = new NormalizedSnapshotSpanCollection( + wordSpans.Select(span => span.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive))); + + currentWord = currentWord.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive); + } + + // First, yield back the word the cursor is under (if it overlaps) + // Note that we'll yield back the same word again in the wordspans collection; + // the duplication here is expected. + if (spans.OverlapsWith(new NormalizedSnapshotSpanCollection(currentWord))) + yield return new TagSpan(currentWord, new HighlightWordTag()); + + // Second, yield all the other words in the file + foreach (SnapshotSpan span in NormalizedSnapshotSpanCollection.Overlap(spans, wordSpans)) + { + yield return new TagSpan(span, new HighlightWordTag()); + } + } + + private bool EnsureInitialized() + { + if (_tree == null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + } +} diff --git a/EditorExtensions/Classifications/JavaScriptArrayOutlining.cs b/EditorExtensions/Classifications/JavaScriptArrayOutlining.cs new file mode 100644 index 000000000..3e4866eb1 --- /dev/null +++ b/EditorExtensions/Classifications/JavaScriptArrayOutlining.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ITaggerProvider))] + [TagType(typeof(IOutliningRegionTag))] + [ContentType("JavaScript")] + internal sealed class ArrayOutliningTaggerProvider : ITaggerProvider + { + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + if (WESettings.GetBoolean(WESettings.Keys.JavaScriptOutlining)) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new JavaScriptArrayOutliningTagger(buffer)) as ITagger; + } + + return null; + } + } + + internal sealed class JavaScriptArrayOutliningTagger : ITagger + { + string startHide = "["; //the characters that start the outlining region + string endHide = "]"; //the characters that end the outlining region + string ellipsis = "..."; //the characters that are displayed when the region is collapsed + ITextBuffer buffer; + ITextSnapshot snapshot; + List regions; + + public JavaScriptArrayOutliningTagger(ITextBuffer buffer) + { + this.buffer = buffer; + this.snapshot = buffer.CurrentSnapshot; + this.regions = new List(); + this.buffer.ChangedLowPriority += BufferChanged; + + Task.Run(() => this.ReParse()); + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0) + yield break; + + List currentRegions = this.regions; + ITextSnapshot currentSnapshot = this.snapshot; + SnapshotSpan entire = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End).TranslateTo(currentSnapshot, SpanTrackingMode.EdgeExclusive); + int startLineNumber = entire.Start.GetContainingLine().LineNumber; + int endLineNumber = entire.End.GetContainingLine().LineNumber; + + foreach (var region in currentRegions) + { + if (region.StartLine <= endLineNumber && region.EndLine >= startLineNumber) + { + var startLine = currentSnapshot.GetLineFromLineNumber(region.StartLine); + string lineText = startLine.GetText().Trim(); + + if (!lineText.Contains("function")) + { + var endLine = currentSnapshot.GetLineFromLineNumber(region.EndLine); + var contentSpan = new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + //the region starts at the beginning of the "[", and goes until the *end* of the line that contains the "]". + yield return new TagSpan(contentSpan, new OutliningRegionTag(false, true, ellipsis, contentSpan.GetText())); + } + } + } + } + + public event EventHandler TagsChanged; + + void BufferChanged(object sender, TextContentChangedEventArgs e) + { + // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event). + if (e.After != buffer.CurrentSnapshot) + return; + + Task.Run(() => this.ReParse()); + } + + void ReParse() + { + ITextSnapshot newSnapshot = buffer.CurrentSnapshot; + List newRegions = new List(); + + //keep the current (deepest) partial region, which will have + // references to any parent partial regions. + PartialRegion currentRegion = null; + + foreach (var line in newSnapshot.Lines) + { + int regionStart = -1; + string text = line.GetText(); + + //lines that contain a "[" denote the start of a new region. + if ((regionStart = text.IndexOf(startHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int newLevel; + if (!TryGetLevel(text, regionStart, out newLevel)) + newLevel = currentLevel + 1; + + //levels are the same and we have an existing region; + //end the current region and start the next + if (currentLevel == newLevel && currentRegion != null) + { + newRegions.Add(new Region() + { + Level = currentRegion.Level, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion.PartialParent + }; + } + //this is a new (sub)region + else + { + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion + }; + } + } + //lines that contain "]" denote the end of a region + else if ((regionStart = text.IndexOf(endHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int closingLevel; + if (!TryGetLevel(text, regionStart, out closingLevel)) + closingLevel = currentLevel; + + //the regions match + if (currentRegion != null && + currentLevel == closingLevel) + { + newRegions.Add(new Region() + { + Level = currentLevel, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = currentRegion.PartialParent; + } + } + } + + //determine the changed span, and send a changed event with the new spans + List oldSpans = + new List(this.regions.Select(r => AsSnapshotSpan(r, this.snapshot) + .TranslateTo(newSnapshot, SpanTrackingMode.EdgeExclusive) + .Span)); + List newSpans = + new List(newRegions.Select(r => AsSnapshotSpan(r, newSnapshot).Span)); + + NormalizedSpanCollection oldSpanCollection = new NormalizedSpanCollection(oldSpans); + NormalizedSpanCollection newSpanCollection = new NormalizedSpanCollection(newSpans); + + //the changed regions are regions that appear in one set or the other, but not both. + NormalizedSpanCollection removed = + NormalizedSpanCollection.Difference(oldSpanCollection, newSpanCollection); + + int changeStart = int.MaxValue; + int changeEnd = -1; + + if (removed.Count > 0) + { + changeStart = removed[0].Start; + changeEnd = removed[removed.Count - 1].End; + } + + if (newSpans.Count > 0) + { + changeStart = Math.Min(changeStart, newSpans[0].Start); + changeEnd = Math.Max(changeEnd, newSpans[newSpans.Count - 1].End); + } + + this.snapshot = newSnapshot; + this.regions = newRegions; + + if (changeStart <= changeEnd) + { + ITextSnapshot snap = this.snapshot; + if (this.TagsChanged != null) + this.TagsChanged(this, new SnapshotSpanEventArgs( + new SnapshotSpan(this.snapshot, Span.FromBounds(changeStart, changeEnd)))); + } + } + + static bool TryGetLevel(string text, int startIndex, out int level) + { + level = -1; + if (text.Length > startIndex + 3) + { + if (int.TryParse(text.Substring(startIndex + 1), out level)) + return true; + } + + return false; + } + + static SnapshotSpan AsSnapshotSpan(Region region, ITextSnapshot snapshot) + { + var startLine = snapshot.GetLineFromLineNumber(region.StartLine); + var endLine = (region.StartLine == region.EndLine) ? startLine + : snapshot.GetLineFromLineNumber(region.EndLine); + return new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + } + + } + + //class PartialRegion + //{ + // public int StartLine { get; set; } + // public int StartOffset { get; set; } + // public int Level { get; set; } + // public PartialRegion PartialParent { get; set; } + //} + + //class Region : PartialRegion + //{ + // public int EndLine { get; set; } + //} + +} diff --git a/EditorExtensions/Classifications/JavaScriptHighlightWordTagger.cs b/EditorExtensions/Classifications/JavaScriptHighlightWordTagger.cs new file mode 100644 index 000000000..16fcc6b85 --- /dev/null +++ b/EditorExtensions/Classifications/JavaScriptHighlightWordTagger.cs @@ -0,0 +1,213 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Threading.Tasks; + +namespace MadsKristensen.WebEssentials.Structures.Js +{ + [Export(typeof(IViewTaggerProvider))] + [ContentType("JavaScript")] + [TagType(typeof(TextMarkerTag))] + internal class HighlightWordTaggerProvider : IViewTaggerProvider + { + [Import] + internal ITextSearchService TextSearchService { get; set; } + + [Import] + internal ITextStructureNavigatorSelectorService TextStructureNavigatorSelector { get; set; } + + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (textView.TextBuffer != buffer) + return null; + + ITextStructureNavigator textStructureNavigator = TextStructureNavigatorSelector.GetTextStructureNavigator(buffer); + return buffer.Properties.GetOrCreateSingletonProperty(() => new JavaScriptHighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator)) as ITagger; + } + } + + internal class HighlightWordTag : TextMarkerTag + { + public HighlightWordTag() : base("MarkerFormatDefinition/HighlightWordFormatDefinition") { } + } + + internal class JavaScriptHighlightWordTagger : ITagger + { + ITextView _view { get; set; } + ITextBuffer _buffer { get; set; } + ITextSearchService _textSearchService { get; set; } + ITextStructureNavigator _textStructureNavigator { get; set; } + NormalizedSnapshotSpanCollection _wordSpans { get; set; } + SnapshotSpan? _currentWord { get; set; } + SnapshotPoint _requestedPoint { get; set; } + object _updateLock = new object(); + private bool _inProgress; + + public JavaScriptHighlightWordTagger(ITextView view, ITextBuffer sourceBuffer, ITextSearchService textSearchService, ITextStructureNavigator textStructureNavigator) + { + this._view = view; + this._buffer = sourceBuffer; + this._textSearchService = textSearchService; + this._textStructureNavigator = textStructureNavigator; + this._wordSpans = new NormalizedSnapshotSpanCollection(); + this._currentWord = null; + this._view.Caret.PositionChanged += CaretPositionChanged; + } + + void CaretPositionChanged(object sender, CaretPositionChangedEventArgs e) + { + if (!_inProgress) + { + _inProgress = true; + + Task.Run(() => + { + UpdateAtCaretPosition(e.NewPosition); + _inProgress = false; + }); + } + } + + public event EventHandler TagsChanged; + + void UpdateAtCaretPosition(CaretPosition caretPosition) + { + SnapshotPoint? point = caretPosition.Point.GetPoint(_buffer, caretPosition.Affinity); + + if (!point.HasValue) + return; + + // If the new caret position is still within the current word (and on the same snapshot), we don't need to check it + if (_currentWord.HasValue + && _currentWord.Value.Snapshot == _view.TextSnapshot + && point.Value >= _currentWord.Value.Start + && point.Value <= _currentWord.Value.End) + { + return; + } + + _requestedPoint = point.Value; + + UpdateWordAdornments(); + } + + void UpdateWordAdornments() + { + SnapshotPoint currentRequest = _requestedPoint; + List wordSpans = new List(); + //Find all words in the buffer like the one the caret is on + TextExtent word = _textStructureNavigator.GetExtentOfWord(currentRequest); + bool foundWord = true; + //If we've selected something not worth highlighting, we might have missed a "word" by a little bit + if (!WordExtentIsValid(currentRequest, word)) + { + //Before we retry, make sure it is worthwhile + if (word.Span.Start != currentRequest + || currentRequest == currentRequest.GetContainingLine().Start + || char.IsWhiteSpace((currentRequest - 1).GetChar())) + { + foundWord = false; + } + else + { + // Try again, one character previous. + //If the caret is at the end of a word, pick up the word. + word = _textStructureNavigator.GetExtentOfWord(currentRequest - 1); + + //If the word still isn't valid, we're done + if (!WordExtentIsValid(currentRequest, word)) + foundWord = false; + } + } + + if (!foundWord) + { + //If we couldn't find a word, clear out the existing markers + SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); + return; + } + + SnapshotSpan currentWord = word.Span; + //If this is the current word, and the caret moved within a word, we're done. + if (_currentWord.HasValue && currentWord == _currentWord) + return; + + //Find the new spans + FindData findData = new FindData(currentWord.GetText(), currentWord.Snapshot); + findData.FindOptions = FindOptions.WholeWord | FindOptions.MatchCase; + + wordSpans.AddRange(_textSearchService.FindAll(findData)); + + //If another change hasn't happened, do a real update + if (currentRequest == _requestedPoint) + SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord); + } + static bool WordExtentIsValid(SnapshotPoint currentRequest, TextExtent word) + { + return word.IsSignificant + && currentRequest.Snapshot.GetText(word.Span).Any(c => char.IsLetter(c)); + } + + void SynchronousUpdate(SnapshotPoint currentRequest, NormalizedSnapshotSpanCollection newSpans, SnapshotSpan? newCurrentWord) + { + lock (_updateLock) + { + if (currentRequest != _requestedPoint) + return; + + _wordSpans = newSpans; + _currentWord = newCurrentWord; + + var tempEvent = TagsChanged; + if (tempEvent != null) + tempEvent(this, new SnapshotSpanEventArgs(new SnapshotSpan(_buffer.CurrentSnapshot, 0, _buffer.CurrentSnapshot.Length))); + } + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (_currentWord == null) + yield break; + + // Hold on to a "snapshot" of the word spans and current word, so that we maintain the same + // collection throughout + SnapshotSpan currentWord = _currentWord.Value; + NormalizedSnapshotSpanCollection wordSpans = _wordSpans; + + if (spans.Count == 0 || _wordSpans.Count == 0) + yield break; + + // If the requested snapshot isn't the same as the one our words are on, translate our spans to the expected snapshot + if (spans[0].Snapshot != wordSpans[0].Snapshot) + { + wordSpans = new NormalizedSnapshotSpanCollection( + wordSpans.Select(span => span.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive))); + + currentWord = currentWord.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive); + } + + NormalizedSnapshotSpanCollection words = NormalizedSnapshotSpanCollection.Overlap(spans, wordSpans); + + if (words.Count == 1) + yield break; + + // First, yield back the word the cursor is under (if it overlaps) + // Note that we'll yield back the same word again in the wordspans collection; + // the duplication here is expected. + if (spans.OverlapsWith(new NormalizedSnapshotSpanCollection(currentWord))) + yield return new TagSpan(currentWord, new HighlightWordTag()); + + // Second, yield all the other words in the file + foreach (SnapshotSpan span in words) + { + yield return new TagSpan(span, new HighlightWordTag()); + } + } + } +} diff --git a/EditorExtensions/Classifications/JavaScriptOutlining.cs b/EditorExtensions/Classifications/JavaScriptOutlining.cs new file mode 100644 index 000000000..c5ad13bd4 --- /dev/null +++ b/EditorExtensions/Classifications/JavaScriptOutlining.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ITaggerProvider))] + [TagType(typeof(IOutliningRegionTag))] + [ContentType("JavaScript")] + internal sealed class OutliningTaggerProvider : ITaggerProvider + { + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + if (WESettings.GetBoolean(WESettings.Keys.JavaScriptOutlining)) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new JavaScriptOutliningTagger(buffer)) as ITagger; + } + + return null; + } + } + + internal sealed class JavaScriptOutliningTagger : ITagger + { + string startHide = "{"; //the characters that start the outlining region + string endHide = "}"; //the characters that end the outlining region + string ellipsis = "..."; //the characters that are displayed when the region is collapsed + ITextBuffer buffer; + ITextSnapshot snapshot; + List regions; + + public JavaScriptOutliningTagger(ITextBuffer buffer) + { + this.buffer = buffer; + this.snapshot = buffer.CurrentSnapshot; + this.regions = new List(); + this.buffer.ChangedLowPriority += BufferChanged; + + Task.Run(() => this.ReParse()); + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0) + yield break; + + List currentRegions = this.regions; + ITextSnapshot currentSnapshot = this.snapshot; + SnapshotSpan entire = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End).TranslateTo(currentSnapshot, SpanTrackingMode.EdgeExclusive); + int startLineNumber = entire.Start.GetContainingLine().LineNumber; + int endLineNumber = entire.End.GetContainingLine().LineNumber; + + foreach (var region in currentRegions) + { + if (region.StartLine <= endLineNumber && region.EndLine >= startLineNumber) + { + var startLine = currentSnapshot.GetLineFromLineNumber(region.StartLine); + string lineText = startLine.GetText().Trim(); + + if (!lineText.Contains("function")) + { + var endLine = currentSnapshot.GetLineFromLineNumber(region.EndLine); + var contentSpan = new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + //the region starts at the beginning of the "[", and goes until the *end* of the line that contains the "]". + yield return new TagSpan(contentSpan, new OutliningRegionTag(false, false, ellipsis, contentSpan.GetText())); + } + } + } + } + + public event EventHandler TagsChanged; + + void BufferChanged(object sender, TextContentChangedEventArgs e) + { + // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event). + if (e.After != buffer.CurrentSnapshot) + return; + + Task.Run(() => this.ReParse()); + } + + void ReParse() + { + ITextSnapshot newSnapshot = buffer.CurrentSnapshot; + List newRegions = new List(); + + //keep the current (deepest) partial region, which will have + // references to any parent partial regions. + PartialRegion currentRegion = null; + + foreach (var line in newSnapshot.Lines) + { + int regionStart = -1; + string text = line.GetText(); + + if (text.IndexOf(startHide) > -1 && text.IndexOf(endHide) > -1) + continue; + + //lines that contain a "[" denote the start of a new region. + if ((regionStart = text.IndexOf(startHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int newLevel; + if (!TryGetLevel(text, regionStart, out newLevel)) + newLevel = currentLevel + 1; + + //levels are the same and we have an existing region; + //end the current region and start the next + if (currentLevel == newLevel && currentRegion != null) + { + newRegions.Add(new Region() + { + Level = currentRegion.Level, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion.PartialParent + }; + } + //this is a new (sub)region + else + { + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion + }; + } + } + //lines that contain "]" denote the end of a region + else if ((regionStart = text.IndexOf(endHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int closingLevel; + if (!TryGetLevel(text, regionStart, out closingLevel)) + closingLevel = currentLevel; + + //the regions match + if (currentRegion != null && + currentLevel == closingLevel) + { + newRegions.Add(new Region() + { + Level = currentLevel, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = currentRegion.PartialParent; + } + } + } + + //determine the changed span, and send a changed event with the new spans + List oldSpans = + new List(this.regions.Select(r => AsSnapshotSpan(r, this.snapshot) + .TranslateTo(newSnapshot, SpanTrackingMode.EdgeExclusive) + .Span)); + List newSpans = + new List(newRegions.Select(r => AsSnapshotSpan(r, newSnapshot).Span)); + + NormalizedSpanCollection oldSpanCollection = new NormalizedSpanCollection(oldSpans); + NormalizedSpanCollection newSpanCollection = new NormalizedSpanCollection(newSpans); + + //the changed regions are regions that appear in one set or the other, but not both. + NormalizedSpanCollection removed = + NormalizedSpanCollection.Difference(oldSpanCollection, newSpanCollection); + + int changeStart = int.MaxValue; + int changeEnd = -1; + + if (removed.Count > 0) + { + changeStart = removed[0].Start; + changeEnd = removed[removed.Count - 1].End; + } + + if (newSpans.Count > 0) + { + changeStart = Math.Min(changeStart, newSpans[0].Start); + changeEnd = Math.Max(changeEnd, newSpans[newSpans.Count - 1].End); + } + + this.snapshot = newSnapshot; + this.regions = newRegions; + + if (changeStart <= changeEnd) + { + ITextSnapshot snap = this.snapshot; + if (this.TagsChanged != null) + this.TagsChanged(this, new SnapshotSpanEventArgs( + new SnapshotSpan(this.snapshot, Span.FromBounds(changeStart, changeEnd)))); + } + } + + static bool TryGetLevel(string text, int startIndex, out int level) + { + level = -1; + if (text.Length > startIndex + 3) + { + if (int.TryParse(text.Substring(startIndex + 1), out level)) + return true; + } + + return false; + } + + static SnapshotSpan AsSnapshotSpan(Region region, ITextSnapshot snapshot) + { + var startLine = snapshot.GetLineFromLineNumber(region.StartLine); + var endLine = (region.StartLine == region.EndLine) ? startLine + : snapshot.GetLineFromLineNumber(region.EndLine); + return new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + } + + } + + //class PartialRegion + //{ + // public int StartLine { get; set; } + // public int StartOffset { get; set; } + // public int Level { get; set; } + // public PartialRegion PartialParent { get; set; } + //} + + //class Region : PartialRegion + //{ + // public int EndLine { get; set; } + //} + +} diff --git a/EditorExtensions/Classifications/JavaScriptRegionTagger.cs b/EditorExtensions/Classifications/JavaScriptRegionTagger.cs new file mode 100644 index 000000000..47f828953 --- /dev/null +++ b/EditorExtensions/Classifications/JavaScriptRegionTagger.cs @@ -0,0 +1,244 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ITaggerProvider))] + [TagType(typeof(IOutliningRegionTag))] + [ContentType("javascript")] + //[ContentType("TypeScript")] + [ContentType("LESS")] + internal sealed class RegionTaggerProvider : ITaggerProvider + { + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new RegionTagger(buffer)) as ITagger; + } + } + + internal sealed class RegionTagger : ITagger + { + string startHide = "//#region"; //the characters that start the outlining region + string endHide = "//#endregion"; //the characters that end the outlining region + string hoverText = "Collapsed content"; //the contents of the tooltip for the collapsed span + ITextBuffer buffer; + ITextSnapshot snapshot; + List regions; + private static Regex regex = new Regex(@"\/\/\#region(.*)?", RegexOptions.Compiled); + + public RegionTagger(ITextBuffer buffer) + { + this.buffer = buffer; + this.snapshot = buffer.CurrentSnapshot; + this.regions = new List(); + this.buffer.Changed += BufferChanged; + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => ReParse()), DispatcherPriority.ApplicationIdle, null); + + this.buffer.Changed += BufferChanged; + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0 || !WESettings.GetBoolean(WESettings.Keys.EnableJavascriptRegions)) + yield break; + + List currentRegions = this.regions; + ITextSnapshot currentSnapshot = this.snapshot; + + SnapshotSpan entire = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End).TranslateTo(currentSnapshot, SpanTrackingMode.EdgeExclusive); + int startLineNumber = entire.Start.GetContainingLine().LineNumber; + int endLineNumber = entire.End.GetContainingLine().LineNumber; + foreach (var region in currentRegions) + { + if (region.StartLine <= endLineNumber && region.EndLine >= startLineNumber) + { + var startLine = currentSnapshot.GetLineFromLineNumber(region.StartLine); + var endLine = currentSnapshot.GetLineFromLineNumber(region.EndLine); + + var snapshot = new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + Match match = regex.Match(snapshot.GetText()); + + //the region starts at the beginning of the "[", and goes until the *end* of the line that contains the "]". + yield return new TagSpan( + snapshot, + new OutliningRegionTag(false, true, " " + match.Groups[1].Value.Trim() + " ", hoverText)); + } + } + } + + public event EventHandler TagsChanged; + + void BufferChanged(object sender, TextContentChangedEventArgs e) + { + // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event). + if (e.After != buffer.CurrentSnapshot) + return; + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => ReParse()), DispatcherPriority.ApplicationIdle, null); + } + + void ReParse() + { + ITextSnapshot newSnapshot = buffer.CurrentSnapshot; + List newRegions = new List(); + + //keep the current (deepest) partial region, which will have + // references to any parent partial regions. + PartialRegion currentRegion = null; + + foreach (var line in newSnapshot.Lines) + { + int regionStart = -1; + string text = line.GetText(); + + //lines that contain a "[" denote the start of a new region. + if ((regionStart = text.IndexOf(startHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int newLevel; + if (!TryGetLevel(text, regionStart, out newLevel)) + newLevel = currentLevel + 1; + + //levels are the same and we have an existing region; + //end the current region and start the next + if (currentLevel == newLevel && currentRegion != null) + { + newRegions.Add(new Region() + { + Level = currentRegion.Level, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion.PartialParent + }; + } + //this is a new (sub)region + else + { + currentRegion = new PartialRegion() + { + Level = newLevel, + StartLine = line.LineNumber, + StartOffset = regionStart, + PartialParent = currentRegion + }; + } + } + //lines that contain "]" denote the end of a region + else if ((regionStart = text.IndexOf(endHide, StringComparison.Ordinal)) != -1) + { + int currentLevel = (currentRegion != null) ? currentRegion.Level : 1; + int closingLevel; + if (!TryGetLevel(text, regionStart, out closingLevel)) + closingLevel = currentLevel; + + //the regions match + if (currentRegion != null && + currentLevel == closingLevel) + { + newRegions.Add(new Region() + { + Level = currentLevel, + StartLine = currentRegion.StartLine, + StartOffset = currentRegion.StartOffset, + EndLine = line.LineNumber + }); + + currentRegion = currentRegion.PartialParent; + } + } + } + + //determine the changed span, and send a changed event with the new spans + List oldSpans = + new List(this.regions.Select(r => AsSnapshotSpan(r, this.snapshot) + .TranslateTo(newSnapshot, SpanTrackingMode.EdgeExclusive) + .Span)); + List newSpans = + new List(newRegions.Select(r => AsSnapshotSpan(r, newSnapshot).Span)); + + NormalizedSpanCollection oldSpanCollection = new NormalizedSpanCollection(oldSpans); + NormalizedSpanCollection newSpanCollection = new NormalizedSpanCollection(newSpans); + + //the changed regions are regions that appear in one set or the other, but not both. + NormalizedSpanCollection removed = + NormalizedSpanCollection.Difference(oldSpanCollection, newSpanCollection); + + int changeStart = int.MaxValue; + int changeEnd = -1; + + if (removed.Count > 0) + { + changeStart = removed[0].Start; + changeEnd = removed[removed.Count - 1].End; + } + + if (newSpans.Count > 0) + { + changeStart = Math.Min(changeStart, newSpans[0].Start); + changeEnd = Math.Max(changeEnd, newSpans[newSpans.Count - 1].End); + } + + this.snapshot = newSnapshot; + this.regions = newRegions; + + if (changeStart <= changeEnd) + { + ITextSnapshot snap = this.snapshot; + if (this.TagsChanged != null) + this.TagsChanged(this, new SnapshotSpanEventArgs( + new SnapshotSpan(this.snapshot, Span.FromBounds(changeStart, changeEnd)))); + } + } + + static bool TryGetLevel(string text, int startIndex, out int level) + { + level = -1; + if (text.Length > startIndex + 3) + { + if (int.TryParse(text.Substring(startIndex + 1), out level)) + return true; + } + + return false; + } + + static SnapshotSpan AsSnapshotSpan(Region region, ITextSnapshot snapshot) + { + var startLine = snapshot.GetLineFromLineNumber(region.StartLine); + var endLine = (region.StartLine == region.EndLine) ? startLine + : snapshot.GetLineFromLineNumber(region.EndLine); + return new SnapshotSpan(startLine.Start + region.StartOffset, endLine.End); + } + } + + class PartialRegion + { + public int StartLine { get; set; } + public int StartOffset { get; set; } + public int Level { get; set; } + public PartialRegion PartialParent { get; set; } + } + + class Region : PartialRegion + { + public int EndLine { get; set; } + } +} diff --git a/EditorExtensions/Classifications/Markdown/MarkdownClassificationTypes.cs b/EditorExtensions/Classifications/Markdown/MarkdownClassificationTypes.cs new file mode 100644 index 000000000..af93c3bdb --- /dev/null +++ b/EditorExtensions/Classifications/Markdown/MarkdownClassificationTypes.cs @@ -0,0 +1,77 @@ +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; +using System.Windows; + +namespace MadsKristensen.EditorExtensions +{ + class MarkdownClassificationTypes + { + public const string MarkdownBold = "md_bold"; + public const string MarkdownItalic = "md_italic"; + public const string MarkdownHeader = "md_header"; + public const string MarkdownCode = "md_code"; + + [Export, Name(MarkdownClassificationTypes.MarkdownBold), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition MarkdownClassificationBold = null; + + [Export, Name(MarkdownClassificationTypes.MarkdownItalic), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition MarkdownClassificationItalic = null; + + [Export, Name(MarkdownClassificationTypes.MarkdownHeader), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition MarkdownClassificationHeader = null; + + [Export, Name(MarkdownClassificationTypes.MarkdownCode), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition MarkdownClassificationCode = null; + } + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = MarkdownClassificationTypes.MarkdownBold)] + [Name(MarkdownClassificationTypes.MarkdownBold)] + [Order(After = Priority.Default)] + internal sealed class MarkdownBoldFormatDefinition : ClassificationFormatDefinition + { + public MarkdownBoldFormatDefinition() + { + IsBold = true; + } + } + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = MarkdownClassificationTypes.MarkdownItalic)] + [Name(MarkdownClassificationTypes.MarkdownItalic)] + [Order(After = Priority.Default)] + internal sealed class MarkdownItalicFormatDefinition : ClassificationFormatDefinition + { + public MarkdownItalicFormatDefinition() + { + IsItalic = true; + } + } + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = MarkdownClassificationTypes.MarkdownHeader)] + [Name(MarkdownClassificationTypes.MarkdownHeader)] + [Order(After = Priority.Default)] + internal sealed class MarkdownHeaderFormatDefinition : ClassificationFormatDefinition + { + public MarkdownHeaderFormatDefinition() + { + IsBold = true; + TextDecorations = new TextDecorationCollection(); + TextDecorations.Add(new TextDecoration()); + } + } + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = MarkdownClassificationTypes.MarkdownCode)] + [Name(MarkdownClassificationTypes.MarkdownCode)] + [Order(After = Priority.Default)] + internal sealed class MarkdownCodeFormatDefinition : ClassificationFormatDefinition + { + public MarkdownCodeFormatDefinition() + { + ForegroundColor = System.Windows.Media.Colors.Green; + } + } +} diff --git a/EditorExtensions/Classifications/Markdown/MarkdownClassifier.cs b/EditorExtensions/Classifications/Markdown/MarkdownClassifier.cs new file mode 100644 index 000000000..4df5d7a61 --- /dev/null +++ b/EditorExtensions/Classifications/Markdown/MarkdownClassifier.cs @@ -0,0 +1,70 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text.RegularExpressions; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IClassifierProvider))] + [ContentType(MarkdownContentTypeDefinition.MarkdownContentType)] + public class MarkdownClassifierProvider : IClassifierProvider + { + [Import] + internal IClassificationTypeRegistryService Registry { get; set; } + + public IClassifier GetClassifier(ITextBuffer textBuffer) + { + return textBuffer.Properties.GetOrCreateSingletonProperty(() => new MarkdownClassifier(Registry)); + } + } + + public class MarkdownClassifier : IClassifier + { + private static readonly Regex _reItalic = new Regex(@"(? GetClassificationSpans(SnapshotSpan span) + { + string text = span.GetText(); + + var bolds = FindMatches(span, text, _reBold, _bold); + var italics = FindMatches(span, text, _reItalic, _italic); + var headers = FindMatches(span, text, _reHeader, _header); + var codes = FindMatches(span, text, _reCode, _code); + + return bolds.Concat(italics).Concat(headers).Concat(codes).ToList(); + } + + private IEnumerable FindMatches(SnapshotSpan span, string text, Regex regex, IClassificationType type) + { + Match match = regex.Match(text); + + while (match.Success) + { + var result = new SnapshotSpan(span.Snapshot, span.Start + match.Index, match.Length); + yield return new ClassificationSpan(result, type); + + match = regex.Match(text, match.Index + match.Length); + } + } + + public event EventHandler ClassificationChanged; + } + +} diff --git a/EditorExtensions/Classifications/Markdown/MarkdownContentTypeDefinition.cs b/EditorExtensions/Classifications/Markdown/MarkdownContentTypeDefinition.cs new file mode 100644 index 000000000..9d46e7229 --- /dev/null +++ b/EditorExtensions/Classifications/Markdown/MarkdownContentTypeDefinition.cs @@ -0,0 +1,39 @@ +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + /// + /// Exports the ScSS content type and file extension + /// + public class MarkdownContentTypeDefinition + { + public const string MarkdownContentType = "markdown"; + + /// + /// Exports the Markdown HTML content type + /// + [Export(typeof(ContentTypeDefinition))] + [Name(MarkdownContentType)] + [BaseDefinition("html")] + public ContentTypeDefinition IMarkdownContentType { get; set; } + + /// + /// Exports the markdown file extension + /// + [Export(typeof(FileExtensionToContentTypeDefinition))] + [ContentType(MarkdownContentType)] + [FileExtension(".md")] + public FileExtensionToContentTypeDefinition IMDFileExtension { get; set; } + + [Export(typeof(FileExtensionToContentTypeDefinition))] + [ContentType(MarkdownContentType)] + [FileExtension(".mdown")] + public FileExtensionToContentTypeDefinition IMDownFileExtension { get; set; } + + [Export(typeof(FileExtensionToContentTypeDefinition))] + [ContentType(MarkdownContentType)] + [FileExtension(".markdown")] + public FileExtensionToContentTypeDefinition IMarkDownFileExtension { get; set; } + } +} diff --git a/EditorExtensions/Classifications/ModernizrClassifier.cs b/EditorExtensions/Classifications/ModernizrClassifier.cs new file mode 100644 index 000000000..0f8b3ed86 --- /dev/null +++ b/EditorExtensions/Classifications/ModernizrClassifier.cs @@ -0,0 +1,160 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal static class ModernizrClassificationTypes + { + internal const string _modernizr = "modernizr"; + + [Export, Name(ModernizrClassificationTypes._modernizr), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition ModernizrClassificationType = null; + } + + [Export(typeof(IClassifierProvider))] + [ContentType("css")] + internal sealed class ModernizrClassifierProvider : IClassifierProvider + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IClassificationTypeRegistryService Registry { get; set; } + + public IClassifier GetClassifier(ITextBuffer buffer) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => { return new ModernizrClassifier(Registry, buffer); }); + } + } + + internal sealed class ModernizrClassifier : IClassifier + { + private IClassificationTypeRegistryService _registry; + private ITextBuffer _buffer; + private CssTree _tree; + internal SortedRangeList Cache = new SortedRangeList(); + private IClassificationType _modernizrClassification; + + internal ModernizrClassifier(IClassificationTypeRegistryService registry, ITextBuffer buffer) + { + _registry = registry; + _buffer = buffer; + _modernizrClassification = _registry.GetClassificationType(ModernizrClassificationTypes._modernizr); + } + + public IList GetClassificationSpans(SnapshotSpan span) + { + List spans = new List(); + + if (!EnsureInitialized()) + return spans; + + foreach (SimpleSelector selector in Cache) + { + int start = span.Start.Position; + int end = span.End.Position; + + if (selector.Start >= start && selector.AfterEnd <= end) + { + var snapShotSpan = new SnapshotSpan(span.Snapshot, selector.Start, selector.Length); + var classSpan = new ClassificationSpan(snapShotSpan, _modernizrClassification); + spans.Add(classSpan); + } + } + + return spans; + } + + public bool EnsureInitialized() + { + if (_tree == null && WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + _tree.TreeUpdated += TreeUpdated; + _tree.ItemsChanged += TreeItemsChanged; + UpdateCache(_tree.StyleSheet); + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + + private void UpdateCache(ParseItem item) + { + var visitor = new CssItemCollector(true); + item.Accept(visitor); + + foreach (SimpleSelector ss in visitor.Items) + { + string text = ss.Text; + + if (ModernizrProvider.IsModernizr(text)) + { + if (!Cache.Contains(ss)) + Cache.Add(ss); + } + } + } + + private void TreeUpdated(object sender, CssTreeUpdateEventArgs e) + { + Cache.Clear(); + UpdateCache(e.Tree.StyleSheet); + } + + private void TreeItemsChanged(object sender, CssItemsChangedEventArgs e) + { + foreach (ParseItem item in e.DeletedItems) + { + var matches = Cache.Where(s => s.Start >= item.Start && s.AfterEnd <= item.AfterEnd); + foreach (var match in matches.Reverse()) + { + Cache.Remove(match); + } + } + + foreach (ParseItem item in e.InsertedItems) + { + UpdateCache(item); + } + } + + public event EventHandler ClassificationChanged; + + public void RaiseClassificationChanged(SnapshotSpan span) + { + var handler = this.ClassificationChanged; + if (handler != null) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => handler(this, new ClassificationChangedEventArgs(span))), DispatcherPriority.ApplicationIdle); + } + } + } + + [Export(typeof(EditorFormatDefinition))] + [UserVisible(true)] + [ClassificationType(ClassificationTypeNames = ModernizrClassificationTypes._modernizr)] + [Name(ModernizrClassificationTypes._modernizr)] + [Order(After = Priority.Default)] + internal sealed class ModernizrFormatDefinition : ClassificationFormatDefinition + { + public ModernizrFormatDefinition() + { + IsBold = true; + DisplayName = "CSS Modernizr selector"; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Classifications/SCSS/ScssClassifierProvider.cs b/EditorExtensions/Classifications/SCSS/ScssClassifierProvider.cs new file mode 100644 index 000000000..960db0504 --- /dev/null +++ b/EditorExtensions/Classifications/SCSS/ScssClassifierProvider.cs @@ -0,0 +1,27 @@ +//using System.ComponentModel.Composition; +//using Microsoft.CSS.Editor; +//using Microsoft.VisualStudio.Text; +//using Microsoft.VisualStudio.Text.Classification; +//using Microsoft.VisualStudio.Utilities; +//using Microsoft.Web.Editor; + +//namespace MadsKristensen.EditorExtensions +//{ +// [Export(typeof(IClassifierProvider))] +// [ContentType(ScssContentTypeDefinition.ScssContentType)] +// internal sealed class ScssClassificationProvider : IClassifierProvider +// { +// [Import] +// public IClassificationTypeRegistryService ClassificationRegistryService { get; set; } + +// public IClassifier GetClassifier(ITextBuffer textBuffer) +// { +// var classifier = ServiceManager.GetService(textBuffer); + +// if (classifier == null) +// classifier = new CssClassifier(textBuffer, new CssClassificationNameProvider(), ClassificationRegistryService); + +// return classifier; +// } +// } +//} diff --git a/EditorExtensions/Classifications/SCSS/ScssContentTypeDefinition.cs b/EditorExtensions/Classifications/SCSS/ScssContentTypeDefinition.cs new file mode 100644 index 000000000..5a5ca43ce --- /dev/null +++ b/EditorExtensions/Classifications/SCSS/ScssContentTypeDefinition.cs @@ -0,0 +1,31 @@ +//using Microsoft.VisualStudio.Utilities; +//using System.ComponentModel.Composition; + +//namespace MadsKristensen.EditorExtensions +//{ +// /// +// /// Exports the ScSS content type and file extension +// /// +// public class ScssContentTypeDefinition +// { +// public const string ScssLanguageName = "scss"; +// public const string ScssContentType = "scss"; +// public const string ScssFileExtension = ".scss"; + +// /// +// /// Exports the SaSS CSS content type +// /// +// [Export(typeof(ContentTypeDefinition))] +// [Name(ScssContentType)] +// [BaseDefinition("LESS")] +// public ContentTypeDefinition IScssContentType { get; set; } + +// /// +// /// Exports the SaSS file extension +// /// +// [Export(typeof(FileExtensionToContentTypeDefinition))] +// [ContentType(ScssContentType)] +// [FileExtension(ScssFileExtension)] +// public FileExtensionToContentTypeDefinition IScssFileExtension { get; set; } +// } +//} diff --git a/EditorExtensions/Classifications/ValueTaggerProvider.cs b/EditorExtensions/Classifications/ValueTaggerProvider.cs new file mode 100644 index 000000000..f8223f802 --- /dev/null +++ b/EditorExtensions/Classifications/ValueTaggerProvider.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Windows.Threading; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IViewTaggerProvider))] + [ContentType("css")] + [TagType(typeof(TextMarkerTag))] + internal class VendorTaggerProvider : IViewTaggerProvider + { + [Import] + internal IClassifierAggregatorService AggregatorFactory = null; + + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (textView == null || !WESettings.GetBoolean(WESettings.Keys.SyncVendorValues)) + { + return null; + } + + if (textView.TextBuffer != buffer) + { + return null; + } + + Func> sc = delegate() { return new VendorTagger(textView, buffer, this) as ITagger; }; + return buffer.Properties.GetOrCreateSingletonProperty>(sc); + } + } + + internal class VendorTagger : ITagger + { + ITextView View { get; set; } + ITextBuffer Buffer { get; set; } + SnapshotPoint? CurrentChar { get; set; } + VendorTaggerProvider Provider { get; set; } + readonly IClassifier _classifier; + private VendorClassifier _vendorClassifier; + private bool _pendingUpdate = false; + + internal VendorTagger(ITextView view, ITextBuffer buffer, VendorTaggerProvider provider) + { + View = view; + Buffer = buffer; + CurrentChar = null; + Provider = provider; + _classifier = provider.AggregatorFactory.GetClassifier(buffer); + buffer.Properties.TryGetProperty(typeof(VendorClassifier), out _vendorClassifier); + + View.Caret.PositionChanged += CaretPositionChanged; + View.LayoutChanged += ViewLayoutChanged; + } + + public event EventHandler TagsChanged; + + void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) + { + if (e.NewSnapshot != e.OldSnapshot) + { + UpdateAtCaretPosition(View.Caret.Position); + } + } + + void CaretPositionChanged(object sender, CaretPositionChangedEventArgs e) + { + UpdateAtCaretPosition(e.NewPosition); + } + + void UpdateAtCaretPosition(CaretPosition caretPosition) + { + if (!_pendingUpdate) + { + _pendingUpdate = true; + CurrentChar = caretPosition.Point.GetPoint(this.Buffer, caretPosition.Affinity); + if (!CurrentChar.HasValue) + { + return; + } + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => Update()), DispatcherPriority.ContextIdle); + } + } + + private void Update() + { + var tempEvent = TagsChanged; + if (tempEvent != null) + { + SnapshotSpan span = new SnapshotSpan(this.Buffer.CurrentSnapshot, 0, this.Buffer.CurrentSnapshot.Length); + tempEvent(this, new SnapshotSpanEventArgs(span)); + _pendingUpdate = false; + } + } + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (spans.Count == 0 || Buffer.CurrentSnapshot.Length == 0) + yield break; + + if (!CurrentChar.HasValue || CurrentChar.Value.Position >= CurrentChar.Value.Snapshot.Length) + yield break; + + SnapshotPoint currentChar = CurrentChar.Value; + if (spans[0].Snapshot != currentChar.Snapshot) + { + currentChar = currentChar.TranslateTo(spans[0].Snapshot, PointTrackingMode.Positive); + } + + var allTags = _vendorClassifier.GetClassificationSpans(spans[0]).Where(s => s.ClassificationType.Classification == ClassificationTypes._value); + foreach (var tagSpan in allTags) + { + if (tagSpan.Span.Contains(currentChar)) + { + Declaration dec = _vendorClassifier.Cache.FirstOrDefault(e => currentChar.Position > e.Start && currentChar.Position < e.AfterEnd); + if (dec != null && dec.PropertyName.Text.Length > 0 && !dec.IsVendorSpecific()) + { + foreach (Declaration vendor in _vendorClassifier.Cache.Where(d => d.Parent == dec.Parent && _vendorClassifier.GetStandardName(d) == dec.PropertyName.Text)) + { + // Manage quotes for -ms-filter + string value = Buffer.CurrentSnapshot.GetText(vendor.Colon.AfterEnd, vendor.AfterEnd - vendor.Colon.AfterEnd); + int quotes = value.StartsWith("'") || value.StartsWith("\"") ? 1 : 0; + SnapshotSpan vendorSpan = new SnapshotSpan(Buffer.CurrentSnapshot, vendor.Colon.AfterEnd + quotes, vendor.AfterEnd - vendor.Colon.AfterEnd - (quotes * 2)); + yield return new TagSpan(vendorSpan, new TextMarkerTag("vendorhighlight")); + } + + SnapshotSpan s = tagSpan.Span; + yield return new TagSpan(s, new TextMarkerTag("vendorhighlight")); + yield break; + } + } + } + } + } + + [Export(typeof(EditorFormatDefinition))] + [Name("vendorhighlight")] + [UserVisible(true)] + internal class HighlightWordFormatDefinition : MarkerFormatDefinition + { + public HighlightWordFormatDefinition() + { + this.DisplayName = "CSS Property Value Highlight"; + } + + } +} \ No newline at end of file diff --git a/EditorExtensions/Classifications/VendorClassifier.cs b/EditorExtensions/Classifications/VendorClassifier.cs new file mode 100644 index 000000000..2532e1fb8 --- /dev/null +++ b/EditorExtensions/Classifications/VendorClassifier.cs @@ -0,0 +1,235 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal static class ClassificationTypes + { + internal const string _declaration = "vendor.declaration"; + internal const string _value = "vendor.value"; + + [Export, Name(ClassificationTypes._declaration), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition VendorDeclarationClassificationType = null; + + [Export, Name(ClassificationTypes._value), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] + internal static ClassificationTypeDefinition VendorValueClassificationType = null; + } + + [Export(typeof(IClassifierProvider))] + [ContentType("css")] + internal sealed class VendorClassifierProvider : IClassifierProvider + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IClassificationTypeRegistryService Registry { get; set; } + + public IClassifier GetClassifier(ITextBuffer buffer) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => { return new VendorClassifier(Registry, buffer); }); + } + } + + internal sealed class VendorClassifier : IClassifier + { + private IClassificationTypeRegistryService _registry; + private ITextBuffer _buffer; + private CssTree _tree; + internal SortedRangeList Cache = new SortedRangeList(); + private IClassificationType _decClassification; + private IClassificationType _valClassification; + + internal VendorClassifier(IClassificationTypeRegistryService registry, ITextBuffer buffer) + { + _registry = registry; + _buffer = buffer; + _decClassification = _registry.GetClassificationType(ClassificationTypes._declaration); + _valClassification = _registry.GetClassificationType(ClassificationTypes._value); + } + + public IList GetClassificationSpans(SnapshotSpan span) + { + List spans = new List(); + if (!WESettings.GetBoolean(WESettings.Keys.SyncVendorValues) || !EnsureInitialized()) + return spans; + + var declarations = Cache.Where(d => span.End <= d.AfterEnd && d.Start >= span.Start); + foreach (Declaration dec in Cache.Where(d => d.PropertyName.Text.Length > 0 && span.Snapshot.Length >= d.AfterEnd)) + { + if (dec.IsVendorSpecific()) + { + var ss = new SnapshotSpan(span.Snapshot, dec.Start, dec.Length); + var s = new ClassificationSpan(ss, _decClassification); + spans.Add(s); + } + + int start = dec.Colon.AfterEnd; + int length = dec.AfterEnd - start; + if (span.Snapshot.Length > start + length) + { + var ss2 = new SnapshotSpan(span.Snapshot, start, length); + var s2 = new ClassificationSpan(ss2, _valClassification); + spans.Add(s2); + } + } + + return spans; + } + + public string GetStandardName(Declaration dec) + { + string name = dec.PropertyName.Text; + if (name.Length > 0 && name[0] == '-') + { + int index = name.IndexOf('-', 1) + 1; + name = index > -1 ? name.Substring(index) : name; + } + + return name; + } + + public bool EnsureInitialized() + { + if (_tree == null && WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + _tree.TreeUpdated += TreeUpdated; + _tree.ItemsChanged += TreeItemsChanged; + UpdateDeclarationCache(_tree.StyleSheet); + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + + private void UpdateDeclarationCache(ParseItem item) + { + var visitor = new CssItemCollector(true); + item.Accept(visitor); + + HashSet rules = new HashSet(); + + foreach (Declaration dec in visitor.Items) + { + RuleBlock rule = dec.Parent as RuleBlock; + if (rule == null || rules.Contains(rule)) + continue; + + var vendors = rule.Declarations.Where(d => d.IsValid && d.IsVendorSpecific()); + foreach (Declaration vendor in vendors) + { + string name = GetStandardName(vendor); + Declaration standard = rule.Declarations.FirstOrDefault(d => d.IsValid && d.PropertyName.Text == name); + + if (standard != null) + { + if (!Cache.Contains(standard)) + Cache.Add(standard); + + if (GetValueText(standard) == GetValueText(vendor) && !Cache.Contains(vendor)) + Cache.Add(vendor); + } + } + + rules.Add(rule); + } + } + + private void TreeUpdated(object sender, CssTreeUpdateEventArgs e) + { + Cache.Clear(); + UpdateDeclarationCache(e.Tree.StyleSheet); + } + + private void TreeItemsChanged(object sender, CssItemsChangedEventArgs e) + { + foreach (ParseItem item in e.DeletedItems) + { + if (Cache.Contains(item)) + Cache.Remove((Declaration)item); + } + + foreach (ParseItem item in e.InsertedItems) + { + UpdateDeclarationCache(item); + UpdateVendorValues(item); + } + } + + private void UpdateVendorValues(ParseItem item) + { + if (!WESettings.GetBoolean(WESettings.Keys.SyncVendorValues)) + return; + + Declaration dec = item.FindType(); + if (dec != null && Cache.Contains(dec) && !dec.IsVendorSpecific()) + { + // Find all vendor specifics that isn't the standard property. + var matches = Cache.Where(d => d.IsValid && d != dec && d.Parent == dec.Parent && GetStandardName(d) == dec.PropertyName.Text && d.PropertyName.Text != dec.PropertyName.Text); + + // Undo sometimes messes with the positions, so we have to make this check before proceeding. + if (!matches.Any() || dec.Text.Length < dec.Colon.AfterEnd - dec.Start || dec.Colon.AfterEnd < dec.Start) + return; + + string text = dec.Text.Substring(dec.Colon.AfterEnd - dec.Start, dec.AfterEnd - dec.Colon.AfterEnd); + using (ITextEdit edit = _buffer.CreateEdit()) + { + foreach (Declaration match in matches.Reverse()) + { + SnapshotSpan span = new SnapshotSpan(_buffer.CurrentSnapshot, match.Colon.AfterEnd, match.AfterEnd - match.Colon.AfterEnd); + if (span.GetText() != text) + edit.Replace(span, text); + } + + edit.Apply(); + } + } + } + + private string GetValueText(Declaration dec) + { + int start = dec.Colon.AfterEnd; + int length = dec.AfterEnd - start; + return _buffer.CurrentSnapshot.GetText(start, length); + } + + public event EventHandler ClassificationChanged; + + public void RaiseClassificationChanged(SnapshotSpan span) + { + var handler = this.ClassificationChanged; + if (handler != null) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => handler(this, new ClassificationChangedEventArgs(span))), DispatcherPriority.ApplicationIdle); + } + } + } + + [Export(typeof(EditorFormatDefinition))] + [UserVisible(true)] + [ClassificationType(ClassificationTypeNames = ClassificationTypes._declaration)] + [Name(ClassificationTypes._declaration)] + [Order(After = Priority.Default)] + internal sealed class VendorDeclarationFormatDefinition : ClassificationFormatDefinition + { + public VendorDeclarationFormatDefinition() + { + ForegroundOpacity = 0.5; + DisplayName = "CSS Vendor Property"; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/ArrowsCommandTarget.cs b/EditorExtensions/Commands/ArrowsCommandTarget.cs new file mode 100644 index 000000000..4b741d5ef --- /dev/null +++ b/EditorExtensions/Commands/ArrowsCommandTarget.cs @@ -0,0 +1,273 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.ComponentModel.Composition; +using System.Globalization; +using Editor = Microsoft.Web.Editor; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType(Microsoft.Web.Editor.CssContentTypeDefinition.CssContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + class NumberTextViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + textView.Properties.GetOrCreateSingletonProperty(() => new NumberTarget(textViewAdapter, textView)); + } + } + + class NumberTarget : IOleCommandTarget + { + private ITextView _textView; + private IOleCommandTarget _nextCommandTarget; + private CssTree _tree; + + public NumberTarget(IVsTextView adapter, ITextView textView) + { + this._textView = textView; + adapter.AddCommandFilter(this, out _nextCommandTarget); + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + switch (nCmdID) + { + case 2400: + if (Move(Direction.Down)) + return VSConstants.S_OK; + break; + + case 2401: + if (Move(Direction.Up)) + return VSConstants.S_OK; + break; + } + } + + return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + + private enum Direction + { + Up, + Down + } + + private bool Move(Direction direction) + { + if (!EnsureInitialized()) + return false; + + int position = _textView.Caret.Position.BufferPosition.Position; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(position); + if (item == null) + return false; + + NumericalValue unit = item.FindType(); + if (unit != null) + { + return HandleUnits(direction, unit); + } + + HexColorValue hex = item.FindType(); + if (hex != null) + { + return HandleHex(direction, hex); + } + + return false; + } + + private bool HandleUnits(Direction direction, NumericalValue item) + { + float value; + if (!float.TryParse(item.Number.Text, out value)) + return false; + + if (!AreWithinLimits(direction, value, item)) + return true; + + var span = new SnapshotSpan(_textView.Selection.SelectedSpans[0].Snapshot, item.Number.Start, item.Number.Length); + float delta = GetDelta(item.Number.Text); + string format = item.Number.Text.Contains(".") ? "#.#0" : string.Empty; + if (NumberDecimalPlaces(item.Number.Text) == 1) + format = "F1"; + + if (direction == Direction.Down) + UpdateSpan(span, (value - delta).ToString(format, CultureInfo.InvariantCulture), "Decrease value"); + else + UpdateSpan(span, (value + delta).ToString(format, CultureInfo.InvariantCulture), "Increase value"); + + return true; + } + + private static int NumberDecimalPlaces(string value) + { + if (value.IndexOf('.') == -1) + return 0; + + int s = value.IndexOf(".") + 1; // the first numbers plus decimal point + return value.Length - s; //total length minus beginning numbers and decimal = number of decimal points + } + + private static bool AreWithinLimits(Direction direction, float number, NumericalValue item) + { + UnitType type = GetUnitType(item); + switch (type) + { + case UnitType.Angle: + return (direction == Direction.Up) ? number < 360 : number > -360; + + //case UnitType.Percentage: + // return (direction == Direction.Up) ? number < 100 : number > 0; + + // Larger than zero + case UnitType.Grid: + case UnitType.Frequency: + case UnitType.Resolution: + case UnitType.Time: + return (direction == Direction.Down) ? number > 0 : true; + + case UnitType.Percentage: + case UnitType.Length: + case UnitType.Viewport: + return true; + } + + FunctionColor func = item.FindType(); + if (func != null) + { + if (func.FunctionName.Text.StartsWith("rgb", StringComparison.Ordinal)) + { + if (direction == Direction.Up) + return number < 255; + else + return number > 0; + } + + if (func.FunctionName.Text.StartsWith("hsl", StringComparison.Ordinal)) + { + if (direction == Direction.Up) + return number < 360; + else + return number > 0; + } + } + + return true; + } + + private static UnitType GetUnitType(ParseItem valueItem) + { + UnitValue unitValue = valueItem as UnitValue; + + return (unitValue != null) ? unitValue.UnitType : UnitType.Unknown; + } + + private bool HandleHex(Direction direction, HexColorValue item) + { + var model = ColorParser.TryParseColor(item.Text, ColorParser.Options.None); + + if (model != null) + { + var span = new SnapshotSpan(_textView.Selection.SelectedSpans[0].Snapshot, item.Start, item.Length); + + if (direction == Direction.Down && model.HslLightness > 0) + { + model.Format = Editor.ColorFormat.RgbHex3; + UpdateSpan(span, Editor.ColorFormatter.FormatColor(model.Darken()), "Darken color"); + } + else if (direction == Direction.Up && model.HslLightness < 1) + { + model.Format = Editor.ColorFormat.RgbHex3; + UpdateSpan(span, Editor.ColorFormatter.FormatColor(model.Brighten()), "Brighten color"); + } + + return true; + } + + return false; + } + + private static float GetDelta(string value) + { + int decimals = NumberDecimalPlaces(value); + if (decimals > 0) + { + if (decimals > 1) + return 0.01F; + else + return 0.1F; + } + + return 1F; + } + + private void UpdateSpan(SnapshotSpan span, string result, string undoTitle) + { + if (result.Length > 1) + result = result.TrimStart('0'); + + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + EditorExtensionsPackage.DTE.UndoContext.Open(undoTitle); + edit.Replace(span, result); + edit.Apply(); + EditorExtensionsPackage.DTE.UndoContext.Close(); + } + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + for (int i = 0; i < cCmds; i++) + { + switch (prgCmds[i].cmdID) + { + case 2401: // Up + case 2400: // Down + prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + return VSConstants.S_OK; + } + } + } + + return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + + public bool EnsureInitialized() + { + if (_tree == null && Microsoft.Web.Editor.WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_textView.TextBuffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/CommandTargetBase.cs b/EditorExtensions/Commands/CommandTargetBase.cs new file mode 100644 index 000000000..4d2c7dcb5 --- /dev/null +++ b/EditorExtensions/Commands/CommandTargetBase.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal abstract class CommandTargetBase : IOleCommandTarget + { + private IOleCommandTarget _nextCommandTarget; + protected IWpfTextView TextView; + + public Guid CommandGroup { get; set; } + public uint[] CommandIds { get; set; } + + public CommandTargetBase(IVsTextView adapter, IWpfTextView textView, Guid commandGroup, params uint[] commandIds) + { + this.CommandGroup = commandGroup; + this.CommandIds = commandIds; + this.TextView = textView; + adapter.AddCommandFilter(this, out _nextCommandTarget); + } + + protected abstract bool IsEnabled(); + protected abstract bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut); + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == this.CommandGroup && this.CommandIds.Contains(nCmdID)) + { + bool result = Execute(nCmdID, nCmdexecopt, pvaIn, pvaOut); + + if (result) + { + return VSConstants.S_OK; + } + } + + return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + if (pguidCmdGroup == CommandGroup) + { + for (int i = 0; i < cCmds; i++) + { + if (CommandIds.Contains(prgCmds[i].cmdID)) + { + if (IsEnabled()) + { + prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + return VSConstants.S_OK; + } + + prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_SUPPORTED;// | (uint)OLECMDF.OLECMDF_INVISIBLE; + //return VSConstants.S_OK; + } + } + } + + return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + } +} diff --git a/EditorExtensions/Commands/Css/CssAddMissingStandardCommandTarget.cs b/EditorExtensions/Commands/Css/CssAddMissingStandardCommandTarget.cs new file mode 100644 index 000000000..cb822fa46 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssAddMissingStandardCommandTarget.cs @@ -0,0 +1,105 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssAddMissingStandard : CommandTargetBase + { + private DTE2 _dte; + private readonly string[] _supported = new[] { "CSS", "LESS" }; + + public CssAddMissingStandard(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidCssCmdSet, PkgCmdIDList.addMissingStandard) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + ITextBuffer buffer = TextView.TextBuffer; + CssEditorDocument doc = new CssEditorDocument(buffer); + ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + + StringBuilder sb = new StringBuilder(buffer.CurrentSnapshot.Length); + sb.Append(buffer.CurrentSnapshot.GetText()); + + EditorExtensionsPackage.DTE.UndoContext.Open("Add Missing Standard Property"); + + string result = AddMissingStandardDeclaration(sb, doc, rootSchema); + Span span = new Span(0, buffer.CurrentSnapshot.Length); + buffer.Replace(span, result); + + var selection = EditorExtensionsPackage.DTE.ActiveDocument.Selection as TextSelection; + selection.GotoLine(1); + + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatDocument"); + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + private string AddMissingStandardDeclaration(StringBuilder sb, CssEditorDocument doc, ICssSchemaInstance rootSchema) + { + var visitor = new CssItemCollector(true); + doc.Tree.StyleSheet.Accept(visitor); + + //var items = visitor.Items.Where(d => d.IsValid && d.IsVendorSpecific()); + foreach (RuleBlock rule in visitor.Items.Reverse()) + { + HashSet list = new HashSet(); + foreach (Declaration dec in rule.Declarations.Where(d => d.IsValid && d.IsVendorSpecific()).Reverse()) + { + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, dec); + ICssCompletionListEntry entry = VendorHelpers.GetMatchingStandardEntry(dec, schema); + + if (entry != null && !list.Contains(entry.DisplayText) && !rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == entry.DisplayText)) + { + int index = dec.Text.IndexOf(":", StringComparison.Ordinal); + string standard = entry.DisplayText + dec.Text.Substring(index); + + sb.Insert(dec.AfterEnd, standard); + list.Add(entry.DisplayText); + } + } + } + + return sb.ToString(); + } + + private string GetVendorDeclarations(IEnumerable prefixes, Declaration declaration) + { + StringBuilder sb = new StringBuilder(); + string separator = true ? Environment.NewLine : " "; + + foreach (var entry in prefixes) + { + sb.Append(entry + declaration.Text + separator); + } + + return sb.ToString(); + } + + protected override bool IsEnabled() + { + var buffer = ProjectHelpers.GetCurentTextBuffer(); + + if (buffer != null && _supported.Contains(buffer.ContentType.DisplayName.ToUpperInvariant())) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssAddVendorStandardCommandTarget.cs b/EditorExtensions/Commands/Css/CssAddVendorStandardCommandTarget.cs new file mode 100644 index 000000000..3fb975d34 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssAddVendorStandardCommandTarget.cs @@ -0,0 +1,100 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssAddMissingVendor : CommandTargetBase + { + private DTE2 _dte; + private readonly string[] _supported = new[] { "CSS", "LESS" }; + + public CssAddMissingVendor(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidCssCmdSet, PkgCmdIDList.addMissingVendor) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + ITextBuffer buffer = ProjectHelpers.GetCurentTextBuffer(); + CssEditorDocument doc = new CssEditorDocument(buffer); + ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + + StringBuilder sb = new StringBuilder(buffer.CurrentSnapshot.Length); + sb.Append(buffer.CurrentSnapshot.GetText()); + + EditorExtensionsPackage.DTE.UndoContext.Open("Add Missing Vendor Specifics"); + + string result = AddMissingVendorDeclarations(sb, doc, rootSchema); + Span span = new Span(0, buffer.CurrentSnapshot.Length); + buffer.Replace(span, result); + + var selection = EditorExtensionsPackage.DTE.ActiveDocument.Selection as TextSelection; + selection.GotoLine(1); + + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatDocument"); + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + private string AddMissingVendorDeclarations(StringBuilder sb, CssEditorDocument doc, ICssSchemaInstance rootSchema) + { + var visitor = new CssItemCollector(true); + doc.Tree.StyleSheet.Accept(visitor); + + var items = visitor.Items.Where(d => d.IsValid && !d.IsVendorSpecific() && d.PropertyName.Text != "filter"); + + foreach (Declaration dec in items.Reverse()) + { + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, dec); + var missingEntries = dec.GetMissingVendorSpecifics(schema); + + if (missingEntries.Any()) + { + var missingPrefixes = missingEntries.Select(e => e.Substring(0, e.IndexOf('-', 1) + 1)); + string vendors = GetVendorDeclarations(missingPrefixes, dec); + + sb.Insert(dec.Start, vendors); + } + } + + return sb.ToString(); + } + + private string GetVendorDeclarations(IEnumerable prefixes, Declaration declaration) + { + StringBuilder sb = new StringBuilder(); + string separator = true ? Environment.NewLine : " "; + + foreach (var entry in prefixes) + { + sb.Append(entry + declaration.Text + separator); + } + + return sb.ToString(); + } + + protected override bool IsEnabled() + { + var buffer = ProjectHelpers.GetCurentTextBuffer(); + + if (buffer != null && _supported.Contains(buffer.ContentType.DisplayName.ToUpperInvariant())) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssCreationListener.cs b/EditorExtensions/Commands/Css/CssCreationListener.cs new file mode 100644 index 000000000..f4c5f2b00 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssCreationListener.cs @@ -0,0 +1,53 @@ +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType(CssContentTypeDefinition.CssContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + class CssSortPropertiesViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import] + internal IClassifierAggregatorService AggregatorService { get; set; } + + [Import] + internal ICompletionBroker CompletionBroker { get; set; } + + [Import] + internal IQuickInfoBroker QuickInfoBroker { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new CssSortProperties(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssExtractToFile(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssAddMissingStandard(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssAddMissingVendor(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssRemoveDuplicates(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new MinifySelection(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssFindReferences(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new F1Help(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssSelectBrowsers(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new RetriggerTarget(textViewAdapter, textView, CompletionBroker)); + + uint cssFormatProperties; + EditorExtensionsPackage.PriorityCommandTarget.RegisterPriorityCommandTarget(0, new CssFormatProperties(textView), out cssFormatProperties); + textView.Closed += delegate { EditorExtensionsPackage.PriorityCommandTarget.UnregisterPriorityCommandTarget(cssFormatProperties); }; + + uint cssSpeedTyping; + EditorExtensionsPackage.PriorityCommandTarget.RegisterPriorityCommandTarget(0, new SpeedTypingTarget(this, textViewAdapter, textView), out cssSpeedTyping); + textView.Closed += delegate { EditorExtensionsPackage.PriorityCommandTarget.UnregisterPriorityCommandTarget(cssSpeedTyping); }; + } + } +} diff --git a/EditorExtensions/Commands/Css/CssExtractToFileCommandTarget.cs b/EditorExtensions/Commands/Css/CssExtractToFileCommandTarget.cs new file mode 100644 index 000000000..62979a973 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssExtractToFileCommandTarget.cs @@ -0,0 +1,118 @@ +using EnvDTE80; +using Microsoft.VisualBasic; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Projection; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssExtractToFile : CommandTargetBase + { + private DTE2 _dte; + private List _possible = new List() { ".CSS", ".LESS", ".JS", ".TS" }; + + public CssExtractToFile(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidExtractCmdSet, PkgCmdIDList.ExtractSelection) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (TextView == null) + return false; + + string content = TextView.Selection.SelectedSpans[0].GetText(); + string extension = Path.GetExtension(_dte.ActiveDocument.FullName).ToLowerInvariant(); + + if (!_possible.Contains(extension.ToUpperInvariant())) + { + extension = ".css"; + } + + string name = Interaction.InputBox("Specify the name of the file", "Web Essentials", "file1" + extension).Trim(); + + if (!string.IsNullOrEmpty(name)) + { + + if (string.IsNullOrEmpty(Path.GetExtension(name))) + { + name = name + extension; + } + + string fileName = Path.Combine(Path.GetDirectoryName(_dte.ActiveDocument.FullName), name); + + if (!File.Exists(fileName)) + { + _dte.UndoContext.Open("Extract to file..."); + + using (StreamWriter writer = new StreamWriter(fileName, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + + ProjectHelpers.AddFileToActiveProject(fileName); + TextView.TextBuffer.Delete(TextView.Selection.SelectedSpans[0].Span); + _dte.ItemOperations.OpenFile(fileName); + + _dte.UndoContext.Close(); + } + else + { + MessageBox.Show("The file already exist", "Web Essentials", MessageBoxButton.OK, MessageBoxImage.Warning); + } + } + + return true; + } + + private bool IsValidTextBuffer(IWpfTextView view) + { + var projection = view.TextBuffer as IProjectionBuffer; + + if (projection != null) + { + int position = view.Caret.Position.BufferPosition.Position; + var snapshotPoint = view.Caret.Position.BufferPosition; + + var buffers = projection.SourceBuffers.Where(s => + s.ContentType.IsOfType("css") || + s.ContentType.IsOfType("javascript")); + + foreach (ITextBuffer buffer in buffers) + { + SnapshotPoint? point = view.BufferGraph.MapDownToBuffer(snapshotPoint, PointTrackingMode.Negative, buffer, PositionAffinity.Predecessor); + + if (point.HasValue) + { + return true; + } + } + + return false; + } + + return true; + } + + protected override bool IsEnabled() + { + var item = _dte.Solution.FindProjectItem(_dte.ActiveDocument.FullName); + bool hasProject = item != null && item.ContainingProject != null && !string.IsNullOrEmpty(item.ContainingProject.FullName); + + if (hasProject && TextView != null && IsValidTextBuffer(TextView) && TextView.Selection.SelectedSpans.Count > 0) + { + return TextView.Selection.SelectedSpans[0].Length > 0; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssFindReferencesCommandTarget.cs b/EditorExtensions/Commands/Css/CssFindReferencesCommandTarget.cs new file mode 100644 index 000000000..7bb93b0b5 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssFindReferencesCommandTarget.cs @@ -0,0 +1,98 @@ +using CssSorter; +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.IO; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssFindReferences : CommandTargetBase + { + private DTE2 _dte; + private CssTree _tree; + + public CssFindReferences(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, typeof(VSConstants.VSStd97CmdID).GUID, (uint)VSConstants.VSStd97CmdID.FindReferences) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (!EnsureInitialized()) + return false; + + int position = TextView.Caret.Position.BufferPosition.Position; + ParseItem item = _tree.StyleSheet.ItemBeforePosition(position); + + if (item != null && item.Parent != null) + { + Find2 find = (Find2)EditorExtensionsPackage.DTE.Find; + string types = find.FilesOfType; + bool matchCase = find.MatchCase; + bool matchWord = find.MatchWholeWord; + + find.WaitForFindToComplete = false; + find.Action = EnvDTE.vsFindAction.vsFindActionFindAll; + find.Backwards = false; + find.MatchInHiddenText = true; + find.MatchWholeWord = true; + find.MatchCase = true; + find.PatternSyntax = EnvDTE.vsFindPatternSyntax.vsFindPatternSyntaxLiteral; + find.ResultsLocation = EnvDTE.vsFindResultsLocation.vsFindResults1; + find.SearchSubfolders = true; + find.FilesOfType = "*.css;*.less;*.scss;*.sass"; + find.Target = EnvDTE.vsFindTarget.vsFindTargetSolution; + find.FindWhat = SearchText(item); + find.Execute(); + + find.FilesOfType = types; + find.MatchCase = matchCase; + find.MatchWholeWord = matchWord; + } + + return true; + } + + private string SearchText(ParseItem item) + { + if (item.Parent is Declaration) + { + return item.Text; + } + else if (item.Parent is AtDirective) + { + return "@" + item.Text; + } + + return item.Parent.Text; + } + + public bool EnsureInitialized() + { + if (_tree == null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(TextView.TextBuffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { } + } + + return _tree != null; + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssFormatCommandTarget.cs b/EditorExtensions/Commands/Css/CssFormatCommandTarget.cs new file mode 100644 index 000000000..793165d62 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssFormatCommandTarget.cs @@ -0,0 +1,56 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text.Editor; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssFormatProperties : IOleCommandTarget + { + private ITextView _textView; + + public CssFormatProperties(ITextView textView) + { + this._textView = textView; + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + switch (nCmdID) + { + case (uint)VSConstants.VSStd2KCmdID.FORMATSELECTION: + case (uint)VSConstants.VSStd2KCmdID.FORMATDOCUMENT: + if (_textView.TextBuffer.ContentType.IsOfType("SCSS")) + { + return VSConstants.S_OK; + } + + break; + } + } + + return (int)(Constants.MSOCMDERR_E_FIRST); + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + for (int i = 0; i < cCmds; i++) + { + switch (prgCmds[i].cmdID) + { + case (uint)VSConstants.VSStd2KCmdID.FORMATSELECTION: + case (uint)VSConstants.VSStd2KCmdID.FORMATDOCUMENT: + prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + return VSConstants.S_OK; + } + } + } + + return (int)(Constants.OLECMDERR_E_NOTSUPPORTED); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssRemoveDuplicatesCommandTarget.cs b/EditorExtensions/Commands/Css/CssRemoveDuplicatesCommandTarget.cs new file mode 100644 index 000000000..35204db17 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssRemoveDuplicatesCommandTarget.cs @@ -0,0 +1,98 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssRemoveDuplicates : CommandTargetBase + { + private DTE2 _dte; + private readonly string[] _supported = new[] { "CSS", "LESS" }; + + public CssRemoveDuplicates(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidCssCmdSet, PkgCmdIDList.cssRemoveDuplicates) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + ITextBuffer buffer = ProjectHelpers.GetCurentTextBuffer(); + CssEditorDocument doc = new CssEditorDocument(buffer); + + StringBuilder sb = new StringBuilder(buffer.CurrentSnapshot.Length); + sb.Append(buffer.CurrentSnapshot.GetText()); + + EditorExtensionsPackage.DTE.UndoContext.Open("Remove Duplicate Properties"); + + string result = RemoveDuplicateProperties(sb, doc); + Span span = new Span(0, buffer.CurrentSnapshot.Length); + buffer.Replace(span, result); + + var selection = EditorExtensionsPackage.DTE.ActiveDocument.Selection as TextSelection; + selection.GotoLine(1); + + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatDocument"); + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + private string RemoveDuplicateProperties(StringBuilder sb, CssEditorDocument doc) + { + var visitor = new CssItemCollector(true); + doc.Tree.StyleSheet.Accept(visitor); + + foreach (RuleBlock rule in visitor.Items.Reverse()) + { + HashSet list = new HashSet(); + + foreach (Declaration dec in rule.Declarations.Reverse()) + { + if (list.Contains(dec.Text)) + { + sb.Remove(dec.Start, dec.Length); + continue; + } + + list.Add(dec.Text); + } + } + + return sb.ToString(); + } + + private string GetVendorDeclarations(IEnumerable prefixes, Declaration declaration) + { + StringBuilder sb = new StringBuilder(); + string separator = true ? Environment.NewLine : " "; + + foreach (var entry in prefixes) + { + sb.Append(entry + declaration.Text + separator); + } + + return sb.ToString(); + } + + protected override bool IsEnabled() + { + var buffer = ProjectHelpers.GetCurentTextBuffer(); + + if (buffer != null && _supported.Contains(buffer.ContentType.DisplayName.ToUpperInvariant())) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssSaveListener.cs b/EditorExtensions/Commands/Css/CssSaveListener.cs new file mode 100644 index 000000000..1c2081d89 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssSaveListener.cs @@ -0,0 +1,70 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewCreationListener))] + [ContentType(Microsoft.Web.Editor.CssContentTypeDefinition.CssContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + public class CssSaveListener : IWpfTextViewCreationListener + { + private ITextDocument _document; + + public void TextViewCreated(IWpfTextView textView) + { + textView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out _document); + + if (_document != null) + { + _document.FileActionOccurred += document_FileActionOccurred; + } + } + + void document_FileActionOccurred(object sender, TextDocumentFileActionEventArgs e) + { + if (!WESettings.GetBoolean(WESettings.Keys.EnableCssMinification)) + return; + + if (e.FileActionType == FileActionTypes.ContentSavedToDisk && e.FilePath.EndsWith(".css")) + { + string minFile = e.FilePath.Insert(e.FilePath.Length - 3, "min."); + + if (File.Exists(minFile) && EditorExtensionsPackage.DTE.Solution.FindProjectItem(minFile) != null) + { + Task.Run(() => + { + Minify(e.FilePath, minFile); + }); + } + } + } + + public static void Minify(string file, string minFile) + { + if (file.EndsWith(".min.css")) + return; + + try + { + string content = MinifyFileMenu.MinifyString(".css", File.ReadAllText(file)); + //Minifier minifier = new Minifier(); + //string content = minifier.MinifyStyleSheet(File.ReadAllText(file)); + + ProjectHelpers.CheckOutFileFromSourceControl(minFile); + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + } + catch + { + Logger.Log("Error minifying: " + file); + } + } + } +} diff --git a/EditorExtensions/Commands/Css/CssSelectBrowsers.cs b/EditorExtensions/Commands/Css/CssSelectBrowsers.cs new file mode 100644 index 000000000..a0493b1a9 --- /dev/null +++ b/EditorExtensions/Commands/Css/CssSelectBrowsers.cs @@ -0,0 +1,71 @@ +using EnvDTE80; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Projection; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssSelectBrowsers : CommandTargetBase + { + private DTE2 _dte; + private List _possible = new List() { ".CSS", ".LESS", ".SCSS" }; + + public CssSelectBrowsers(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidMinifyCmdSet, PkgCmdIDList.SelectBrowsers) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + BrowserSelector selector = new BrowserSelector(); + selector.ShowDialog(); + + return true; + } + + private bool IsValidTextBuffer(IWpfTextView view) + { + var projection = view.TextBuffer as IProjectionBuffer; + + if (projection != null) + { + int position = view.Caret.Position.BufferPosition.Position; + var snapshotPoint = view.Caret.Position.BufferPosition; + + var buffers = projection.SourceBuffers.Where(s => s.ContentType.IsOfType("css")); + + foreach (ITextBuffer buffer in buffers) + { + SnapshotPoint? point = view.BufferGraph.MapDownToBuffer(snapshotPoint, PointTrackingMode.Negative, buffer, PositionAffinity.Predecessor); + + if (point.HasValue) + { + return true; + } + } + + return false; + } + + return true; + } + + protected override bool IsEnabled() + { + var item = _dte.Solution.FindProjectItem(_dte.ActiveDocument.FullName); + bool hasProject = item != null && item.ContainingProject != null && !string.IsNullOrEmpty(item.ContainingProject.FullName); + + if (hasProject && TextView != null && IsValidTextBuffer(TextView)) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/CssSortPropertiesCommandTarget.cs b/EditorExtensions/Commands/Css/CssSortPropertiesCommandTarget.cs new file mode 100644 index 000000000..b88a4bd6b --- /dev/null +++ b/EditorExtensions/Commands/Css/CssSortPropertiesCommandTarget.cs @@ -0,0 +1,69 @@ +using CssSorter; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.IO; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class CssSortProperties : CommandTargetBase + { + private DTE2 _dte; + private readonly string[] _supported = new[] { "CSS", "LESS" }; + //private static uint[] _commandIds = new uint[] { PkgCmdIDList.sortCssProperties }; + + public CssSortProperties(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidCssCmdSet, PkgCmdIDList.sortCssProperties) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + TextDocument doc = _dte.ActiveDocument.Object("TextDocument") as TextDocument; + EditPoint edit = doc.StartPoint.CreateEditPoint(); + string text = SortProperties(edit.GetText(doc.EndPoint)); + + _dte.UndoContext.Open("Sort All Properties"); + + edit.ReplaceText(doc.EndPoint, text, (int)vsFindOptions.vsFindOptionsNone); + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatDocument"); + doc.Selection.MoveToPoint(doc.StartPoint); + + _dte.UndoContext.Close(); + + return true; + } + + private string SortProperties(string text) + { + Sorter sorter = new Sorter(); + + if (Path.GetExtension(_dte.ActiveDocument.FullName) == ".css") + { + return sorter.SortStyleSheet(text); + } + else if (Path.GetExtension(_dte.ActiveDocument.FullName) == ".less") + { + return sorter.SortLess(text); + } + + return text; + } + + protected override bool IsEnabled() + { + var buffer = ProjectHelpers.GetCurentTextBuffer(); + + if (buffer != null && _supported.Contains(buffer.ContentType.DisplayName.ToUpperInvariant())) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/F1HelpCommandTarget.cs b/EditorExtensions/Commands/Css/F1HelpCommandTarget.cs new file mode 100644 index 000000000..36e02cc7b --- /dev/null +++ b/EditorExtensions/Commands/Css/F1HelpCommandTarget.cs @@ -0,0 +1,111 @@ +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class F1Help : CommandTargetBase + { + private CssTree _tree; + + public F1Help(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, typeof(VSConstants.VSStd97CmdID).GUID, (uint)VSConstants.VSStd97CmdID.F1Help) + { } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (!EnsureInitialized()) + return false; + + int position = TextView.Caret.Position.BufferPosition.Position; + ParseItem item = _tree.StyleSheet.ItemBeforePosition(position); + + if (item == null) + return false; + + return SchemaLookup(item); + } + + private delegate ICssCompletionListEntry Reference(string name); + + private bool SchemaLookup(ParseItem item) + { + if (item is ClassSelector || item is IdSelector || item is ItemName || item.Parent is RuleBlock || item.Parent is StyleSheet) + return false; + + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaRootForBuffer(TextView.TextBuffer); + + Declaration dec = item.FindType(); + if (dec != null && dec.PropertyName != null) + return OpenReferenceUrl(schema.GetProperty, dec.PropertyName.Text, "http://realworldvalidator.com/css/properties/"); + + PseudoClassFunctionSelector pseudoClassFunction = item.FindType(); + if (pseudoClassFunction != null) + return OpenReferenceUrl(schema.GetPseudo, pseudoClassFunction.Colon.Text + pseudoClassFunction.Function.FunctionName.Text + ")", "http://realworldvalidator.com/css/pseudoclasses/"); + + PseudoElementFunctionSelector pseudoElementFunction = item.FindType(); + if (pseudoElementFunction != null) + return OpenReferenceUrl(schema.GetPseudo, pseudoElementFunction.DoubleColon.Text + pseudoElementFunction.Function.FunctionName.Text + ")", "http://realworldvalidator.com/css/pseudoelements/"); + + PseudoElementSelector pseudoElement = item.FindType(); + if (pseudoElement != null && pseudoElement.PseudoElement != null) + return OpenReferenceUrl(schema.GetPseudo, pseudoElement.DoubleColon.Text + pseudoElement.PseudoElement.Text, "http://realworldvalidator.com/css/pseudoelements/"); + + PseudoClassSelector pseudoClass = item.FindType(); + if (pseudoClass != null && pseudoClass.PseudoClass != null) + return OpenReferenceUrl(schema.GetPseudo, pseudoClass.Colon.Text + pseudoClass.PseudoClass.Text, "http://realworldvalidator.com/css/pseudoclasses/"); + + AtDirective directive = item.FindType(); + if (directive != null) + return OpenReferenceUrl(schema.GetAtDirective, directive.At.Text + directive.Keyword.Text, "http://realworldvalidator.com/css/atdirectives/"); + + return false; + } + + private bool OpenReferenceUrl(Reference reference, string name, string baseUrl) + { + ICssCompletionListEntry entry = reference.Invoke(name); + if (entry != null) + { + string standardsReference = entry.GetAttribute("standard-reference"); + string text = entry.DisplayText; + Uri url; + + if (Uri.TryCreate(baseUrl + text, UriKind.Absolute, out url)) + { + System.Diagnostics.Process.Start(url.ToString()); + return true; + } + } + + return false; + } + + public bool EnsureInitialized() + { + if (_tree == null && Microsoft.Web.Editor.WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(TextView.TextBuffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { } + } + + return _tree != null; + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/RetriggerCommandTarget.cs b/EditorExtensions/Commands/Css/RetriggerCommandTarget.cs new file mode 100644 index 000000000..f99d9156d --- /dev/null +++ b/EditorExtensions/Commands/Css/RetriggerCommandTarget.cs @@ -0,0 +1,62 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.ComponentModel.Composition; +using System.Runtime.InteropServices; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal class RetriggerTarget : IOleCommandTarget + { + private ITextView _textView; + private IOleCommandTarget _nextCommandTarget; + private ICompletionBroker _broker; + + public RetriggerTarget(IVsTextView adapter, ITextView textView, ICompletionBroker broker) + { + _textView = textView; + _broker = broker; + adapter.AddCommandFilter(this, out _nextCommandTarget); + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) + { + char typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); + + switch (typedChar) + { + case '!': + case '(': + case '/': + Retrigger(); + break; + } + } + + return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + + private void Retrigger() + { + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => + { + CssCompletionController.FromView(_textView).OnShowMemberList(true); + }), DispatcherPriority.Normal, null); + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Css/SpeedTyping.cs b/EditorExtensions/Commands/Css/SpeedTyping.cs new file mode 100644 index 000000000..6cf01315c --- /dev/null +++ b/EditorExtensions/Commands/Css/SpeedTyping.cs @@ -0,0 +1,389 @@ +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Windows.Forms; +using System.Windows.Input; + +namespace MadsKristensen.EditorExtensions +{ + internal class SpeedTypingTarget : IOleCommandTarget + { + private IWpfTextView _textView; + private ICompletionBroker _broker; + private IQuickInfoBroker _QuickInfobroker; + private IClassifierAggregatorService _aggregator; + private DTE2 _dte; + private CssTree _tree; + + public SpeedTypingTarget(CssSortPropertiesViewCreationListener componentContext, IVsTextView adapter, IWpfTextView textView) + { + this._dte = EditorExtensionsPackage.DTE; + this._textView = textView; + this._aggregator = componentContext.AggregatorService; + this._broker = componentContext.CompletionBroker; + this._QuickInfobroker = componentContext.QuickInfoBroker; + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + //foreach (OutputWindowPane item in WebEssentialsPackage.dte.ToolWindows.OutputWindow.OutputWindowPanes) + //{ + // item.OutputString(nCmdID.ToString() + Environment.NewLine); + //} + + if (pguidCmdGroup == VSConstants.VSStd2K && WESettings.GetBoolean(WESettings.Keys.EnableSpeedTyping)) + { + switch ((VSConstants.VSStd2KCmdID)nCmdID) + { + case VSConstants.VSStd2KCmdID.RETURN: + if (Keyboard.IsKeyDown(Key.RightShift) || Keyboard.IsKeyDown(Key.LeftShift)) + { + if (Jump()) return + VSConstants.S_OK; + } + else + { + CommitStatementCompletion(); + if (Process(true, true, true) == VSConstants.S_OK) return VSConstants.S_OK; + } + break; + + case VSConstants.VSStd2KCmdID.TAB: + var completion = CommitStatementCompletion(); + if (Process(false, true, false) == VSConstants.S_OK || completion) return VSConstants.S_OK; + break; + } + } + + return (int)(Constants.MSOCMDERR_E_FIRST); + } + + private bool Jump() + { + if (!EnsureInitialized()) + return false; + + int position = _textView.Caret.Position.BufferPosition.Position; + ParseItem item = _tree.StyleSheet.ItemBeforePosition(position); + + if (item != null) + { + RuleBlock rule = item.FindType(); + Declaration dec = item.FindType(); + + if (rule != null && dec != null) + { + CommitStatementCompletion(); + + var line = _textView.TextSnapshot.GetLineFromPosition(position); + string text = line.Extent.GetText().TrimEnd(); + + if (!string.IsNullOrWhiteSpace(text) && !text.EndsWith(";")) + { + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + edit.Replace(line.Extent, text + ";"); + edit.Apply(); + } + } + + EditorExtensionsPackage.ExecuteCommand("Edit.FormatSelection"); + + SnapshotPoint point = new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, rule.AfterEnd); + _textView.Caret.MoveTo(point); + _textView.ViewScroller.EnsureSpanVisible(new SnapshotSpan(point, 0)); + return true; + } + } + + return false; + } + + //private int JumpOut() + //{ + // int result = VSConstants.S_FALSE; + // var span = _textView.Selection.SelectedSpans[0]; + // var position = span.Start.Position; + // var line = span.Start.GetContainingLine(); + // var classifications = _aggregator.GetClassifier(_textView.TextBuffer).GetClassificationSpans(line.Extent); + + // _dte.UndoContext.Open("Jump out of brace"); + // try + // { + // foreach (var classification in classifications) + // { + // if (IsPropertyValue(classification) && IsPropertyValueEligible(line, position)) + // { + // CommitStatementCompletion(); + // line = _textView.TextSnapshot.GetLineFromPosition(position); + // using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + // { + // edit.Replace(line.Extent, line.Extent.GetText().TrimEnd() + ";"); + // edit.Apply(); + // } + // } + // else if (IsSelector(classification) || (IsPropertyName(classification) && !line.Extent.GetText().Contains(":"))) + // { + // return VSConstants.S_FALSE; + // } + // } + + // var text = _textView.TextSnapshot.GetText(); + // int start = text.LastIndexOf('{', position - 1); + // int middle = text.IndexOf('{', position - 1); + // int end = text.IndexOf('}', position - 1); + // int emptyLines = ResolveEmptyLines(end); + + // string blanks = string.Empty; + // if (emptyLines < 3) + // { + // for (int i = 0; i < (3 - emptyLines); i++) + // { + // blanks += "\n"; + // } + // } + + // if ((end < middle || middle == -1) && start < position && end > position) + // { + // using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + // { + // edit.Replace(_textView.TextSnapshot.GetLineFromPosition(end).Extent, "}" + blanks); + + // if (string.IsNullOrWhiteSpace(line.GetText())) + // { + // edit.Delete(line.ExtentIncludingLineBreak); + // end = end - line.ExtentIncludingLineBreak.Length; + // } + + // edit.Apply(); + // result = VSConstants.S_OK; + // } + + // _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot, end + 3)); + // _broker.DismissAllSessions(_textView); + // DismissQuickInfo(); + // } + // } + // finally + // { + // _dte.UndoContext.Close(); + // } + + // return result; + //} + + //private int ResolveEmptyLines(int end) + //{ + // if (end == -1 || _textView.TextSnapshot.GetLineNumberFromPosition(end) == _textView.TextSnapshot.LineCount) + // return 0; + + // int emptyLines = 0; + // int currentLine = _textView.TextSnapshot.GetLineFromPosition(end).LineNumber + 1; + // while ((currentLine + emptyLines) < _textView.TextSnapshot.LineCount) + // { + // if (string.IsNullOrWhiteSpace(_textView.TextSnapshot.GetLineFromLineNumber(currentLine + emptyLines).GetText())) + // { + // emptyLines++; + // } + // else + // { + // break; + // } + // } + // return emptyLines; + //} + + private int Process(bool selector, bool name, bool value) + { + if (!EnsureInitialized()) + return VSConstants.S_FALSE; + + var span = _textView.Selection.SelectedSpans[0]; + var line = span.Start.GetContainingLine(); + var position = span.Start.Position;// -(line.Length - line.GetText().TrimEnd().Length); + var classifications = _aggregator.GetClassifier(_textView.TextBuffer).GetClassificationSpans(line.Extent); + + foreach (var classification in classifications) + { + if (selector && IsSelector(classification) && IsSelectorEligible(line, position)) + { + return InsertBraces(line); + } + else if (name && IsPropertyName(classification) && IsPropertyNameEligible(line)) + { + DismissQuickInfo(); + return InsertColon(position); + } + else if (value && IsPropertyValue(classification) && IsPropertyValueEligible(line, position)) + { + DismissQuickInfo(); + return InsertSemiColon(line); + } + } + + return VSConstants.S_FALSE; + } + + private static bool IsSelector(ClassificationSpan classification) + { + return classification.ClassificationType.Classification == "CSS Selector"; + } + + private static bool IsPropertyName(ClassificationSpan classification) + { + return classification.ClassificationType.Classification == "CSS Property Name"; + } + + private static bool IsPropertyValue(ClassificationSpan classification) + { + return classification.ClassificationType.Classification == "CSS Property Value"; + } + + private bool IsSelectorEligible(ITextSnapshotLine line, int position) + { + string text = line.GetText(); + if (text.IndexOf('{') > -1) + return false; + + if (text.Trim().EndsWith(",", StringComparison.Ordinal)) + return false; + + if (line.LineNumber + 1 < line.Snapshot.LineCount) + { + var next = line.Snapshot.GetLineFromLineNumber(line.LineNumber + 1); + if (next.GetText().Trim().StartsWith("{", StringComparison.Ordinal)) + return false; + } + + return true; + } + + private bool IsPropertyValueEligible(ITextSnapshotLine line, int position) + { + string text = line.GetText(); + int diff = text.Length - text.TrimEnd().Length; + + if (line.End.Position - diff > position) + return false; + + if (text.IndexOf(';') > -1) + return false; + + return true; + } + + private bool IsPropertyNameEligible(ITextSnapshotLine line) + { + return !line.GetText().Contains(":"); + } + + private bool CommitStatementCompletion() + { + bool value = _broker.IsCompletionActive(_textView); + + if (_broker.IsCompletionActive(_textView)) + { + _broker.GetSessions(_textView)[0].Commit(); + } + + return value; + } + + private void DismissQuickInfo() + { + if (_QuickInfobroker.IsQuickInfoActive(_textView)) + _QuickInfobroker.GetSessions(_textView)[0].Dismiss(); + } + + private int InsertBraces(ITextSnapshotLine line) + { + string text = line.GetText(); + + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + _dte.UndoContext.Open("Insert braces"); + edit.Replace(line.Extent, text.TrimEnd() + " {\n\t\n}"); + edit.Apply(); + _dte.UndoContext.Close(); + } + + SendKeys.Send("{LEFT}{LEFT}^( )"); + return VSConstants.S_OK; + } + + private int InsertColon(int position) + { + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + _dte.UndoContext.Open("Insert braces"); + edit.Insert(position, ":"); + edit.Apply(); + _dte.UndoContext.Close(); + } + + SendKeys.Send(" "); + + return VSConstants.S_OK; + } + + private int InsertSemiColon(ITextSnapshotLine line) + { + string text = line.GetText(); + + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + _dte.UndoContext.Open("Insert braces"); + edit.Replace(line.Extent, text.TrimEnd() + ";\n\t"); + edit.Apply(); + _dte.UndoContext.Close(); + } + + //SendKeys.Send("^( )"); + return VSConstants.S_OK; + } + + public bool EnsureInitialized() + { + if (_tree == null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_textView.TextBuffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + //if (WESettings.GetBoolean(WESettings.Keys.EnableSpeedTyping)) + //{ + // for (int i = 0; i < cCmds; i++) + // { + // switch ((VSConstants.VSStd2KCmdID)prgCmds[i].cmdID) + // { + // case VSConstants.VSStd2KCmdID.RETURN: + // prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + // return VSConstants.S_OK; + // } + // } + //} + + //return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + return (int)(Constants.OLECMDERR_E_NOTSUPPORTED); + } + } +} diff --git a/EditorExtensions/Commands/FeatureEnabler.cs b/EditorExtensions/Commands/FeatureEnabler.cs new file mode 100644 index 000000000..4124c49f3 --- /dev/null +++ b/EditorExtensions/Commands/FeatureEnabler.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Microsoft.VisualStudio.JavaScript.Web.Extensions.Shared; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IFeatureEnabler))] + internal class FeatureEnabler : IFeatureEnabler + { + private static string[] _enabledFeatures = + { + FeatureManager.Features.DocCommentExtension, + FeatureManager.Features.DocCommentScaffolding + }; + + public IEnumerable EnabledFeatures + { + get + { + return _enabledFeatures; + } + } + } +} diff --git a/EditorExtensions/Commands/HTML/ContractSelectionTarget.cs b/EditorExtensions/Commands/HTML/ContractSelectionTarget.cs new file mode 100644 index 000000000..97c2e06ac --- /dev/null +++ b/EditorExtensions/Commands/HTML/ContractSelectionTarget.cs @@ -0,0 +1,91 @@ +using Microsoft.Html.Core; +using Microsoft.Html.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class ContactSelection : CommandTargetBase + { + private IWpfTextView _view; + private ITextBuffer _buffer; + + public ContactSelection(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidFormattingCmdSet, PkgCmdIDList.ContractSelection) + { + _view = textView; + _buffer = textView.TextBuffer; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + HtmlEditorDocument document = HtmlEditorDocument.FromTextView(_view); + var tree = document.HtmlEditorTree; + + int start = _view.Selection.Start.Position.Position; + int end = _view.Selection.End.Position.Position; + + ElementNode tag = null; + AttributeNode attr = null; + + tree.GetPositionElement(start + 1, out tag, out attr); + + if (tag == null) + return false; + + if (tag.EndTag != null && tag.StartTag.Start == start && tag.EndTag.End == end) + { + Select(tag.InnerRange.Start, tag.InnerRange.Length); + } + else if (tag.Children.Count > 0) + { + var current = NodeAtCaret(tree); + var child = ChildNode(current, tag); + + if (tag.Children.Contains(child)) + Select(child.Start, child.OuterRange.Length); + else + Select(tag.Children[0].Start, tag.Children[0].End - tag.Children[0].Start); + } + + return true; + } + + private ElementNode ChildNode(ElementNode deepChild, ElementNode parent) + { + if (deepChild.Parent != parent) + { + return ChildNode(deepChild.Parent, parent); + } + + return deepChild; + } + + private ElementNode NodeAtCaret(HtmlEditorTree tree) + { + int start = _view.Caret.Position.BufferPosition.Position; + + ElementNode tag = null; + AttributeNode attr = null; + + tree.GetPositionElement(start, out tag, out attr); + + return tag; + } + + private void Select(int start, int length) + { + var span = new SnapshotSpan(_buffer.CurrentSnapshot, start, length); + _view.Selection.Select(span, false); + } + + protected override bool IsEnabled() + { + return true; + } + + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/HTML/ExpandSelectionTarget.cs b/EditorExtensions/Commands/HTML/ExpandSelectionTarget.cs new file mode 100644 index 000000000..816342793 --- /dev/null +++ b/EditorExtensions/Commands/HTML/ExpandSelectionTarget.cs @@ -0,0 +1,70 @@ +using Microsoft.Html.Core; +using Microsoft.Html.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class ExpandSelection : CommandTargetBase + { + private IWpfTextView _view; + private ITextBuffer _buffer; + + public ExpandSelection(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidFormattingCmdSet, PkgCmdIDList.ExpandSelection) + { + _view = textView; + _buffer = textView.TextBuffer; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + HtmlEditorDocument document = HtmlEditorDocument.FromTextView(_view); + var tree = document.HtmlEditorTree; + + int start = _view.Selection.Start.Position.Position; + int end = _view.Selection.End.Position.Position; + + ElementNode tag = null; + AttributeNode attr = null; + + tree.GetPositionElement(start, out tag, out attr); + + if (tag == null) + return false; + + if (tag.EndTag != null && tag.StartTag.End == start && tag.EndTag.Start == end) + { + Select(tag.Start, tag.OuterRange.Length); + } + else if (tag.EndTag != null && tag.StartTag.Start < start && tag.EndTag.End > end) + { + Select(tag.InnerRange.Start, tag.InnerRange.Length); + } + else if (tag.IsSelfClosing() && tag.Start < start && tag.End > end) + { + Select(tag.Start, tag.OuterRange.Length); + } + else if (tag.Parent != null) + { + Select(tag.Parent.Start, tag.Parent.OuterRange.Length); + } + + return true; + } + + private void Select(int start, int length) + { + var span = new SnapshotSpan(_buffer.CurrentSnapshot, start, length); + _view.Selection.Select(span, false); + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/HTML/HtmlCreationListener.cs b/EditorExtensions/Commands/HTML/HtmlCreationListener.cs new file mode 100644 index 000000000..4b728d98f --- /dev/null +++ b/EditorExtensions/Commands/HTML/HtmlCreationListener.cs @@ -0,0 +1,54 @@ +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType("HTML")] + [ContentType("HTMLX")] + [TextViewRole(PredefinedTextViewRoles.Document)] + class HtmlViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import] + internal ICompletionBroker CompletionBroker { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new ZenCoding(textViewAdapter, textView, CompletionBroker)); + + //uint zenCoding; + //EditorExtensionsPackage.PriorityCommandTarget.RegisterPriorityCommandTarget(0, new ZenCoding(textViewAdapter, textView, CompletionBroker), out zenCoding); + //textView.Closed += delegate { EditorExtensionsPackage.PriorityCommandTarget.UnregisterPriorityCommandTarget(zenCoding); }; + } + } + + [Export(typeof(IVsTextViewCreationListener))] + [ContentType("HTMLX")] + [TextViewRole(PredefinedTextViewRoles.Document)] + class HtmlxViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import] + internal ICompletionBroker CompletionBroker { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new SurroundWith(textViewAdapter, textView, CompletionBroker)); + textView.Properties.GetOrCreateSingletonProperty(() => new ExpandSelection(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new ContactSelection(textViewAdapter, textView)); + } + } +} diff --git a/EditorExtensions/Commands/HTML/SurroundWithTarget.cs b/EditorExtensions/Commands/HTML/SurroundWithTarget.cs new file mode 100644 index 000000000..9eb449c4d --- /dev/null +++ b/EditorExtensions/Commands/HTML/SurroundWithTarget.cs @@ -0,0 +1,90 @@ +using Microsoft.Html.Core; +using Microsoft.Html.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class SurroundWith : CommandTargetBase + { + private ICompletionBroker _broker; + private IWpfTextView _view; + private ITextBuffer _buffer; + + public SurroundWith(IVsTextView adapter, IWpfTextView textView, ICompletionBroker broker) + : base(adapter, textView, GuidList.guidFormattingCmdSet, PkgCmdIDList.SurroundWith) + { + _broker = broker; + _view = textView; + _buffer = textView.TextBuffer; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (_view.Selection.IsEmpty) + { + return HandleElement(); + } + else + { + int start = _view.Selection.Start.Position.Position; + int end = _view.Selection.End.Position.Position; + Update(start, end); + return true; + } + + return false; + } + + private bool HandleElement() + { + HtmlEditorDocument document = HtmlEditorDocument.FromTextView(_view); + var tree = document.HtmlEditorTree; + + int position = _view.Caret.Position.BufferPosition.Position; + + ElementNode tag = null; + AttributeNode attr = null; + + tree.GetPositionElement(position, out tag, out attr); + + if (tag != null && (tag.EndTag != null || tag.IsSelfClosing())) + { + int start = tag.Start; + int end = tag.End; + + Update(start, end); + return true; + } + + return false; + } + + private void Update(int start, int end) + { + EditorExtensionsPackage.DTE.UndoContext.Open("Surround with..."); + + using (var edit = _buffer.CreateEdit()) + { + edit.Insert(end, "

"); + edit.Insert(start, "

"); + edit.Apply(); + } + + SnapshotPoint point = new SnapshotPoint(_buffer.CurrentSnapshot, start + 1); + + _view.Caret.MoveTo(point); + _view.Selection.Select(new SnapshotSpan(_buffer.CurrentSnapshot, point, 1), false); + + EditorExtensionsPackage.DTE.UndoContext.Close(); + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/HTML/ZenCodingCommandTarget.cs b/EditorExtensions/Commands/HTML/ZenCodingCommandTarget.cs new file mode 100644 index 000000000..2831334f1 --- /dev/null +++ b/EditorExtensions/Commands/HTML/ZenCodingCommandTarget.cs @@ -0,0 +1,301 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Projection; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Threading; +using ZenCoding; + +namespace MadsKristensen.EditorExtensions +{ + internal class ZenCoding : CommandTargetBase + { + private ICompletionBroker _broker; + private ITrackingSpan _trackingSpan; + + private static Regex _bracket = new Regex(@"<([a-z0-9]*)\b[^>]*>([^<]*)", RegexOptions.IgnoreCase); + private static Regex _quotes = new Regex("(=\"()\")", RegexOptions.IgnoreCase); + + public ZenCoding(IVsTextView adapter, IWpfTextView textView, ICompletionBroker broker) + : base(adapter, textView, typeof(VSConstants.VSStd2KCmdID).GUID, 4, 5) + { + _broker = broker; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (commandId == 4 && !_broker.IsCompletionActive(TextView)) + { + if (WESettings.GetBoolean(WESettings.Keys.EnableHtmlZenCoding)) + { + if (InvokeZenCoding()) + { + return true; + } + else if (MoveToNextEmptySlot()) + { + return true; + } + } + } + else if (commandId == 5 && !_broker.IsCompletionActive(TextView)) + { + if (WESettings.GetBoolean(WESettings.Keys.EnableHtmlZenCoding) && MoveToPrevEmptySlot()) + { + return true; + } + } + + return false; + } + + private bool MoveToNextEmptySlot() + { + if (_trackingSpan == null) + return false; + + int position = TextView.Caret.Position.BufferPosition.Position + 1; + Span ts = _trackingSpan.GetSpan(TextView.TextBuffer.CurrentSnapshot); + + if (ts.Contains(position)) + { + Span span = new Span(position, ts.End - position); + SetCaret(span, false); + return true; + } + + return false; + } + + private bool MoveToPrevEmptySlot() + { + if (_trackingSpan == null) + return false; + + int position = TextView.Caret.Position.BufferPosition.Position; + + if (position > 0) + { + Span ts = _trackingSpan.GetSpan(TextView.TextBuffer.CurrentSnapshot); + + if (ts.Contains(position - 1)) + { + Span span = new Span(ts.Start, position - ts.Start - 1); + SetCaret(span, true); + return true; + } + } + + return false; + } + + private bool InvokeZenCoding() + { + Span zenSpan = GetText(); + + if (zenSpan.Length == 0 || TextView.Selection.SelectedSpans[0].Length > 0 || !IsValidTextBuffer()) + return false; + + string zenSyntax = TextView.TextBuffer.CurrentSnapshot.GetText(zenSpan); + + Parser parser = new Parser(); + string result = parser.Parse(zenSyntax, ZenType.HTML); + + if (!string.IsNullOrEmpty(result)) + { + EditorExtensionsPackage.DTE.UndoContext.Open("ZenCoding"); + + ITextSelection selection = UpdateTextBuffer(zenSpan, result); + Span newSpan = new Span(zenSpan.Start, selection.SelectedSpans[0].Length); + + if (result.Count(c => c == '>') > 2) + { + _trackingSpan = TextView.TextBuffer.CurrentSnapshot.CreateTrackingSpan(newSpan, SpanTrackingMode.EdgeExclusive); + } + + selection.Clear(); + + EditorExtensionsPackage.DTE.UndoContext.Close(); + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => SetCaret(newSpan, false)), DispatcherPriority.Normal, null); + + return true; + } + + return false; + } + + private bool IsValidTextBuffer() + { + var projection = TextView.TextBuffer as IProjectionBuffer; + + if (projection != null) + { + int position = TextView.Caret.Position.BufferPosition.Position; + var snapshotPoint = TextView.Caret.Position.BufferPosition; + + var buffers = projection.SourceBuffers.Where( + s => + !s.ContentType.IsOfType("html") + && !s.ContentType.IsOfType("htmlx") + && !s.ContentType.IsOfType("inert") + && !s.ContentType.IsOfType("CSharp") + && !s.ContentType.IsOfType("VisualBasic") + && !s.ContentType.IsOfType("RoslynCSharp") + && !s.ContentType.IsOfType("RoslynVisualBasic")); + + + foreach (ITextBuffer buffer in buffers) + { + SnapshotPoint? point = TextView.BufferGraph.MapDownToBuffer(snapshotPoint, PointTrackingMode.Negative, buffer, PositionAffinity.Predecessor); + + if (point.HasValue) + { + return false; + } + } + } + + return true; + } + + + //private bool IsValidTextBuffer() + //{ + // IProjectionBuffer projection = _textView.TextBuffer as IProjectionBuffer; + + // if (projection != null) + // { + // int position = _textView.Caret.Position.BufferPosition.Position; + // var buffers = projection.SourceBuffers.Where(s => s.ContentType.IsOfType("css") || s.ContentType.IsOfType("javascript")); + + // foreach (ITextBuffer buffer in buffers) + // { + // IProjectionSnapshot snapshot = buffer.CurrentSnapshot as IProjectionSnapshot; + // bool containsPosition = snapshot.GetSourceSpans().Any(s => s.Contains(position)); + + // if (containsPosition) + // { + // return false; + // } + // } + // } + + // return true; + //} + + private bool SetCaret(Span zenSpan, bool isReverse) + { + string text = TextView.TextBuffer.CurrentSnapshot.GetText(); + Span quote = FindTabSpan(zenSpan, isReverse, text, _quotes); + Span bracket = FindTabSpan(zenSpan, isReverse, text, _bracket); + + if (!isReverse && bracket.Start > 0 && (bracket.Start < quote.Start || quote.Start == 0)) + { + quote = bracket; + } + else if (isReverse && bracket.Start > 0 && (bracket.Start > quote.Start || quote.Start == 0)) + { + quote = bracket; + } + + if (zenSpan.Contains(quote.Start)) + { + MoveTab(quote); + return true; + } + else if (!isReverse) + { + MoveTab(new Span(zenSpan.End, 0)); + return true; + } + + return false; + } + + private void MoveTab(Span quote) + { + TextView.Caret.MoveTo(new SnapshotPoint(TextView.TextBuffer.CurrentSnapshot, quote.Start)); + SnapshotSpan span = new SnapshotSpan(TextView.TextBuffer.CurrentSnapshot, quote); + TextView.Selection.Select(span, false); + } + + private static Span FindTabSpan(Span zenSpan, bool isReverse, string text, Regex regex) + { + MatchCollection matches = regex.Matches(text); + + if (!isReverse) + { + foreach (Match match in matches) + { + Group group = match.Groups[2]; + + if (group.Index >= zenSpan.Start) + { + return new Span(group.Index, group.Length); + } + } + } + else + { + for (int i = matches.Count - 1; i >= 0; i--) + { + Group group = matches[i].Groups[2]; + + if (group.Index < zenSpan.End) + { + return new Span(group.Index, group.Length); + } + } + } + + return new Span(); + } + + private ITextSelection UpdateTextBuffer(Span zenSpan, string result) + { + TextView.TextBuffer.Replace(zenSpan, result); + + SnapshotPoint point = new SnapshotPoint(TextView.TextBuffer.CurrentSnapshot, zenSpan.Start); + SnapshotSpan snapshot = new SnapshotSpan(point, result.Length); + TextView.Selection.Select(snapshot, false); + + EditorExtensionsPackage.ExecuteCommand("Edit.FormatSelection"); + + return TextView.Selection; + } + + private Span GetText() + { + int position = TextView.Caret.Position.BufferPosition.Position; + + if (position >= 0) + { + var line = TextView.TextBuffer.CurrentSnapshot.GetLineFromPosition(position); + string text = line.GetText().TrimEnd(); + + if (string.IsNullOrWhiteSpace(text) || text.Length < position - line.Start || text.Length + line.Start > position) + return new Span(); + + string result = text.Substring(0, position - line.Start).TrimStart(); + + if (result.Length > 0 && !text.Contains("<") && !char.IsWhiteSpace(result.Last())) + { + return new Span(line.Start.Position + text.IndexOf(result), result.Length); + } + } + + return new Span(); + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JavaScript/JavaScriptCreationListener.cs b/EditorExtensions/Commands/JavaScript/JavaScriptCreationListener.cs new file mode 100644 index 000000000..d3f532bf5 --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JavaScriptCreationListener.cs @@ -0,0 +1,42 @@ +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType("JavaScript")] + [TextViewRole(PredefinedTextViewRoles.Document)] + class JavaScriptSortPropertiesViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import(typeof(ITextStructureNavigatorSelectorService))] + internal ITextStructureNavigatorSelectorService Navigator { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new MinifySelection(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new JavaScriptFindReferences(textViewAdapter, textView, Navigator)); + textView.Properties.GetOrCreateSingletonProperty(() => new CssExtractToFile(textViewAdapter, textView)); + + ITextDocument document; + textView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document); + + if (document != null) + { + JsHintProjectRunner runner = new JsHintProjectRunner(document); + textView.Closed += (s, e) => runner.Dispose(); + + textView.TextBuffer.Properties.GetOrCreateSingletonProperty(() => runner); + } + } + } +} diff --git a/EditorExtensions/Commands/JavaScript/JavaScriptFindReferencesCommandTarget.cs b/EditorExtensions/Commands/JavaScript/JavaScriptFindReferencesCommandTarget.cs new file mode 100644 index 000000000..80fcac941 --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JavaScriptFindReferencesCommandTarget.cs @@ -0,0 +1,65 @@ +using EnvDTE80; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class JavaScriptFindReferences : CommandTargetBase + { + private DTE2 _dte; + private ITextStructureNavigator _navigator; + + public JavaScriptFindReferences(IVsTextView adapter, IWpfTextView textView, ITextStructureNavigatorSelectorService navigator) + : base(adapter, textView, typeof(VSConstants.VSStd97CmdID).GUID, (uint)VSConstants.VSStd97CmdID.FindReferences) + { + _navigator = navigator.GetTextStructureNavigator(textView.TextBuffer); + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + int position = TextView.Caret.Position.BufferPosition.Position; + SnapshotPoint? point = TextView.Caret.Position.Point.GetPoint(TextView.TextBuffer, PositionAffinity.Predecessor); + + if (point.HasValue) + { + TextExtent wordExtent = _navigator.GetExtentOfWord(point.Value - 1); + string wordText = TextView.TextSnapshot.GetText(wordExtent.Span); + + Find2 find = (Find2)EditorExtensionsPackage.DTE.Find; + string types = find.FilesOfType; + bool matchCase = find.MatchCase; + bool matchWord = find.MatchWholeWord; + + find.WaitForFindToComplete = false; + find.Action = EnvDTE.vsFindAction.vsFindActionFindAll; + find.Backwards = false; + find.MatchInHiddenText = true; + find.MatchWholeWord = true; + find.MatchCase = true; + find.PatternSyntax = EnvDTE.vsFindPatternSyntax.vsFindPatternSyntaxLiteral; + find.ResultsLocation = EnvDTE.vsFindResultsLocation.vsFindResults1; + find.SearchSubfolders = true; + find.FilesOfType = "*.js"; + find.Target = EnvDTE.vsFindTarget.vsFindTargetSolution; + find.FindWhat = wordText; + find.Execute(); + + find.FilesOfType = types; + find.MatchCase = matchCase; + find.MatchWholeWord = matchWord; + } + + return true; + } + + protected override bool IsEnabled() + { + return true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JavaScript/JavaScriptSaveListener.cs b/EditorExtensions/Commands/JavaScript/JavaScriptSaveListener.cs new file mode 100644 index 000000000..934104ddb --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JavaScriptSaveListener.cs @@ -0,0 +1,128 @@ +using Microsoft.Ajax.Utilities; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System; +using System.ComponentModel.Composition; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewCreationListener))] + [ContentType("JavaScript")] + [TextViewRole(PredefinedTextViewRoles.Document)] + public class JavaScriptSaveListener : IWpfTextViewCreationListener + { + private ITextDocument _document; + + public void TextViewCreated(IWpfTextView textView) + { + textView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out _document); + + if (_document != null) + { + _document.FileActionOccurred += document_FileActionOccurred; + } + } + + void document_FileActionOccurred(object sender, TextDocumentFileActionEventArgs e) + { + if (!WESettings.GetBoolean(WESettings.Keys.EnableJsMinification)) + return; + + ITextDocument document = (ITextDocument)sender; + + if (document.TextBuffer != null && e.FileActionType == FileActionTypes.ContentSavedToDisk && e.FilePath.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) + { + string minFile = e.FilePath.Insert(e.FilePath.Length - 2, "min."); + string bundleFile = e.FilePath + ".bundle"; + + if (!File.Exists(bundleFile) && File.Exists(minFile) && EditorExtensionsPackage.DTE.Solution.FindProjectItem(minFile) != null) + { + Task.Run(() => + { + Minify(e.FilePath, minFile, false); + }); + } + } + } + + public static void Minify(string sourceFile, string minFile, bool isBundle) + { + if (sourceFile.EndsWith(".min.js")) + return; + + try + { + CodeSettings settings = new CodeSettings() + { + EvalTreatment = EvalTreatment.MakeImmediateSafe, + TermSemicolons = true, + PreserveImportantComments = WESettings.GetBoolean(WESettings.Keys.KeepImportantComments) + }; + + if (WESettings.GetBoolean(WESettings.Keys.GenerateJavaScriptSourceMaps)) + { + MinifyFileWithSourceMap(sourceFile, minFile, settings, isBundle); + } + else + { + MinifyFile(sourceFile, minFile, settings, isBundle); + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + + private static void MinifyFileWithSourceMap(string file, string minFile, CodeSettings settings, bool isBundle) + { + string mapPath = minFile + ".map"; + ProjectHelpers.CheckOutFileFromSourceControl(mapPath); + + using (TextWriter writer = new StreamWriter(mapPath, false, new UTF8Encoding(false))) + using (V3SourceMap sourceMap = new V3SourceMap(writer)) + { + settings.SymbolsMap = sourceMap; + + sourceMap.StartPackage(Path.GetFileName(minFile), Path.GetFileName(mapPath)); + + // This fails when debugger is attached. Bug raised with Ron Logan + MinifyFile(file, minFile, settings, isBundle); + + sourceMap.EndPackage(); + + if (!isBundle) + { + MarginBase.AddFileToProject(file, mapPath); + } + } + } + + private static void MinifyFile(string file, string minFile, CodeSettings settings, bool isBundle) + { + Minifier minifier = new Minifier(); + + if (!isBundle) + { + minifier.FileName = Path.GetFileName(file); + } + + string content = minifier.MinifyJavaScript(File.ReadAllText(file), settings); + + if (WESettings.GetBoolean(WESettings.Keys.GenerateJavaScriptSourceMaps)) + { + content += Environment.NewLine + "//@ sourceMappingURL=" + Path.GetFileName(minFile) + ".map"; + } + + ProjectHelpers.CheckOutFileFromSourceControl(minFile); + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + } + } +} diff --git a/EditorExtensions/Commands/JavaScript/JsHintCompiler.cs b/EditorExtensions/Commands/JavaScript/JsHintCompiler.cs new file mode 100644 index 000000000..dbc488730 --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JsHintCompiler.cs @@ -0,0 +1,84 @@ +using MadsKristensen.EditorExtensions; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Threading; + +///

+/// Summary description for Lint +/// +[ComVisible(true)] +public class JsHintCompiler : ScriptRunnerBase +{ + private string _settings; + private JsHintOptions _options; + + public JsHintCompiler(Dispatcher dispatcher) + : base(dispatcher) + { } + + protected override string CreateHtml(string source, string state) + { + if (_options == null) + { + _options = new JsHintOptions(); + _options.LoadSettingsFromStorage(); + JsHintOptions.Changed += delegate { _options.LoadSettingsFromStorage(); GenerateSettings(); }; + + GenerateSettings(); + } + + source = source + .Replace("\\", "\\\\") + .Replace("\n", "\\n") + .Replace("\r", "\\r") + .Replace("'", "\\'"); + + string script = ReadResourceFile("MadsKristensen.EditorExtensions.Resources.Scripts.jshint.js") + + "JSHINT('" + source + "', {" + _settings + "});" + + "window.external.Execute(JSON.stringify(JSHINT.errors), '" + state.Replace("\\", "\\\\") + "')"; + + return ""; + } + + private void GenerateSettings() + { + Type type = _options.GetType(); + PropertyInfo[] properties = type.GetProperties(); + List list = new List(); + + foreach (PropertyInfo item in properties) + { + if (!item.Name.StartsWith("JsHint_")) + continue; + + object value = item.GetValue(_options, null); + int intValue; + bool boolValue; + + if (int.TryParse(value.ToString(), out intValue) && intValue > -1) + { + list.Add(item.Name.Replace("JsHint_", string.Empty) + ":" + intValue); + } + else if (bool.TryParse(value.ToString(), out boolValue) && boolValue == true) + { + list.Add(item.Name.Replace("JsHint_", string.Empty) + ":true"); + } + } + + _settings = string.Join(", ", list); + } +} + +public class Result +{ + public string id { get; set; } + public string raw { get; set; } + public string evidence { get; set; } + public int line { get; set; } + public int character { get; set; } + public string a { get; set; } + public string b { get; set; } + public string reason { get; set; } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JavaScript/JsHintProjectRunner.cs b/EditorExtensions/Commands/JavaScript/JsHintProjectRunner.cs new file mode 100644 index 000000000..c542b685f --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JsHintProjectRunner.cs @@ -0,0 +1,64 @@ +using Microsoft.VisualStudio.Text; +using System; +using System.IO; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal class JsHintProjectRunner : IDisposable + { + private ITextDocument _document; + private JsHintRunner _runner; + private bool _isDisposed; + + public JsHintProjectRunner(ITextDocument document) + { + _document = document; + _document.FileActionOccurred += DocumentSavedHandler; + _runner = new JsHintRunner(_document.FilePath); + + if (WESettings.GetBoolean(WESettings.Keys.EnableJsHint)) + { + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => _runner.RunCompiler()), DispatcherPriority.ApplicationIdle, null); + } + } + + private void DocumentSavedHandler(object sender, TextDocumentFileActionEventArgs e) + { + if (!WESettings.GetBoolean(WESettings.Keys.EnableJsHint)) + return; + + ITextDocument document = (ITextDocument)sender; + + if (document.TextBuffer != null && !_isDisposed && e.FileActionType == FileActionTypes.ContentSavedToDisk) + { + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => _runner.RunCompiler()), DispatcherPriority.ApplicationIdle, null); + } + } + + public static void RunOnAllFilesInProject() + { + string dir = ProjectHelpers.GetRootFolder(); + + if (dir != null && Directory.Exists(dir)) + { + foreach (string file in Directory.GetFiles(dir, "*.js", SearchOption.AllDirectories)) + { + JsHintRunner runner = new JsHintRunner(file); + runner.RunCompiler(); + } + } + } + + public void Dispose() + { + if (!_isDisposed) + { + //_document.Dispose(); + _runner.Dispose(); + } + + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JavaScript/JsHintRunner.cs b/EditorExtensions/Commands/JavaScript/JsHintRunner.cs new file mode 100644 index 000000000..bc1e2b9ab --- /dev/null +++ b/EditorExtensions/Commands/JavaScript/JsHintRunner.cs @@ -0,0 +1,246 @@ +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web.Script.Serialization; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal class JsHintRunner : IDisposable + { + private ErrorListProvider _provider; + private static Dictionary _providers = new Dictionary(); + private string _fileName; + private bool _isDisposed; + + static JsHintRunner() + { + EditorExtensionsPackage.DTE.Events.SolutionEvents.AfterClosing += SolutionEvents_AfterClosing; + } + + static void SolutionEvents_AfterClosing() + { + Reset(); + EditorExtensionsPackage.DTE.Events.SolutionEvents.AfterClosing -= SolutionEvents_AfterClosing; + } + + public JsHintRunner(string fileName) + { + _fileName = fileName; + + if (_providers.ContainsKey(fileName)) + { + _provider = _providers[fileName]; + } + else + { + _provider = new ErrorListProvider(EditorExtensionsPackage.Instance); + _providers.Add(fileName, _provider); + } + } + + public void RunCompiler() + { + if (!_isDisposed && !ShouldIgnore(_fileName)) + { + EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Running JSHint..."; + JsHintCompiler lint = new JsHintCompiler(Dispatcher.CurrentDispatcher); + + System.Threading.Tasks.Task.Run(() => + { + using (StreamReader reader = new StreamReader(_fileName)) + { + string content = reader.ReadToEnd(); + + lint.Completed += LintCompletedHandler; + lint.Compile(content, _fileName); + } + }); + } + } + + public static void Reset() + { + foreach (string key in _providers.Keys) + { + _providers[key].Tasks.Clear(); + _providers[key].Dispose(); + } + + _providers.Clear(); + } + + public static bool ShouldIgnore(string file) + { + if (!Path.GetExtension(file).Equals(".js", StringComparison.OrdinalIgnoreCase) || + file.EndsWith(".min.js") || + file.EndsWith(".debug.js") || + file.EndsWith(".intellisense.js") || + !File.Exists(file) || + EditorExtensionsPackage.DTE.Solution.FindProjectItem(file) == null) + { + return true; + } + + string name = Path.GetFileName(file); + + foreach (string regex in _ignoreList) + { + if (Regex.IsMatch(name, regex, RegexOptions.IgnoreCase)) + { + return true; + } + } + + return false; + } + + private static List _ignoreList = new List() + { + @"jquery-([0-9\.]+)\.js", + @"jquery-ui-([0-9\.]+)\.js", + @"knockout-([0-9\.]+)\.js", + @"modernizr-([0-9\.]+)\.js", + @"backbone\.js", + @"angular\.js", + @"amplify\.js", + @"dojo\.js", + @"ember\.js", + @"handlebars-([0-9a-z\.]+)\.js", + @"mustache\.js", + @"underscore\.js", + @"yepnope\.js", + @"ext-core\.js", + @"highlight\.js", + @"history\.js", + @"require\.js", + @"sammy\.js", + @"json2\.js", + @"_references\.js", + @"MicrosoftAjax([a-z]+)\.js", + @"scriptaculous\.js ", + @"prototype\.js ", + @"qunit-([0-9a-z\.]+)\.js", + @"swfobject\.js", + @"bootstrap\.js", + @"webfont\.js", + @"zepto\.js", + }; + + private void LintCompletedHandler(object sender, CompilerEventArgs e) + { + using (JsHintCompiler lint = (JsHintCompiler)sender) + { + if (!_isDisposed) + { + System.Threading.Tasks.Task.Run(() => + { + ReadResult(e); + }); + } + + lint.Completed -= LintCompletedHandler; + } + + EditorExtensionsPackage.DTE.StatusBar.Clear(); + } + + private void ReadResult(CompilerEventArgs e) + { + try + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + Result[] results = serializer.Deserialize(e.Result); + + _provider.SuspendRefresh(); + _provider.Tasks.Clear(); + + foreach (Result error in results.Where(r => r != null)) + { + ErrorTask task = CreateTask(e.State, error); + _provider.Tasks.Add(task); + } + + _provider.ResumeRefresh(); + } + catch + { + Logger.Log("Error reading JSHint result"); + } + } + + private ErrorTask CreateTask(string data, Result error) + { + ErrorTask task = new ErrorTask() + { + Line = error.line, + Column = error.character, + ErrorCategory = GetOutputLocation(), + Category = TaskCategory.Html, + Document = data, + Priority = TaskPriority.Low, + Text = GetErrorMessage(error), + }; + + task.AddHierarchyItem(); + + task.Navigate += task_Navigate; + return task; + } + + private static TaskErrorCategory GetOutputLocation() + { + var location = (WESettings.Keys.FullErrorLocation)WESettings.GetInt(WESettings.Keys.JsHintErrorLocation); + + if (location == WESettings.Keys.FullErrorLocation.Errors) + return TaskErrorCategory.Error; + + if (location == WESettings.Keys.FullErrorLocation.Warnings) + return TaskErrorCategory.Warning; + + return TaskErrorCategory.Message; + } + + private string GetErrorMessage(Result error) + { + string raw = error.raw; + if (raw == "Missing radix parameter.") + raw = "When using the parseInt function, remember to specify the radix parameter. Example: parseInt('3', 10)"; + + return "JSHint (r10): " + raw.Replace("{a}", error.a).Replace("{b}", error.b); + } + + private void task_Navigate(object sender, EventArgs e) + { + Task task = sender as Task; + + _provider.Navigate(task, new Guid(EnvDTE.Constants.vsViewKindPrimary)); + + if (task.Column > 0) + { + var doc = (TextDocument)EditorExtensionsPackage.DTE.ActiveDocument.Object("textdocument"); + doc.Selection.MoveToLineAndOffset(task.Line, task.Column, false); + } + } + + public void Dispose() + { + if (!_isDisposed) + { + if (_providers.ContainsKey(_fileName)) + { + _providers.Remove(_fileName); + } + + _provider.Tasks.Clear(); + _provider.Dispose(); + } + + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JavaScriptSmartIndentCommandTarget.cs b/EditorExtensions/Commands/JavaScriptSmartIndentCommandTarget.cs new file mode 100644 index 000000000..ce51120cc --- /dev/null +++ b/EditorExtensions/Commands/JavaScriptSmartIndentCommandTarget.cs @@ -0,0 +1,113 @@ +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.ComponentModel.Composition; +using System.Windows.Forms; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType("JavaScript")] + [TextViewRole(PredefinedTextViewRoles.Document)] + class JavaScriptSmartIndentTextViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import] + internal ICompletionBroker CompletionBroker { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + textView.Properties.GetOrCreateSingletonProperty(() => new JavaScriptSmartIndent(textViewAdapter, textView, CompletionBroker)); + } + } + + class JavaScriptSmartIndent : IOleCommandTarget + { + private ITextView _textView; + private IOleCommandTarget _nextCommandTarget; + private ICompletionBroker _broker; + + public JavaScriptSmartIndent(IVsTextView adapter, ITextView textView, ICompletionBroker broker) + { + _textView = textView; + _broker = broker; + adapter.AddCommandFilter(this, out _nextCommandTarget); + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + if (nCmdID == 3 && !_broker.IsCompletionActive(_textView)) + { + if (Indent()) + { + return VSConstants.S_OK; + } + } + + } + + return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + + private bool Indent() + { + int position = _textView.Caret.Position.BufferPosition.Position; + + + if (position == 0 || position == _textView.TextBuffer.CurrentSnapshot.Length || _textView.Selection.SelectedSpans[0].Length > 0) + return false; + + char before = _textView.TextBuffer.CurrentSnapshot.GetText(position - 1, 1)[0]; + char after = _textView.TextBuffer.CurrentSnapshot.GetText(position, 1)[0]; + + if (before == '{' && after == '}') + { + EditorExtensionsPackage.DTE.UndoContext.Open("Smart indent"); + + _textView.TextBuffer.Insert(position, Environment.NewLine + '\t'); + SnapshotPoint point = new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, position); + _textView.Selection.Select(new SnapshotSpan(point, 4), true); + + EditorExtensionsPackage.ExecuteCommand("Edit.FormatSelection"); + + _textView.Selection.Clear(); + SendKeys.Send("{ENTER}"); + + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + return false; + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + for (int i = 0; i < cCmds; i++) + { + switch (prgCmds[i].cmdID) + { + case 3: + prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + return VSConstants.S_OK; + } + } + } + + return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/JsDocRegistry.cs b/EditorExtensions/Commands/JsDocRegistry.cs new file mode 100644 index 000000000..4792bff06 --- /dev/null +++ b/EditorExtensions/Commands/JsDocRegistry.cs @@ -0,0 +1,86 @@ +using Microsoft.Win32; +using System; +using System.IO; +using System.Reflection; + +namespace MadsKristensen.EditorExtensions +{ + public static class JsDocComments + { + private static string _fileName = "JsDocComments.js"; + + public static void Register() + { + try + { + string userPath = GetUserFilePath(); + + if (!File.Exists(userPath)) + { + string assembly = Assembly.GetExecutingAssembly().Location; + string folder = Path.GetDirectoryName(assembly).ToLowerInvariant(); + string file = Path.Combine(folder, "resources\\scripts\\JsDocComments.js"); + + if (!File.Exists(file)) + return; + + File.Copy(file, userPath); + UpdateRegistry(userPath); + } + } + catch + { + Logger.Log("Error registering JSDoc comments with Visual Studio"); + } + } + + private static string GetUserFilePath() + { + string user = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + string folder = Path.Combine(user, "Web Essentials"); + + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + + return Path.Combine(folder, _fileName); + } + + private static void UpdateRegistry(string file) + { + using (RegistryKey key = EditorExtensionsPackage.Instance.UserRegistryRoot.OpenSubKey("JavaScriptLanguageService", true)) + { + if (key != null) + { + string value = (string)key.GetValue("ReferenceGroups"); + if (value.Contains(file)) + return; + + string newValue = value; + int index = value.IndexOf(_fileName); + + if (index > -1) + { + int start = value.LastIndexOf('|', index); + int length = index - start + _fileName.Length; + string oldPath = value.Substring(start, length); + newValue = value.Replace(oldPath, "|" + file); + } + else + { + int startWeb = value.IndexOf("Implicit (Web)"); + int semicolon = value.IndexOf(';', startWeb); + + if (semicolon > -1) + { + newValue = value.Insert(semicolon, "|" + file); + } + } + + key.SetValue("ReferenceGroups", newValue); + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/LESS/LessCreationListener.cs b/EditorExtensions/Commands/LESS/LessCreationListener.cs new file mode 100644 index 000000000..91ee8dbae --- /dev/null +++ b/EditorExtensions/Commands/LESS/LessCreationListener.cs @@ -0,0 +1,27 @@ +using Microsoft.Less.Core; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType(LessContentTypeDefinition.LessContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + class LessViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new LessExtractVariableCommandTarget(textViewAdapter, textView)); + textView.Properties.GetOrCreateSingletonProperty(() => new LessExtractMixinCommandTarget(textViewAdapter, textView)); + } + } +} diff --git a/EditorExtensions/Commands/LESS/LessExtractMixinCommandTarget.cs b/EditorExtensions/Commands/LESS/LessExtractMixinCommandTarget.cs new file mode 100644 index 000000000..6a789d619 --- /dev/null +++ b/EditorExtensions/Commands/LESS/LessExtractMixinCommandTarget.cs @@ -0,0 +1,61 @@ +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class LessExtractMixinCommandTarget : CommandTargetBase + { + private DTE2 _dte; + + public LessExtractMixinCommandTarget(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidExtractCmdSet, PkgCmdIDList.ExtractMixin) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (TextView == null) + return false; + + CssEditorDocument document = CssEditorDocument.FromTextBuffer(TextView.TextBuffer); + + int position = TextView.Caret.Position.BufferPosition.Position; + ParseItem item = document.Tree.StyleSheet.ItemBeforePosition(position); + + ParseItem rule = LessExtractVariableCommandTarget.FindParent(item); + int mixinStart = rule.Start; + string name = Microsoft.VisualBasic.Interaction.InputBox("Name of the Mixin", "Web Essentials"); + + if (!string.IsNullOrEmpty(name)) + { + EditorExtensionsPackage.DTE.UndoContext.Open("Extract to mixin"); + + var selection = TextView.Selection.SelectedSpans[0]; + string text = selection.GetText(); + TextView.TextBuffer.Replace(selection.Span, "." + name + "();"); + TextView.TextBuffer.Insert(rule.Start, "." + name + "() {" + Environment.NewLine + text + Environment.NewLine + "}" + Environment.NewLine + Environment.NewLine); + + TextView.Selection.Select(new SnapshotSpan(TextView.TextBuffer.CurrentSnapshot, mixinStart, 1), false); + EditorExtensionsPackage.ExecuteCommand("Edit.FormatSelection"); + TextView.Selection.Clear(); + + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + return false; + } + + protected override bool IsEnabled() + { + return TextView.Selection.SelectedSpans[0].Length > 0; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/LESS/LessExtractVariableCommandTarget.cs b/EditorExtensions/Commands/LESS/LessExtractVariableCommandTarget.cs new file mode 100644 index 000000000..6a7ee5c38 --- /dev/null +++ b/EditorExtensions/Commands/LESS/LessExtractVariableCommandTarget.cs @@ -0,0 +1,73 @@ +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.Less.Core; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; + +namespace MadsKristensen.EditorExtensions +{ + internal class LessExtractVariableCommandTarget : CommandTargetBase + { + private DTE2 _dte; + + public LessExtractVariableCommandTarget(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidExtractCmdSet, PkgCmdIDList.ExtractVariable) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (TextView == null) + return false; + + CssEditorDocument document = CssEditorDocument.FromTextBuffer(TextView.TextBuffer); + + int position = TextView.Caret.Position.BufferPosition.Position; + ParseItem item = document.Tree.StyleSheet.ItemBeforePosition(position); + + ParseItem rule = FindParent(item); + string text = item.Text; + string name = Microsoft.VisualBasic.Interaction.InputBox("Name of the variable", "Web Essentials"); + + if (!string.IsNullOrEmpty(name)) + { + EditorExtensionsPackage.DTE.UndoContext.Open("Extract to variable"); + + Span span = TextView.Selection.SelectedSpans[0].Span; + TextView.TextBuffer.Replace(span, "@" + name); + TextView.TextBuffer.Insert(rule.Start, "@" + name + ": " + text + ";" + Environment.NewLine + Environment.NewLine); + + EditorExtensionsPackage.DTE.UndoContext.Close(); + + return true; + } + + return false; + } + + public static ParseItem FindParent(ParseItem item) + { + ParseItem parent = item.Parent; + + while (true) + { + if (parent.Parent == null || parent.Parent is LessStyleSheet || parent.Parent is AtDirective) + break; + + parent = parent.Parent; + } + + return parent; + } + + protected override bool IsEnabled() + { + var span = TextView.Selection.SelectedSpans[0]; + return span.Length > 0 && !span.GetText().Contains("\r"); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/MoveRuleCommandTarget.cs b/EditorExtensions/Commands/MoveRuleCommandTarget.cs new file mode 100644 index 000000000..981d41a40 --- /dev/null +++ b/EditorExtensions/Commands/MoveRuleCommandTarget.cs @@ -0,0 +1,382 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Xml; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType(Microsoft.Web.Editor.CssContentTypeDefinition.CssContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + class MoveRuleTextViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + textView.Properties.GetOrCreateSingletonProperty(() => new MoveRuleTarget(textViewAdapter, textView)); + } + } + + class MoveRuleTarget : IOleCommandTarget + { + private ITextView _textView; + private IOleCommandTarget _nextCommandTarget; + private CssTree _tree; + + public MoveRuleTarget(IVsTextView adapter, ITextView textView) + { + this._textView = textView; + adapter.AddCommandFilter(this, out _nextCommandTarget); + } + + public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + switch (nCmdID) + { + case 2400: + if (Move(Direction.Down)) + return VSConstants.S_OK; + break; + + case 2401: + if (Move(Direction.Up)) + return VSConstants.S_OK; + break; + } + } + + return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + + private enum Direction + { + Up, + Down + } + + private bool Move(Direction direction) + { + if (!EnsureInitialized()) + return false; + + int position = _textView.Caret.Position.BufferPosition.Position; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(position); + + Declaration dec = item.FindType(); + if (dec != null) + { + return HandleDeclaration(direction, dec); + } + + Selector selector = item.FindType(); + if (selector != null) + { + return HandleSelector(direction, selector); + } + + return false; + } + + private bool HandleDeclaration(Direction direction, Declaration declaration) + { + RuleBlock rule = declaration.FindType(); + if (rule == null || rule.Text.IndexOfAny(new[] { '\r', '\n' }) == -1 || (direction == Direction.Up && rule.Declarations.First() == declaration) || (direction == Direction.Down && rule.Declarations.Last() == declaration)) + return false; + + Declaration sibling = null; + string text = null; + + if (direction == Direction.Up) + { + sibling = rule.Declarations.ElementAt(rule.Declarations.IndexOf(declaration) - 1); + text = declaration.Text + sibling.Text; + } + else + { + sibling = rule.Declarations.ElementAt(rule.Declarations.IndexOf(declaration) + 1); + text = sibling.Text + declaration.Text; + } + + EditorExtensionsPackage.DTE.UndoContext.Open("Move CSS declaration"); + + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + int start = Math.Min(declaration.Start, sibling.Start); + int end = Math.Max(declaration.AfterEnd, sibling.AfterEnd); + edit.Replace(start, end - start, text); + edit.Apply(); + + if (direction == Direction.Up) + _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, sibling.Start + 1)); + + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatSelection"); + EditorExtensionsPackage.DTE.UndoContext.Close(); + } + + return true; + } + + private bool HandleSelector(Direction direction, Selector selector) + { + //new WriteBrowserXml().Parse(); + RuleSet rule = selector.FindType(); + if (rule == null) + return false; + + if (direction == Direction.Up) + { + rule = rule.PreviousSibling as RuleSet; + if (rule == null) + return false; + } + + EditorExtensionsPackage.DTE.UndoContext.Open("Move CSS rule"); + + using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) + { + int position = SwapItemWithNextSibling(rule, edit); + if (position > -1) + { + if (direction == Direction.Down) + _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, position + 1)); + else + _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, rule.Start + 1)); + + // TODO: Format both rules + EditorExtensionsPackage.DTE.ExecuteCommand("Edit.FormatSelection"); + } + + EditorExtensionsPackage.DTE.UndoContext.Close(); + } + + return true; + } + + private int SwapItemWithNextSibling(ParseItem item, ITextEdit edit) + { + RuleSet next = item.NextSibling as RuleSet; + if (next == null) + return -1; + + ITextSnapshot snapshot = _textView.TextBuffer.CurrentSnapshot; + string whitespace = snapshot.GetText(item.AfterEnd, next.Start - item.AfterEnd); + string text = next.Text + whitespace + item.Text; + + edit.Replace(item.Start, next.AfterEnd - item.Start, text); + edit.Apply(); + + return item.Start + next.Length + whitespace.Length; + } + + public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) + { + if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID) + { + for (int i = 0; i < cCmds; i++) + { + switch (prgCmds[i].cmdID) + { + case 2401: // Up + case 2400: // Down + prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); + return VSConstants.S_OK; + } + } + } + + return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + + public bool EnsureInitialized() + { + if (_tree == null && Microsoft.Web.Editor.WebEditor.Host != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_textView.TextBuffer); + _tree = document.Tree; + } + catch (ArgumentNullException) + { + } + } + + return _tree != null; + } + } + + public class WriteBrowserXml + { + private const string _fileName = @"C:\Users\madsk\Documents\visual studio 2012\Projects\RealWorldValidator\RealWorldValidator\App_Data\browsers.xml"; + + public void Parse() + { + ICssSchemaInstance root = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + IEnumerable schemas = GetAllSchemas(root); + using (XmlWriter writer = XmlWriter.Create(_fileName)) + { + writer.WriteStartElement("css"); + + // @-Directives + List directives = new List(root.AtDirectives); + directives.AddRange(schemas.SelectMany(s => s.AtDirectives)); + directives = RemoveDuplicates(directives); + + writer.WriteStartElement("atDirectives"); + WriteSection(writer, directives); + //WriteSection(writer, root.AtDirectives); + //foreach (var schema in schemas) + // WriteSection(writer, schema.AtDirectives); + writer.WriteEndElement(); + + // Pseudos + List pseudos = new List(root.PseudoClassesAndElements); + pseudos.AddRange(schemas.SelectMany(s => s.PseudoClassesAndElements)); + pseudos = RemoveDuplicates(pseudos); + + writer.WriteStartElement("pseudoClasses"); + WriteSection(writer, pseudos.Where(p => p.DisplayText[1] != ':')); + writer.WriteEndElement(); + + writer.WriteStartElement("pseudoElements"); + WriteSection(writer, pseudos.Where(p => p.DisplayText[1] == ':')); + writer.WriteEndElement(); + + // Properties + List properties = new List(root.Properties); + properties.AddRange(schemas.SelectMany(s => s.Properties)); + properties = RemoveDuplicates(properties); + + writer.WriteStartElement("properties"); + WriteProperties(writer, properties, root); + //WriteProperties(writer, root.Properties, root); + //foreach (var schema in schemas) + // WriteProperties(writer, schema.Properties, schema); + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + } + + private List RemoveDuplicates(List list) + { + for (int i = list.Count() - 1; i > -1; i--) + { + if (list.Count(p => p.DisplayText == list.ElementAt(i).DisplayText) > 1) + list.RemoveAt(i); + } + + return list; + } + + string[] vs = new[] { "@-we-palette", "@unspecified", "@global", "@specific" }; + + private IEnumerable GetAllSchemas(ICssSchemaInstance rootSchema) + { + foreach (ICssCompletionListEntry directive in rootSchema.AtDirectives) + { + if (vs.Contains(directive.DisplayText)) + continue; + + ICssSchemaInstance schema = rootSchema.GetAtDirectiveSchemaInstance(directive.DisplayText); + if (schema != null && schema.Properties.Count() != rootSchema.Properties.Count()) + yield return schema; + } + } + + private void WriteSection(XmlWriter writer, IEnumerable entries) + { + foreach (ICssCompletionListEntry entry in entries.OrderBy(e => e.DisplayText)) + { + writer.WriteStartElement("entry"); + writer.WriteAttributeString("name", entry.DisplayText); + writer.WriteAttributeString("version", entry.GetAttribute("version")); + WriteBrowserSupport(writer, entry); + + if (!string.IsNullOrEmpty(entry.GetAttribute("standard-reference"))) + writer.WriteAttributeString("ref", entry.GetAttribute("standard-reference")); + + if (!string.IsNullOrEmpty(entry.GetAttribute("syntax"))) + writer.WriteAttributeString("syntax", entry.GetAttribute("syntax")); + + if (!string.IsNullOrEmpty(entry.GetAttribute("description"))) + writer.WriteElementString("desc", entry.GetAttribute("description")); + + writer.WriteEndElement(); + } + } + + private void WriteProperties(XmlWriter writer, IEnumerable entries, ICssSchemaInstance schema) + { + foreach (ICssCompletionListEntry entry in entries.OrderBy(e => e.DisplayText)) + { + writer.WriteStartElement("entry"); + writer.WriteAttributeString("name", entry.DisplayText); + writer.WriteAttributeString("restriction", entry.GetAttribute("restriction")); + writer.WriteAttributeString("version", entry.GetAttribute("version")); + WriteBrowserSupport(writer, entry); + + if (!string.IsNullOrEmpty(entry.GetAttribute("standard-reference"))) + writer.WriteAttributeString("ref", entry.GetAttribute("standard-reference")); + + if (!string.IsNullOrEmpty(entry.GetAttribute("syntax"))) + writer.WriteAttributeString("syntax", entry.GetAttribute("syntax")); + + if (!string.IsNullOrEmpty(entry.GetAttribute("description"))) + writer.WriteElementString("desc", entry.GetAttribute("description")); + + var values = schema.GetPropertyValues(entry.DisplayText); + if (values.Count() > 2) + { + writer.WriteStartElement("values"); + foreach (ICssCompletionListEntry value in values.OrderBy(v => v.DisplayText)) + { + if (value.DisplayText == "initial" || value.DisplayText == "inherit") + continue; + + writer.WriteStartElement("value"); + writer.WriteAttributeString("name", value.DisplayText); + writer.WriteAttributeString("version", value.GetAttribute("version") != string.Empty ? value.GetAttribute("version") : entry.GetAttribute("version")); + WriteBrowserSupport(writer, value); + + if (!string.IsNullOrEmpty(value.GetAttribute("description"))) + writer.WriteElementString("desc", value.GetAttribute("description")); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + } + + private static void WriteBrowserSupport(XmlWriter writer, ICssCompletionListEntry entry) + { + string attr = entry.GetAttribute("browsers"); + + if (string.IsNullOrEmpty(attr)) + attr = "all"; + + writer.WriteAttributeString("browsers", attr); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/PasteJsonAsTypeScript.cs b/EditorExtensions/Commands/PasteJsonAsTypeScript.cs new file mode 100644 index 000000000..a96cf0e84 --- /dev/null +++ b/EditorExtensions/Commands/PasteJsonAsTypeScript.cs @@ -0,0 +1,136 @@ +using Microsoft.VisualStudio.Web.PasteJson; +using System; +using System.ComponentModel.Composition; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IPasteJsonCodeGenerator))] + [ExportMetadata("CodeGeneratorType", "TypeScript")] + internal class CSharpCodeGenerator : IPasteJsonCodeGenerator + { + private Regex _validIdentifierRegex = new Regex(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Nl}\p{Mn}\p{Mc}\p{Cf}\p{Pc}\p{Lm}]"); + + public string GenerateStartClass(string className) + { + return string.Format("interface {0}", className) + Environment.NewLine + "{"; + } + + public string GenerateProperty(PasteJsonUtil.LangIndependentType langIndependentType, string propertyName) + { + return string.Format("{1}: {0};", GeneratePropertyTypeName(langIndependentType), propertyName); + } + + public string GenerateObjectProperty(string typeOfObject, string propertyName) + { + return string.Format("{1}: {0};", typeOfObject, propertyName); + } + + public string GenerateArrayProperty(int dimensions, string typeOfArray, string propertyName) + { + if (dimensions > 0) + { + string mutliDimension = GetArrayDeclaration(dimensions); + return string.Format("{2}: {0}{1};", typeOfArray, mutliDimension, propertyName); + } + return null; + } + + public string GenerateArrayProperty(int dimensions, PasteJsonUtil.LangIndependentType langIndependentType, string propertyName) + { + if (dimensions > 0) + { + string mutliDimension = GetArrayDeclaration(dimensions); + return string.Format("{2}: {0}{1};", GeneratePropertyTypeName(langIndependentType), mutliDimension, propertyName); + } + return null; + } + + private string GetArrayDeclaration(int dimension) + { + StringBuilder arrayDeclaration = new StringBuilder(); + for (int loop = 1; loop <= dimension; loop++) + { + arrayDeclaration.Append(GeneratePropertyTypeName(PasteJsonUtil.LangIndependentType.Array)); + } + return arrayDeclaration.ToString(); + } + + public string GenerateEndClass(string className) + { + return "}"; + } + + public string MakeValidName(string name) + { + return _validIdentifierRegex.Replace(name, ""); + } + + private string GeneratePropertyTypeName(PasteJsonUtil.LangIndependentType langIndependentType) + { + string returnType = string.Empty; + Debug.Assert(langIndependentType != PasteJsonUtil.LangIndependentType.Object, "I should not be expecting Object"); + + switch (langIndependentType) + { + case PasteJsonUtil.LangIndependentType.Array: + returnType = "[]"; + break; + case PasteJsonUtil.LangIndependentType.Boolean: + returnType = "bool"; + break; + case PasteJsonUtil.LangIndependentType.Date: + returnType = "Date"; + break; + case PasteJsonUtil.LangIndependentType.Double: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.Float: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.Integer: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.Long: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.NullableBoolean: + returnType = "bool"; + break; + case PasteJsonUtil.LangIndependentType.NullableDate: + returnType = "Date"; + break; + case PasteJsonUtil.LangIndependentType.NullableDouble: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.NullableFloat: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.NullableInteger: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.NullableLong: + returnType = "number"; + break; + case PasteJsonUtil.LangIndependentType.NullOrUndefined: + returnType = "any"; + break; + case PasteJsonUtil.LangIndependentType.String: + returnType = "string"; + break; + case PasteJsonUtil.LangIndependentType.Unknown: + returnType = "any"; + break; + case PasteJsonUtil.LangIndependentType.Uri: + returnType = "string"; + break; + default: + Debug.Assert(true, "Property Type:" + langIndependentType.ToString() + " is not supported !!"); + break; + } + return returnType; + } + } +} diff --git a/EditorExtensions/Commands/Shared/EncodeSelectionCommandTarget.cs b/EditorExtensions/Commands/Shared/EncodeSelectionCommandTarget.cs new file mode 100644 index 000000000..193558618 --- /dev/null +++ b/EditorExtensions/Commands/Shared/EncodeSelectionCommandTarget.cs @@ -0,0 +1,81 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Web; + +namespace MadsKristensen.EditorExtensions +{ + internal class EncodeSelection : CommandTargetBase + { + private DTE2 _dte; + private static uint[] _commandIds = new uint[] { + PkgCmdIDList.htmlEncode, + PkgCmdIDList.htmlDecode, + PkgCmdIDList.attrEncode, + PkgCmdIDList.urlEncode, + PkgCmdIDList.urlDecode, + PkgCmdIDList.urlPathEncode, + PkgCmdIDList.jsEncode, + }; + + private delegate string Replacement(string original); + + public EncodeSelection(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidEditorExtensionsCmdSet, _commandIds) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + switch (commandId) + { + case PkgCmdIDList.htmlEncode: + return Replace(HttpUtility.HtmlEncode); + case PkgCmdIDList.htmlDecode: + return Replace(HttpUtility.HtmlDecode); + case PkgCmdIDList.attrEncode: + return Replace(HttpUtility.HtmlAttributeEncode); + case PkgCmdIDList.urlEncode: + return Replace(HttpUtility.UrlEncode); + case PkgCmdIDList.urlDecode: + return Replace(HttpUtility.UrlDecode); + case PkgCmdIDList.urlPathEncode: + return Replace(HttpUtility.UrlPathEncode); + case PkgCmdIDList.jsEncode: + return Replace(HttpUtility.JavaScriptStringEncode); + } + + return true; + } + + private bool Replace(Replacement callback) + { + TextDocument document = GetTextDocument(); + string replacement = callback(document.Selection.Text); + + _dte.UndoContext.Open(callback.Method.Name); + document.Selection.Insert(replacement, 0); + _dte.UndoContext.Close(); + + return true; + } + + private TextDocument GetTextDocument() + { + return _dte.ActiveDocument.Object("TextDocument") as TextDocument; + } + + protected override bool IsEnabled() + { + if (TextView != null && TextView.Selection.SelectedSpans.Count > 0) + { + return TextView.Selection.SelectedSpans[0].Length > 0; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Shared/MinifySelectionCommandTarget.cs b/EditorExtensions/Commands/Shared/MinifySelectionCommandTarget.cs new file mode 100644 index 000000000..99c104569 --- /dev/null +++ b/EditorExtensions/Commands/Shared/MinifySelectionCommandTarget.cs @@ -0,0 +1,48 @@ +using EnvDTE80; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + internal class MinifySelection : CommandTargetBase + { + private DTE2 _dte; + + public MinifySelection(IVsTextView adapter, IWpfTextView textView) + : base(adapter, textView, GuidList.guidMinifyCmdSet, PkgCmdIDList.MinifySelection) + { + _dte = EditorExtensionsPackage.DTE; + } + + protected override bool Execute(uint commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (TextView != null) + { + _dte.UndoContext.Open("Minify"); + + string content = TextView.Selection.SelectedSpans[0].GetText(); + string extension = Path.GetExtension(_dte.ActiveDocument.FullName).ToLowerInvariant(); + string result = MinifyFileMenu.MinifyString(extension, content); + + TextView.TextBuffer.Replace(TextView.Selection.SelectedSpans[0].Span, result); + + _dte.UndoContext.Close(); + } + + return true; + } + + protected override bool IsEnabled() + { + if (TextView != null && TextView.Selection.SelectedSpans.Count > 0) + { + return TextView.Selection.SelectedSpans[0].Length > 0; + } + + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Commands/Shared/TextCreationListener.cs b/EditorExtensions/Commands/Shared/TextCreationListener.cs new file mode 100644 index 000000000..9d5c8c5e0 --- /dev/null +++ b/EditorExtensions/Commands/Shared/TextCreationListener.cs @@ -0,0 +1,28 @@ +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IVsTextViewCreationListener))] + [ContentType("text")] + [TextViewRole(PredefinedTextViewRoles.Document)] + class TextViewCreationListener : IVsTextViewCreationListener + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; } + + [Import] + internal ICompletionBroker CompletionBroker { get; set; } + + public void VsTextViewCreated(IVsTextView textViewAdapter) + { + var textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); + + textView.Properties.GetOrCreateSingletonProperty(() => new EncodeSelection(textViewAdapter, textView)); + } + } +} diff --git a/EditorExtensions/Commands/TypeThrough/CSSTypeThroughControllerProvider.cs b/EditorExtensions/Commands/TypeThrough/CSSTypeThroughControllerProvider.cs new file mode 100644 index 000000000..8c37932ad --- /dev/null +++ b/EditorExtensions/Commands/TypeThrough/CSSTypeThroughControllerProvider.cs @@ -0,0 +1,84 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [ContentType(CssContentTypeDefinition.CssContentType)] + [Name("CSS Type Through Completion Controller")] + [Order(Before = "Default Completion Controller")] + [TextViewRole(PredefinedTextViewRoles.Editable)] + internal class CssTypeThroughControllerProvider : IIntellisenseControllerProvider + { + public IIntellisenseController TryCreateIntellisenseController(ITextView view, IList subjectBuffers) + { + if (subjectBuffers[0].ContentType.IsOfType(CssContentTypeDefinition.CssContentType)) + { + var completionController = ServiceManager.GetService(subjectBuffers[0]); + + if (completionController == null) + completionController = new CssTypeThroughController(view, subjectBuffers); + + return completionController; + } + + return null; + } + } + + internal class CssTypeThroughController : TypeThroughController + { + public CssTypeThroughController(ITextView textView, IList subjectBuffers) + : base(textView, subjectBuffers) + { + } + + protected override bool CanComplete(ITextBuffer textBuffer, int position) + { + var document = CssEditorDocument.FromTextBuffer(textBuffer); + + var item = document.StyleSheet.ComplexItemFromRange(position, 0); + if (item is Comment) + return false; + + var tokenItem = document.StyleSheet.ItemFromRange(position, 0); + var ti = tokenItem as TokenItem; + if (ti != null) + { + if ((ti.TokenType == CssTokenType.String || ti.TokenType == CssTokenType.MultilineString) && !ti.IsUnclosed) + return false; + } + + return true; + } + + protected override char GetCompletionCharacter(char typedCharacter) + { + switch (typedCharacter) + { + //case '\"': + //case '\'': + // return typedCharacter; + + //case '[': + // return ']'; + + //case '(': + // return ')'; + + case '{': + return '}'; + } + + return '\0'; + } + } +} diff --git a/EditorExtensions/Commands/TypeThrough/JavaScriptTypeThroughControllerProvider.cs b/EditorExtensions/Commands/TypeThrough/JavaScriptTypeThroughControllerProvider.cs new file mode 100644 index 000000000..d3b7004b6 --- /dev/null +++ b/EditorExtensions/Commands/TypeThrough/JavaScriptTypeThroughControllerProvider.cs @@ -0,0 +1,76 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [ContentType("JavaScript")] + [ContentType("TypeScript")] + [Name("JavaScript Type Through Completion Controller")] + [Order(Before = "Default Completion Controller")] + [TextViewRole(PredefinedTextViewRoles.Editable)] + internal class JavaScriptTypeThroughControllerProvider : IIntellisenseControllerProvider + { + public IIntellisenseController TryCreateIntellisenseController(ITextView view, IList subjectBuffers) + { + if (subjectBuffers.Count > 0 && (subjectBuffers[0].ContentType.IsOfType("JavaScript") || subjectBuffers[0].ContentType.IsOfType("TypeScript"))) + { + var completionController = ServiceManager.GetService(subjectBuffers[0]); + + if (completionController == null) + completionController = new JavaScriptTypeThroughController(view, subjectBuffers); + + return completionController; + } + + return null; + } + } + + internal class JavaScriptTypeThroughController : TypeThroughController + { + public JavaScriptTypeThroughController(ITextView textView, IList subjectBuffers) + : base(textView, subjectBuffers) + { + } + + protected override bool CanComplete(ITextBuffer textBuffer, int position) + { + bool result = WESettings.GetBoolean(WESettings.Keys.JavaScriptAutoCloseBraces); + + if (result) + { + var line = textBuffer.CurrentSnapshot.GetLineFromPosition(position); + result = line.Start.Position + line.GetText().TrimEnd('\r', '\n', ' ', ';', ',').Length == position + 1; + } + + return result; + } + + protected override char GetCompletionCharacter(char typedCharacter) + { + switch (typedCharacter) + { + //case '\"': + //case '\'': + // return typedCharacter; + + case '[': + return ']'; + + case '(': + return ')'; + + case '{': + return '}'; + } + + return '\0'; + } + } +} diff --git a/EditorExtensions/Commands/TypeThrough/LESSTypeThroughControllerProvider.cs b/EditorExtensions/Commands/TypeThrough/LESSTypeThroughControllerProvider.cs new file mode 100644 index 000000000..5a4996557 --- /dev/null +++ b/EditorExtensions/Commands/TypeThrough/LESSTypeThroughControllerProvider.cs @@ -0,0 +1,58 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.Less.Core; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [ContentType(LessContentTypeDefinition.LessContentType)] + [Name("LESS Type Through Completion Controller")] + [Order(Before = "Default Completion Controller")] + [TextViewRole(PredefinedTextViewRoles.Editable)] + internal class LessTypeThroughControllerProvider : IIntellisenseControllerProvider + { + public IIntellisenseController TryCreateIntellisenseController(ITextView view, IList subjectBuffers) + { + var completionController = ServiceManager.GetService(subjectBuffers[0]); + + if (completionController == null) + completionController = new LessTypeThroughController(view, subjectBuffers); + + return completionController; + } + } + + internal class LessTypeThroughController : CssTypeThroughController + { + public LessTypeThroughController(ITextView view, IList subjectBuffers) : + base(view, subjectBuffers) + { + } + + protected override bool CanComplete(ITextBuffer textBuffer, int position) + { + var document = CssEditorDocument.FromTextBuffer(textBuffer); + + var item = document.StyleSheet.ComplexItemFromRange(position, 0); + if (item is CppComment || item is CppCommentText) + return false; + + var tokenItem = document.StyleSheet.ItemFromRange(position, 0); + var ti = tokenItem as TokenItem; + if (ti != null) + { + if (ti.Token.IsComment) + return false; + } + + return base.CanComplete(textBuffer, position); + } + } +} diff --git a/EditorExtensions/Commands/TypeThrough/ProvisionalText.cs b/EditorExtensions/Commands/TypeThrough/ProvisionalText.cs new file mode 100644 index 000000000..38505bf7f --- /dev/null +++ b/EditorExtensions/Commands/TypeThrough/ProvisionalText.cs @@ -0,0 +1,264 @@ +using System; +using System.Linq; +using System.ComponentModel.Composition; +using System.Windows; +using System.Windows.Media; +using System.Windows.Shapes; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Projection; +using Microsoft.VisualStudio.Utilities; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewCreationListener))] + [ContentType("CSS")] + [ContentType("JavaScript")] + [TextViewRole(PredefinedTextViewRoles.Document)] + internal sealed class HtmlProvisionalTextHighlightFactory : IWpfTextViewCreationListener + { + [Export(typeof(AdornmentLayerDefinition))] + [Name("HtmlProvisionalTextHighlight")] + [Order(Before = PredefinedAdornmentLayers.Outlining)] + [TextViewRole(PredefinedTextViewRoles.Document)] + public AdornmentLayerDefinition EditorAdornmentLayer { get; set; } + + public void TextViewCreated(IWpfTextView textView) + { + } + } + + public class ProvisionalText + { + public static bool IgnoreChange { get; set; } + + public event EventHandler OnClose; + public char ProvisionalChar { get; private set; } + public ITrackingSpan TrackingSpan { get; private set; } + + private ITextView _textView; + private IAdornmentLayer _layer; + private Path _highlightAdornment; + private Brush _highlightBrush; + private bool _overtype = false; + private bool _delete = false; + private bool _projectionsChanged = false; + private bool _adornmentRemoved = false; + private IProjectionBuffer _projectionBuffer; + + public ProvisionalText(ITextView textView, Span textSpan) + { + IgnoreChange = false; + + _textView = textView; + + var wpfTextView = _textView as IWpfTextView; + _layer = wpfTextView.GetAdornmentLayer("HtmlProvisionalTextHighlight"); + + var textBuffer = _textView.TextBuffer; + var snapshot = textBuffer.CurrentSnapshot; + var provisionalCharSpan = new Span(textSpan.End - 1, 1); + + TrackingSpan = snapshot.CreateTrackingSpan(textSpan, SpanTrackingMode.EdgeExclusive); + _textView.Caret.PositionChanged += OnCaretPositionChanged; + + textBuffer.Changed += OnTextBufferChanged; + textBuffer.PostChanged += OnPostChanged; + + var _projectionBuffer = _textView.TextBuffer as IProjectionBuffer; + if (_projectionBuffer != null) + { + _projectionBuffer.SourceSpansChanged += OnSourceSpansChanged; + } + + Color highlightColor = SystemColors.HighlightColor; + Color baseColor = Color.FromArgb(96, highlightColor.R, highlightColor.G, highlightColor.B); + _highlightBrush = new SolidColorBrush(baseColor); + + ProvisionalChar = snapshot.GetText(provisionalCharSpan)[0]; + HighlightSpan(provisionalCharSpan.Start); + } + + public Span CurrentSpan + { + get + { + return TrackingSpan.GetSpan(_textView.TextBuffer.CurrentSnapshot); + } + } + + private void EndTracking() + { + if (_textView != null) + { + ClearHighlight(); + + if (_projectionBuffer != null) + { + _projectionBuffer.SourceSpansChanged -= OnSourceSpansChanged; + _projectionBuffer = null; + } + + if (_projectionsChanged || _adornmentRemoved) + { + _projectionsChanged = false; + _adornmentRemoved = false; + } + + _textView.TextBuffer.Changed -= OnTextBufferChanged; + _textView.TextBuffer.PostChanged -= OnPostChanged; + + _textView.Caret.PositionChanged -= OnCaretPositionChanged; + _textView = null; + + if (OnClose != null) + OnClose(this, EventArgs.Empty); + } + } + + public bool IsPositionInSpan(int position) + { + if (_textView != null) + { + if (CurrentSpan.Contains(position) && position > CurrentSpan.Start) + return true; + } + + return false; + } + + private void OnSourceSpansChanged(object sender, ProjectionSourceSpansChangedEventArgs e) + { + _projectionsChanged = true; + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => ResoreHighlight())); + } + + void OnCaretPositionChanged(object sender, CaretPositionChangedEventArgs e) + { + // If caret moves outside of the text tracking span, consider text final + var position = _textView.Caret.Position.BufferPosition; + + if (!CurrentSpan.Contains(position) || position == CurrentSpan.Start) + { + EndTracking(); + } + } + + void OnPostChanged(object sender, EventArgs e) + { + if (_textView != null && !IgnoreChange && !_projectionsChanged) + { + if (_overtype || _delete) + { + _textView.TextBuffer.Replace(new Span(CurrentSpan.End - 1, 1), String.Empty); + EndTracking(); + } + else + { + HighlightSpan(CurrentSpan.End - 1); + } + } + } + + void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) + { + // Zero changes typically means secondary buffer regeneration + if (e.Changes.Count == 0) + { + _projectionsChanged = true; + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => ResoreHighlight())); + } + + if (_textView != null && !IgnoreChange && !_projectionsChanged) + { + // If there is a change outside text span or change over provisional + // text, we are done here: commit provisional text and disconnect. + + if (CurrentSpan.Length > 0 && e.Changes.Count == 1) + { + var change = e.Changes[0]; + + if (CurrentSpan.Contains(change.OldSpan)) + { + // Check provisional text overtype + if (change.OldLength == 0 && change.NewLength == 1 && change.OldPosition == CurrentSpan.End - 2) + { + char ch = _textView.TextBuffer.CurrentSnapshot.GetText(change.NewPosition, 1)[0]; + + if (ch == ProvisionalChar) + _overtype = true; + } + else if (change.NewLength > 0 && change.NewText.Last() == ProvisionalChar)//(change.NewLength == 0 && change.OldLength > 0 && change.OldPosition == CurrentSpan.Start) + { + // Deleting open quote or brace should also delete provisional character + _delete = true; + } + + return; + } + } + + EndTracking(); + } + } + + private void ResoreHighlight() + { + if (_textView != null && (_projectionsChanged || _adornmentRemoved)) + { + HighlightSpan(CurrentSpan.End - 1); + } + + _projectionsChanged = false; + _adornmentRemoved = false; + } + + void HighlightSpan(int bufferPosition) + { + ClearHighlight(); + + var wpfTextView = _textView as IWpfTextView; + var snapshotSpan = new SnapshotSpan(wpfTextView.TextBuffer.CurrentSnapshot, new Span(bufferPosition, 1)); + + Geometry highlightGeometry = wpfTextView.TextViewLines.GetTextMarkerGeometry(snapshotSpan); + if (highlightGeometry != null) + { + _highlightAdornment = new Path(); + _highlightAdornment.Data = highlightGeometry; + _highlightAdornment.Fill = _highlightBrush; + } + + if (_highlightAdornment != null) + { + _layer.AddAdornment( + AdornmentPositioningBehavior.TextRelative, snapshotSpan, + this, _highlightAdornment, new AdornmentRemovedCallback(OnAdornmentRemoved)); + } + } + + private bool _removing = false; + + private void OnAdornmentRemoved(object tag, UIElement element) + { + if (_removing) + return; + + _adornmentRemoved = true; + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => ResoreHighlight())); + } + + private void ClearHighlight() + { + if (_highlightAdornment != null) + { + _removing = true; + + _layer.RemoveAdornment(_highlightAdornment); + _highlightAdornment = null; + + _removing = false; + } + } + } +} diff --git a/EditorExtensions/Commands/TypeThrough/TypeThroughController.cs b/EditorExtensions/Commands/TypeThrough/TypeThroughController.cs new file mode 100644 index 000000000..2f54e8a6c --- /dev/null +++ b/EditorExtensions/Commands/TypeThrough/TypeThroughController.cs @@ -0,0 +1,252 @@ +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace MadsKristensen.EditorExtensions +{ + public class TypeThroughController : IIntellisenseController + { + ITextBuffer _textBuffer; + ITextView _textView; + + List _provisionalTexts = new List(); + char _typedChar = '\0'; + bool _processing = false; + int _caretPosition = 0; + int _bufferVersionWaterline; + + public TypeThroughController(ITextView textView, IList subjectBuffers) + { + _textBuffer = subjectBuffers[0]; + _textView = textView; + + _textBuffer.Changed += TextBuffer_Changed; + _textBuffer.PostChanged += TextBuffer_PostChanged; + + _bufferVersionWaterline = _textBuffer.CurrentSnapshot.Version.ReiteratedVersionNumber; + } + + protected virtual bool CanComplete(ITextBuffer textBuffer, int position) + { + return true; + } + + void TextBuffer_PostChanged(object sender, System.EventArgs e) + { + if (!_processing && _typedChar != '\0') + { + OnPostTypeChar(_typedChar); + _typedChar = '\0'; + } + } + + void TextBuffer_Changed(object sender, TextContentChangedEventArgs e) + { + if (_processing) + return; + + _typedChar = '\0'; + + if (e.Changes.Count == 1 && e.AfterVersion.ReiteratedVersionNumber > _bufferVersionWaterline) + { + var change = e.Changes[0]; + + _bufferVersionWaterline = e.AfterVersion.ReiteratedVersionNumber; + + // Change length may be > 1 in autoformatting languages. + // However, there will be only one non-ws character in the change. + // Be careful when is inserted: the change won't + // actually be in this buffer. + + var snapshot = _textBuffer.CurrentSnapshot; + if (change.NewSpan.End <= snapshot.Length) + { + var text = _textBuffer.CurrentSnapshot.GetText(change.NewSpan); + text = text.Trim(); + + if (text.Length == 1) + { + // Allow completion of different characters inside spans, but not when + // character and its completion pair is the same. For example, we do + // want to complete () in foo(bar|) when user types ( after bar. However, + // we do not want to complete " when user is typing in a string which + // was already completed and instead " should be a terminating type-through. + + var typedChar = text[0]; + var completionChar = GetCompletionCharacter(typedChar); + + var caretPosition = GetCaretPositionInBuffer(); + if (caretPosition.HasValue) + { + bool compatible = true; + + var innerText = GetInnerProvisionalText(); + if (innerText != null) + compatible = IsCompatibleCharacter(innerText.ProvisionalChar, typedChar); + + if (!IsPositionInProvisionalText(caretPosition.Value) || typedChar != completionChar || compatible) + { + _typedChar = typedChar; + _caretPosition = caretPosition.Value; + } + } + } + } + } + } + + protected virtual char GetCompletionCharacter(char typedCharacter) + { + switch (typedCharacter) + { + //case '\"': + //case '\'': + // return typedCharacter; + + //case '[': + // return ']'; + + //case '(': + // return ')'; + + case '{': + case '}': + return '}'; + } + + return '\0'; + } + + protected virtual bool IsCompatibleCharacter(char primaryCharacter, char candidateCharacter) + { + if (primaryCharacter == '\"' || primaryCharacter == '\'') + return false; // no completion in strings + + return true; + } + + private void OnPostTypeChar(char typedCharacter) + { + // When language autoformats, like JS, caret may be in a very different + // place by now. Check if store caret position still makes sense and + // if not, reacquire it. In contained language scenario + // current caret position may be beyond projection boundary like when + // typing at the end of onclick="return foo(". + + //var settings = WebEditor.GetSettings(_textBuffer.ContentType.TypeName); + //if (settings.GetBoolean(CommonSettings.InsertMatchingBracesKey)) + if (WESettings.GetBoolean(WESettings.Keys.AutoCloseCurlyBraces)) + { + char completionCharacter = GetCompletionCharacter(typedCharacter); + if (completionCharacter != '\0') + { + var viewCaretPosition = _textView.Caret.Position.BufferPosition; + _processing = true; + + var bufferCaretPosition = GetCaretPositionInBuffer(); + if (bufferCaretPosition.HasValue) + { + _caretPosition = bufferCaretPosition.Value; + } + else if (viewCaretPosition.Position == _textView.TextBuffer.CurrentSnapshot.Length) + { + _caretPosition = _textBuffer.CurrentSnapshot.Length; + } + + if (_caretPosition > 0) + { + if (CanComplete(_textBuffer, _caretPosition - 1)) + { + ProvisionalText.IgnoreChange = true; + _textView.TextBuffer.Replace(new Span(viewCaretPosition, 0), completionCharacter.ToString()); + ProvisionalText.IgnoreChange = false; + + _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, viewCaretPosition)); + + var provisionalText = new ProvisionalText(_textView, new Span(viewCaretPosition - 1, 2)); + provisionalText.OnClose += new System.EventHandler(OnCloseProvisionalText); + + _provisionalTexts.Add(provisionalText); + } + } + } + + _processing = false; + } + } + + private SnapshotPoint? GetCaretPositionInBuffer() + { + var viewCaretPosition = _textView.Caret.Position.BufferPosition.Position; + var snapshot = _textView.TextBuffer.CurrentSnapshot; + + if (viewCaretPosition > snapshot.Length) + return null; + + return _textView.BufferGraph.MapDownToBuffer( + new SnapshotPoint(_textView.TextBuffer.CurrentSnapshot, viewCaretPosition), PointTrackingMode.Positive, + _textBuffer, PositionAffinity.Predecessor); + } + + private bool IsPositionInProvisionalText(int position) + { + foreach (var pt in _provisionalTexts) + { + if (pt.IsPositionInSpan(position)) + return true; + } + + return false; + } + + private ProvisionalText GetInnerProvisionalText() + { + int minLength = Int32.MaxValue; + ProvisionalText innerText = null; + + foreach (var pt in _provisionalTexts) + { + if (pt.CurrentSpan.Length < minLength) + { + minLength = pt.CurrentSpan.Length; + innerText = pt; + } + } + + return innerText; + } + + private void OnCloseProvisionalText(object sender, EventArgs e) + { + _provisionalTexts.Remove(sender as ProvisionalText); + } + + #region IIntellisenseController Members + + public void ConnectSubjectBuffer(ITextBuffer subjectBuffer) + { + if (_textBuffer != null) + { + _textBuffer.Changed += TextBuffer_Changed; + _textBuffer.PostChanged += TextBuffer_PostChanged; + } + } + + public void Detach(ITextView textView) + { + } + + public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer) + { + if (_textBuffer != null) + { + _textBuffer.Changed -= TextBuffer_Changed; + _textBuffer.PostChanged -= TextBuffer_PostChanged; + } + } + + #endregion + } +} diff --git a/EditorExtensions/Completion/CompletionListEntry.cs b/EditorExtensions/Completion/CompletionListEntry.cs new file mode 100644 index 000000000..a3cd2ae5b --- /dev/null +++ b/EditorExtensions/Completion/CompletionListEntry.cs @@ -0,0 +1,77 @@ +using System; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + internal class CompletionListEntry : ICssCompletionListEntry + { + private string _name; + + public CompletionListEntry(string name, int sortingPriority = 0) + { + _name = name; + SortingPriority = sortingPriority; + } + + public string Description + { + get { return string.Empty; } + } + + public string DisplayText + { + get { return _name; } + } + + public string GetSyntax(Version version) + { + return string.Empty; + } + + public StandardGlyphGroup StandardGlyph + { + get { return StandardGlyphGroup.GlyphGroupEnumMember; } + } + + public string GetAttribute(string name) + { + return string.Empty; + } + + public string GetInsertionText(CssTextSource textSource, ITrackingSpan typingSpan) + { + return DisplayText; + } + + public string GetVersionedAttribute(string name, Version version) + { + return GetAttribute(name); + } + + public bool AllowQuotedString + { + get { return false; } + } + + public bool IsBuilder + { + get { return false; } + } + + public int SortingPriority { get; set; } + + + public bool IsSupported(BrowserVersion browser) + { + return true; + } + + public bool IsSupported(Version cssVersion) + { + return true; + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/AnimationNameCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/AnimationNameCompletionProvider.cs new file mode 100644 index 000000000..f9c3b8473 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/AnimationNameCompletionProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("AnimationNameCompletionProvider")] + internal class AnimationNameCompletionProvider : ICssCompletionListProvider + { + public CssCompletionContextType ContextType + { + get { return CssCompletionContextType.PropertyValue; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + HashSet entries = new HashSet(); + Declaration dec = context.ContextItem.FindType(); + + if (dec == null || dec.PropertyName == null || (!dec.PropertyName.Text.EndsWith("animation-name", StringComparison.OrdinalIgnoreCase) && dec.PropertyName.Text != "animation")) + return entries; + + StyleSheet stylesheet = context.ContextItem.StyleSheet; + var visitor = new CssItemCollector(); + stylesheet.Accept(visitor); + + foreach (KeyFramesDirective keyframes in visitor.Items) + { + if (!entries.Any(e => e.DisplayText.Equals(keyframes.Name.Text, StringComparison.OrdinalIgnoreCase))) + entries.Add(new CompletionListEntry(keyframes.Name.Text)); + } + + return entries; + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/ClassCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/ClassCompletionProvider.cs new file mode 100644 index 000000000..76710f230 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/ClassCompletionProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("ClassCompletionProvider")] + internal class ClassCompletionProvider : ICssCompletionListProvider + { + public CssCompletionContextType ContextType + { + get { return (CssCompletionContextType)602; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + HashSet classNames = new HashSet(); + HashSet entries = new HashSet(); + + StyleSheet stylesheet = context.ContextItem.StyleSheet; + var visitorRules = new CssItemCollector(); + stylesheet.Accept(visitorRules); + + foreach (ClassSelector item in visitorRules.Items) + { + if (item != context.ContextItem && !classNames.Contains(item.Text)) + { + classNames.Add(item.Text); + entries.Add(new CompletionListEntry(item.Text)); + } + } + + return entries; + } + + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/ColorCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/ColorCompletionProvider.cs new file mode 100644 index 000000000..aefb808b7 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/ColorCompletionProvider.cs @@ -0,0 +1,49 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Drawing; +using System.Reflection; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("ColorCompletionProvider")] + [Order(Before = "Default PropertyValue")] + internal class ColorCompletionProvider : ICssCompletionListProvider, ICssCompletionPresenterProvider + { + public CssCompletionContextType ContextType + { + get { return CssCompletionContextType.PropertyValue; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + yield break; + } + + public CompletionPresenterInfo TryCreateCompletionPresenter(ICompletionSession session, CssCompletionContext context) + { + string text = context.Snapshot.GetText(context.SpanStart, context.SpanLength); + if (Color.FromName(text).IsKnownColor) + { + return CreatePresenter(session, context); + } + + return new CompletionPresenterInfo(null, true); + } + + private static CompletionPresenterInfo CreatePresenter(ICompletionSession session, CssCompletionContext context) + { + object[] parameters = new object[] { session, context }; + BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; + Type type = typeof(CssClassifier).Assembly.GetType("Microsoft.CSS.Editor.ColorPickerPresenter"); + object colorPicker = Activator.CreateInstance(type, flags, null, parameters, null); + + return new CompletionPresenterInfo((IIntellisensePresenter)colorPicker, false); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/CompletionProviders/FontCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/FontCompletionProvider.cs new file mode 100644 index 000000000..7e74e032e --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/FontCompletionProvider.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Windows.Forms; +using System.Windows.Threading; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("FontCompletionProvider")] + internal class FontCompletionProvider : ICssCompletionListProvider, ICssCompletionCommitListener + { + private static List _emptyList = new List(); + public CssCompletionContextType ContextType + { + get { return CssCompletionContextType.PropertyValue; } + } + + public static bool IsFontFamilyContext(CssCompletionContext context) + { + if (context != null && context.ContextItem != null) + { + Declaration decl = context.ContextItem.Parent as Declaration; + string propertyName = (decl != null && decl.PropertyName != null) ? decl.PropertyName.Text : string.Empty; + + // Currently, only "font-family" will show font names, so just hard-code that name. + if (propertyName == "font-family") + { + return true; + } + } + + return false; + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + if (IsFontFamilyContext(context)) + { + List entries = new List(); + List idNames = new List(); + + StyleSheet stylesheet = context.ContextItem.StyleSheet; + var visitorRules = new CssItemCollector(); + stylesheet.Accept(visitorRules); + + foreach (FontFaceDirective item in visitorRules.Items) + { + var visitorDec = new CssItemCollector(); + item.Block.Accept(visitorDec); + + Declaration family = visitorDec.Items.FirstOrDefault(i => i.PropertyName.Text == "font-family"); + + if (family != null) + { + string value = string.Join(string.Empty, family.Values.Select(v => v.Text)); + entries.Add(new FontFamilyCompletionListEntry(value.Trim('\'', '"'))); + } + } + + entries.Add(new FontFamilyCompletionListEntry("Pick from file...")); + + return entries; + } + + return _emptyList; + } + + public void OnCommitted(ICssCompletionListEntry entry, ITrackingSpan contextSpan, SnapshotPoint caret, ITextView textView) + { + if (entry.DisplayText == "Pick from file...") + { + string fontFamily; + string atDirective = GetFontFromFile(entry.DisplayText, (IWpfTextView)textView, out fontFamily); + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => Replace(contextSpan, textView, atDirective, fontFamily)), DispatcherPriority.Normal); + + } + } + + private static void Replace(ITrackingSpan contextSpan, ITextView textView, string atDirective, string fontFamily) + { + EditorExtensionsPackage.DTE.UndoContext.Open("Embed font"); + textView.TextBuffer.Insert(0, atDirective + Environment.NewLine + Environment.NewLine); + textView.TextBuffer.Insert(contextSpan.GetSpan(textView.TextBuffer.CurrentSnapshot).Start, fontFamily); + EditorExtensionsPackage.DTE.UndoContext.Close(); + + } + + private static object _syncRoot = new object(); + private string GetFontFromFile(string text, IWpfTextView view, out string fontFamily) + { + lock (_syncRoot) + { + fontFamily = text; + OpenFileDialog dialog = new OpenFileDialog(); + dialog.InitialDirectory = Path.GetDirectoryName(EditorExtensionsPackage.DTE.ActiveDocument.FullName); + dialog.Filter = "Fonts (*.woff;*.eot;*.ttf;*.otf;*.svg)|*.woff;*.eot;*.ttf;*.otf;*.svg"; + dialog.DefaultExt = ".woff"; + + if (dialog.ShowDialog() == DialogResult.OK) + { + FontDropHandler fdh = new FontDropHandler(view); + return fdh.GetCodeFromFile(dialog.FileName, out fontFamily); + } + + return text; + } + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/FontFamilyCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/FontFamilyCompletionProvider.cs new file mode 100644 index 000000000..0aa82bb6d --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/FontFamilyCompletionProvider.cs @@ -0,0 +1,57 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("FontFamilyCompletionProvider")] + internal class FontFamilyCompletionProvider : ICssCompletionListProvider + { + private static List _entryCache = new List() + { + "Arial, 'DejaVu Sans', 'Liberation Sans', Freesans, sans-serif", + "'Arial Narrow', 'Nimbus Sans L', sans-serif", + "'Arial Black', Gadget, sans-serif", + "'Bookman Old Style', Bookman, 'URW Bookman L', 'Palatino Linotype', serif", + "'Century Gothic', futura, 'URW Gothic L', Verdana, sans-serif", + "'Comic Sans MS', cursive", + "Consolas, 'Lucida Console', 'DejaVu Sans Mono', monospace", + "'Courier New', Courier, 'Nimbus Mono L', monospace", + "Constantina, Georgia, 'Nimbus Roman No9 L', serif", + "Helvetica, Arial, 'DejaVu Sans', 'Liberation Sans', Freesans, sans-serif", + "Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif", + "'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans Condensed', sans-serif", + "Cambria, 'Palatino Linotype', 'Book Antiqua', 'URW Palladio L', serif", + "symbol, 'Standard Symbols L'", + "Cambria, 'Times New Roman', 'Nimbus Roman No9 L', 'Freeserif', Times, serif", + "Verdana, Geneva, 'DejaVu Sans', sans-serif", + "'Monotype Corsiva', 'Apple Chancery', 'ITC Zapf Chancery', 'URW Chancery L', cursive", + "'Monotype Sorts', dingbats, 'ITC Zapf Dingbats', fantasy" + }; + + public CssCompletionContextType ContextType + { + get { return CssCompletionContextType.PropertyValue; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + Declaration dec = context.ContextItem.FindType(); + + if (dec == null || dec.PropertyName == null || dec.PropertyName.Text != "font-family") + yield break; + + foreach (string item in _entryCache) + { + ICssCompletionListEntry entry = new CompletionListEntry(item, 1); + yield return entry; + } + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/IdCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/IdCompletionProvider.cs new file mode 100644 index 000000000..4a8b2d07c --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/IdCompletionProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("IdCompletionProvider")] + internal class IdCompletionProvider : ICssCompletionListProvider + { + public CssCompletionContextType ContextType + { + get { return (CssCompletionContextType)603; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + List idNames = new List(); + List entries = new List(); + + StyleSheet stylesheet = context.ContextItem.StyleSheet; + var visitorRules = new CssItemCollector(); + stylesheet.Accept(visitorRules); + + foreach (IdSelector item in visitorRules.Items) + { + if (item != context.ContextItem && !idNames.Contains(item.Text)) + { + idNames.Add(item.Text); + entries.Add(new CompletionListEntry(item.Text)); + } + } + + return entries; + } + + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/ImportantCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/ImportantCompletionProvider.cs new file mode 100644 index 000000000..ce33b0aee --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/ImportantCompletionProvider.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("ImportantCompletionProvider")] + internal class ImportantCompletionProvider : ICssCompletionListProvider + { + public CssCompletionContextType ContextType + { + get { return CssCompletionContextType.PropertyValue; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + List entries = new List(); + Declaration dec = context.ContextItem.FindType(); + if (dec == null || dec.Colon == null || dec.Important != null || dec.Values.Count == 0) + return entries; + + ParseItem before = dec.ItemBeforePosition(context.SpanStart); + if (before != null && before.Text == "!") + entries.Add(new CompletionListEntry("important", 1)); + + return entries; + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/RegionCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/RegionCompletionProvider.cs new file mode 100644 index 000000000..2c1f40f66 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/RegionCompletionProvider.cs @@ -0,0 +1,44 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("RegionCompletionProvider")] + internal class RegionCompletionProvider : ICssCompletionListProvider, ICssCompletionCommitListener + { + private RegionCompletionListEntry _entry = new RegionCompletionListEntry(); + + public CssCompletionContextType ContextType + { + get { return (CssCompletionContextType)601; } //ItemName + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + var line = context.Snapshot.GetLineFromPosition(context.ContextItem.Start); + string text = line.GetText().Trim(); + + if (text.Length == context.ContextItem.Length) + { + yield return _entry; + } + } + + public void OnCommitted(ICssCompletionListEntry entry, ITrackingSpan contextSpan, SnapshotPoint caret, ITextView textView) + { + if (entry.DisplayText == "Add region...") + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => System.Windows.Forms.SendKeys.Send("{TAB}")), DispatcherPriority.Normal); + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/CompletionProviders/TagCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/TagCompletionProvider.cs new file mode 100644 index 000000000..c0fa109e0 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/TagCompletionProvider.cs @@ -0,0 +1,154 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio.Utilities; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("TagCompletionProvider")] + internal class TagCompletionProvider : ICssCompletionListProvider + { + private static IEnumerable _entryCache = GetListEntriesCache(); + + public CssCompletionContextType ContextType + { + get { return (CssCompletionContextType)601; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + return _entryCache; + } + + private static IEnumerable GetListEntriesCache() + { + List entries = new List(); + + entries.Add(new CompletionListEntry("a")); + entries.Add(new CompletionListEntry("abbr")); + entries.Add(new CompletionListEntry("acronym")); + entries.Add(new CompletionListEntry("address")); + //entries.Add(new CompletionListEntry("applet")); + entries.Add(new CompletionListEntry("area")); + entries.Add(new CompletionListEntry("article")); + entries.Add(new CompletionListEntry("aside")); + entries.Add(new CompletionListEntry("audio")); + entries.Add(new CompletionListEntry("b")); + //entries.Add(new CompletionListEntry("base")); + //entries.Add(new CompletionListEntry("basefont")); + entries.Add(new CompletionListEntry("bdi")); + entries.Add(new CompletionListEntry("bdo")); + entries.Add(new CompletionListEntry("big")); + entries.Add(new CompletionListEntry("blockquote")); + entries.Add(new CompletionListEntry("body")); + //entries.Add(new CompletionListEntry("br")); + entries.Add(new CompletionListEntry("button")); + entries.Add(new CompletionListEntry("canvas")); + entries.Add(new CompletionListEntry("caption")); + entries.Add(new CompletionListEntry("center")); + entries.Add(new CompletionListEntry("cite")); + entries.Add(new CompletionListEntry("code")); + entries.Add(new CompletionListEntry("col")); + entries.Add(new CompletionListEntry("colgroup")); + //entries.Add(new CompletionListEntry("command")); + entries.Add(new CompletionListEntry("datalist")); + entries.Add(new CompletionListEntry("dd")); + entries.Add(new CompletionListEntry("del")); + entries.Add(new CompletionListEntry("details")); + entries.Add(new CompletionListEntry("dfn")); + //entries.Add(new CompletionListEntry("dir")); + entries.Add(new CompletionListEntry("div")); + entries.Add(new CompletionListEntry("dl")); + entries.Add(new CompletionListEntry("dt")); + entries.Add(new CompletionListEntry("em")); + entries.Add(new CompletionListEntry("embed")); + entries.Add(new CompletionListEntry("fieldset")); + entries.Add(new CompletionListEntry("figcaption")); + entries.Add(new CompletionListEntry("figure")); + //entries.Add(new CompletionListEntry("font")); + entries.Add(new CompletionListEntry("footer")); + entries.Add(new CompletionListEntry("form")); + //entries.Add(new CompletionListEntry("frame")); + //entries.Add(new CompletionListEntry("frameset")); + entries.Add(new CompletionListEntry("h1")); + entries.Add(new CompletionListEntry("h2")); + entries.Add(new CompletionListEntry("h3")); + entries.Add(new CompletionListEntry("h4")); + entries.Add(new CompletionListEntry("h5")); + entries.Add(new CompletionListEntry("h6")); + //entries.Add(new CompletionListEntry("head")); + entries.Add(new CompletionListEntry("header")); + entries.Add(new CompletionListEntry("hgroup")); + entries.Add(new CompletionListEntry("hr")); + entries.Add(new CompletionListEntry("html")); + entries.Add(new CompletionListEntry("i")); + entries.Add(new CompletionListEntry("iframe")); + entries.Add(new CompletionListEntry("img")); + entries.Add(new CompletionListEntry("input")); + entries.Add(new CompletionListEntry("ins")); + //entries.Add(new CompletionListEntry("keygen")); + entries.Add(new CompletionListEntry("kbd")); + entries.Add(new CompletionListEntry("label")); + entries.Add(new CompletionListEntry("legend")); + entries.Add(new CompletionListEntry("li")); + //entries.Add(new CompletionListEntry("link")); + entries.Add(new CompletionListEntry("map")); + entries.Add(new CompletionListEntry("mark")); + entries.Add(new CompletionListEntry("menu")); + //entries.Add(new CompletionListEntry("meta")); + entries.Add(new CompletionListEntry("meter")); + entries.Add(new CompletionListEntry("nav")); + //entries.Add(new CompletionListEntry("noframes")); + //entries.Add(new CompletionListEntry("noscript")); + entries.Add(new CompletionListEntry("object")); + entries.Add(new CompletionListEntry("ol")); + entries.Add(new CompletionListEntry("optgroup")); + entries.Add(new CompletionListEntry("option")); + entries.Add(new CompletionListEntry("output")); + entries.Add(new CompletionListEntry("p")); + entries.Add(new CompletionListEntry("param")); + entries.Add(new CompletionListEntry("pre")); + entries.Add(new CompletionListEntry("progress")); + entries.Add(new CompletionListEntry("q")); + entries.Add(new CompletionListEntry("rp")); + entries.Add(new CompletionListEntry("rt")); + entries.Add(new CompletionListEntry("ruby")); + entries.Add(new CompletionListEntry("s")); + entries.Add(new CompletionListEntry("samp")); + //entries.Add(new CompletionListEntry("script")); + entries.Add(new CompletionListEntry("section")); + entries.Add(new CompletionListEntry("select")); + entries.Add(new CompletionListEntry("small")); + //entries.Add(new CompletionListEntry("source")); + entries.Add(new CompletionListEntry("span")); + //entries.Add(new CompletionListEntry("strike")); + entries.Add(new CompletionListEntry("strong")); + entries.Add(new CompletionListEntry("style")); + entries.Add(new CompletionListEntry("sub")); + entries.Add(new CompletionListEntry("summary")); + entries.Add(new CompletionListEntry("sup")); + entries.Add(new CompletionListEntry("svg")); + entries.Add(new CompletionListEntry("table")); + entries.Add(new CompletionListEntry("tbody")); + entries.Add(new CompletionListEntry("td")); + entries.Add(new CompletionListEntry("textarea")); + entries.Add(new CompletionListEntry("tfoot")); + entries.Add(new CompletionListEntry("th")); + entries.Add(new CompletionListEntry("thead")); + entries.Add(new CompletionListEntry("time")); + //entries.Add(new CompletionListEntry("title")); + entries.Add(new CompletionListEntry("tr")); + entries.Add(new CompletionListEntry("track")); + entries.Add(new CompletionListEntry("tt")); + entries.Add(new CompletionListEntry("u")); + entries.Add(new CompletionListEntry("ul")); + entries.Add(new CompletionListEntry("var")); + entries.Add(new CompletionListEntry("video")); + //entries.Add(new CompletionListEntry("wbr")); + + return entries; + } + } +} diff --git a/EditorExtensions/Completion/CompletionProviders/UrlPickerCompletionProvider.cs b/EditorExtensions/Completion/CompletionProviders/UrlPickerCompletionProvider.cs new file mode 100644 index 000000000..a636d2512 --- /dev/null +++ b/EditorExtensions/Completion/CompletionProviders/UrlPickerCompletionProvider.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Windows.Threading; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionProvider))] + [Name("UrlPickerCompletionProvider")] + internal class UrlPickerCompletionProvider : ICssCompletionListProvider, ICssCompletionCommitListener + { + private static List _imageExtensions = new List() { "", ".png", ".jpg", "gif", ".svg", ".jpeg", ".bmp", ".tif", ".tiff" }; + public CssCompletionContextType ContextType + { + get { return (CssCompletionContextType)604; } + } + + public IEnumerable GetListEntries(CssCompletionContext context) + { + UrlItem urlItem = (UrlItem)context.ContextItem; + + string url = urlItem.UrlString != null ? urlItem.UrlString.Text : string.Empty; + string directory = GetDirectory(url); + + if (url.StartsWith("http") || url.Contains("//") || url.Contains(";base64,") || !Directory.Exists(directory)) + yield break; + + foreach (string item in Directory.GetFileSystemEntries(directory)) + { + string entry = item.Substring(item.LastIndexOf("\\") + 1); + + //if (_imageExtensions.Contains(Path.GetExtension(entry))) + yield return new UrlPickerCompletionListEntry(entry); + } + } + + private static string GetDirectory(string url) + { + if (url == "/" || url.LastIndexOf('/') == 0) + return GetRootFolder(); + + return GetRelativeFolder(url); + } + + private static string GetRelativeFolder(string url) + { + int end = Math.Max(0, url.LastIndexOf('/')); + return ProjectHelpers.ToAbsoluteFilePath(url.Substring(0, end)); + } + + private static string GetRootFolder() + { + string root = ProjectHelpers.GetRootFolder(); + if (File.Exists(root)) + return Path.GetDirectoryName(root); + + return root; + } + + public void OnCommitted(ICssCompletionListEntry entry, Microsoft.VisualStudio.Text.ITrackingSpan contextSpan, Microsoft.VisualStudio.Text.SnapshotPoint caret, Microsoft.VisualStudio.Text.Editor.ITextView textView) + { + if (Path.GetExtension(entry.DisplayText).Length == 0) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => CssCompletionController.FromView(textView).OnShowMemberList(filterList: true)), DispatcherPriority.Normal); + } + } + } +} diff --git a/EditorExtensions/Completion/ContextProviders/ClassContextProvider.cs b/EditorExtensions/Completion/ContextProviders/ClassContextProvider.cs new file mode 100644 index 000000000..17e5093e9 --- /dev/null +++ b/EditorExtensions/Completion/ContextProviders/ClassContextProvider.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionContextProvider))] + [Name("ClassCompletionContextProvider")] + internal class ClassCompletionContextProvider : ICssCompletionContextProvider + { + public ClassCompletionContextProvider() + { + } + + public IEnumerable ItemTypes + { + get + { + return new Type[] { typeof(ClassSelector), }; + } + } + + public CssCompletionContext GetCompletionContext(ParseItem item, int position) + { + return new CssCompletionContext((CssCompletionContextType)602, item.Start, item.Length, null); + } + } +} diff --git a/EditorExtensions/Completion/ContextProviders/IdContextProvider.cs b/EditorExtensions/Completion/ContextProviders/IdContextProvider.cs new file mode 100644 index 000000000..51424f6cd --- /dev/null +++ b/EditorExtensions/Completion/ContextProviders/IdContextProvider.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionContextProvider))] + [Name("IdCompletionContextProvider")] + internal class IdCompletionContextProvider : ICssCompletionContextProvider + { + public IdCompletionContextProvider() + { + } + + public IEnumerable ItemTypes + { + get + { + return new Type[] { typeof(IdSelector), }; + } + } + + public CssCompletionContext GetCompletionContext(ParseItem item, int position) + { + return new CssCompletionContext((CssCompletionContextType)603, item.Start, item.Length, null); + } + } +} diff --git a/EditorExtensions/Completion/ContextProviders/LessPseudoContextProvider.cs b/EditorExtensions/Completion/ContextProviders/LessPseudoContextProvider.cs new file mode 100644 index 000000000..ff818d58b --- /dev/null +++ b/EditorExtensions/Completion/ContextProviders/LessPseudoContextProvider.cs @@ -0,0 +1,43 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.Less.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionContextProvider))] + [Name("LessPseudoContextProvider")] + [Order(Before = "Default Pseudo")] + internal class LessPseudoContextProvider : ICssCompletionContextProvider + { + public IEnumerable ItemTypes + { + get + { + return new Type[] + { + typeof(PseudoClassFunctionSelector), + typeof(PseudoClassSelector), + typeof(PseudoElementFunctionSelector), + typeof(PseudoElementSelector) + }; + } + } + + public CssCompletionContext GetCompletionContext(ParseItem item, int position) + { + RuleSet rule = item.FindType(); + + if (rule != null && rule.Parent is LessRuleBlock) + { + return new CssCompletionContext(CssCompletionContextType.Invalid, item.Start, item.Length, item); + } + + return null; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/ContextProviders/TagContextProvider.cs b/EditorExtensions/Completion/ContextProviders/TagContextProvider.cs new file mode 100644 index 000000000..32a74710e --- /dev/null +++ b/EditorExtensions/Completion/ContextProviders/TagContextProvider.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionContextProvider))] + [Name("TagCompletionContextProvider")] + internal class TagCompletionContextProvider : ICssCompletionContextProvider + { + public TagCompletionContextProvider() + { + } + + public IEnumerable ItemTypes + { + get + { + return new Type[] { typeof(ItemName), }; + } + } + + public CssCompletionContext GetCompletionContext(ParseItem item, int position) + { + return new CssCompletionContext((CssCompletionContextType)601, item.Start, item.Length, null); + } + } +} diff --git a/EditorExtensions/Completion/ContextProviders/UrlPickerContextProvider.cs b/EditorExtensions/Completion/ContextProviders/UrlPickerContextProvider.cs new file mode 100644 index 000000000..66bf6672e --- /dev/null +++ b/EditorExtensions/Completion/ContextProviders/UrlPickerContextProvider.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssCompletionContextProvider))] + [Name("UrlPickerCompletionContextProvider")] + internal class UrlPickerCompletionContextProvider : ICssCompletionContextProvider + { + public UrlPickerCompletionContextProvider() + { + } + + public IEnumerable ItemTypes + { + get + { + return new Type[] { typeof(UrlItem), }; + } + } + + public CssCompletionContext GetCompletionContext(ParseItem item, int position) + { + UrlItem urlItem = (UrlItem)item; + int start = item.Start + 4; + int length = 0; + + if (urlItem.UrlString != null) + { + start = urlItem.UrlString.Start; + length = urlItem.UrlString.Length; + + int relative = position - start; + int lastSlash = urlItem.UrlString.Text.LastIndexOf('/'); + if (lastSlash < relative) + { + start = start + lastSlash + 1; + length = length - (lastSlash + 1); + } + } + + return new CssCompletionContext((CssCompletionContextType)604, start, length, null); + } + } +} diff --git a/EditorExtensions/Completion/CustomCompletionListEntry.cs b/EditorExtensions/Completion/CustomCompletionListEntry.cs new file mode 100644 index 000000000..34b3d3292 --- /dev/null +++ b/EditorExtensions/Completion/CustomCompletionListEntry.cs @@ -0,0 +1,72 @@ +using System; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + internal class CustomCompletionListEntry : ICssCompletionListEntry + { + private string _insertion; + + public CustomCompletionListEntry(string name, string insertion) + { + this.DisplayText = name; + _insertion = insertion; + } + + + public string Description { get; set; } + + public string DisplayText { get; set; } + + public string GetSyntax(Version version) + { + return string.Empty; + } + + public StandardGlyphGroup StandardGlyph + { + get { return StandardGlyphGroup.GlyphGroupEnumMember; } + } + + public string GetAttribute(string name) + { + return string.Empty; + } + + public string GetInsertionText(CssTextSource textSource, ITrackingSpan typingSpan) + { + return _insertion; + } + + public string GetVersionedAttribute(string name, Version version) + { + return GetAttribute(name); + } + + public bool AllowQuotedString + { + get { return false; } + } + + public bool IsBuilder + { + get { return false; } + } + + public int SortingPriority { get; set; } + + + public bool IsSupported(BrowserVersion browser) + { + return true; + } + + public bool IsSupported(Version cssVersion) + { + return true; + } + } +} diff --git a/EditorExtensions/Completion/Filter/GradientCompletionListFilter.cs b/EditorExtensions/Completion/Filter/GradientCompletionListFilter.cs new file mode 100644 index 000000000..168f7961d --- /dev/null +++ b/EditorExtensions/Completion/Filter/GradientCompletionListFilter.cs @@ -0,0 +1,97 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Reflection; + +namespace MadsKristensen.EditorExtensions.Completion +{ + [Export(typeof(ICssCompletionListFilter))] + [Name("Gradient Filter")] + internal class GradientCompletionListFilter : ICssCompletionListFilter + { + [Import] + private IGlyphService _glyphService = null; + + public void FilterCompletionList(IList completions, CssCompletionContext context) + { + if (context.ContextType != CssCompletionContextType.PropertyValue) + return; + + for (int i = 0; i < completions.Count; i++) + { + CssSchemaCompletionEntry entry = completions[i] as CssSchemaCompletionEntry; + + if (entry != null && entry.DisplayText.Contains("gradient(")) + { + var cce = CreateCompletionEntry(context, entry); + cce.FilterType = entry.FilterType; + cce.IsBuilder = entry.IsBuilder; + + completions[i] = cce; + } + } + } + + private CssSchemaCompletionEntry CreateCompletionEntry(CssCompletionContext context, CssSchemaCompletionEntry entry) + { + CustomCompletionListEntry interim = new CustomCompletionListEntry(entry.DisplayText, GetArguments(entry.DisplayText)); + interim.Description = entry.Description; + + object[] parameters = new object[] + { + interim, + entry.CompletionProvider, + CssTextSource.Document, + context.Snapshot.CreateTrackingSpan(context.SpanStart, context.SpanLength, SpanTrackingMode.EdgeExclusive), + _glyphService + }; + + BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; + return (CssSchemaCompletionEntry)Activator.CreateInstance(typeof(CssSchemaCompletionEntry), flags, null, parameters, null); + } + + private static string GetArguments(string functionName) + { + switch (functionName) + { + case "linear-gradient()": + case "-webkit-linear-gradient()": + case "-ms-linear-gradient()": + case "-moz-linear-gradient()": + case "-o-linear-gradient()": + return functionName.Replace("()", "(top, #1e5799 0%, #7db9e8 100%)"); + + case "-webkit-gradient()": + return functionName.Replace("()", "(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(100%,#7db9e8))"); + + case "radial-gradient()": + case "-webkit-radial-gradient()": + case "-ms-radial-gradient()": + case "-moz-radial-gradient()": + case "-o-radial-gradient()": + return functionName.Replace("()", "(50px 50px, circle closest-side, black, white)"); + + case "repeating-linear-gradient()": + case "-webkit-repeating-linear-gradient()": + case "-ms-repeating-linear-gradient()": + case "-moz-repeating-linear-gradient()": + case "-o-repeating-linear-gradient()": + return functionName.Replace("()", "(red, blue 20px, red 40px)"); + + case "repeating-radial-gradient()": + case "-webkit-repeating-radial-gradient()": + case "-ms-repeating-radial-gradient()": + case "-moz-repeating-radial-gradient()": + case "-o-repeating-radial-gradient()": + return functionName.Replace("()", "(red, blue 20px, red 40px)"); + } + + return functionName; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/Filter/HideInheritInitialCompletionListFilter.cs b/EditorExtensions/Completion/Filter/HideInheritInitialCompletionListFilter.cs new file mode 100644 index 000000000..a496624ec --- /dev/null +++ b/EditorExtensions/Completion/Filter/HideInheritInitialCompletionListFilter.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions.Completion +{ + [Export(typeof(ICssCompletionListFilter))] + [Name("Inherit/Initial Filter")] + internal class HideInheritInitialCompletionListFilter : ICssCompletionListFilter + { + public void FilterCompletionList(IList completions, CssCompletionContext context) + { + if (context.ContextType != CssCompletionContextType.PropertyValue || WESettings.GetBoolean(WESettings.Keys.ShowInitialInherit)) + return; + + foreach (CssCompletionEntry entry in completions) + { + if (entry.DisplayText == "initial" || entry.DisplayText == "inherit") + { + entry.FilterType = CompletionEntryFilterType.NeverVisible; + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/Filter/HideUnsupportedCompletionListFilter.cs b/EditorExtensions/Completion/Filter/HideUnsupportedCompletionListFilter.cs new file mode 100644 index 000000000..cecee7a6e --- /dev/null +++ b/EditorExtensions/Completion/Filter/HideUnsupportedCompletionListFilter.cs @@ -0,0 +1,41 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; +using System; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssSchemaFilterProvider))] + [Name("HideUnsupportedSchemaFilterProvider")] + internal class HideUnsupportedSchemaFilterProvider : ICssSchemaFilterProvider + { + public ICssSchemaFilter CreateFilter(ICssSchemaManager schemaManager, ITextBuffer textBuffer) + { + return textBuffer.Properties.GetOrCreateSingletonProperty(() => new HideUnsupportedSchemaFilter()); + } + } + + internal class HideUnsupportedSchemaFilter : ICssSchemaFilter + { + public bool IsSupported(Version cssVersion, ICssCompletionListEntry entry) + { + if (WESettings.GetBoolean(WESettings.Keys.ShowUnsupported)) + return entry.IsSupported(cssVersion); + + return entry.GetAttribute("browsers") != "none" || entry.DisplayText.Contains("gradient"); + } + + public string Name + { + get { return WESettings.GetBoolean(WESettings.Keys.ShowUnsupported) ? string.Empty : "WE"; } + } + + public bool Equals(ICssSchemaFilter other) + { + return other.Name.Equals(Name); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/Filter/WebkitScrollbarCompletionListFilter.cs b/EditorExtensions/Completion/Filter/WebkitScrollbarCompletionListFilter.cs new file mode 100644 index 000000000..695bb1f3f --- /dev/null +++ b/EditorExtensions/Completion/Filter/WebkitScrollbarCompletionListFilter.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions.Completion +{ + [Export(typeof(ICssCompletionListFilter))] + [Name("WebkitScrollbarCompletionListFilter")] + internal class WebkitScrollbarCompletionListFilter : ICssCompletionListFilter + { + private static readonly StringCollection _cache = new StringCollection() + { + ":horizontal", + ":vertical", + ":decrement", + ":increment", + ":start", + ":end", + ":double-button", + ":single-button", + ":no-button", + ":corner-present", + ":window-inactive", + }; + + public void FilterCompletionList(IList completions, CssCompletionContext context) + { + if (context.ContextType != CssCompletionContextType.PseudoClassOrElement) + return; + + ParseItem prev = context.ContextItem.PreviousSibling; + bool hasScrollbar = false; + + if (prev != null) + { + hasScrollbar = prev.Text.Contains(":-webkit-resizer") || prev.Text.Contains(":-webkit-scrollbar"); + } + + foreach (CssCompletionEntry entry in completions) + { + if (hasScrollbar) + { + entry.FilterType = _cache.Contains(entry.DisplayText) ? entry.FilterType : CompletionEntryFilterType.NeverVisible; + } + else + { + entry.FilterType = !_cache.Contains(entry.DisplayText) ? entry.FilterType : CompletionEntryFilterType.NeverVisible; + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Completion/FontFamilyCompletionListEntry.cs b/EditorExtensions/Completion/FontFamilyCompletionListEntry.cs new file mode 100644 index 000000000..4b98ee913 --- /dev/null +++ b/EditorExtensions/Completion/FontFamilyCompletionListEntry.cs @@ -0,0 +1,112 @@ +using System; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + /// + /// This represents a font family in the completion list + /// + internal class FontFamilyCompletionListEntry : ICssCompletionListEntry + { + private string _name; + + public FontFamilyCompletionListEntry(string name) + { + _name = name ?? string.Empty; + } + + public string DisplayText + { + get { return _name; } + } + + public string Description + { + get { return string.Empty; } + } + + public string GetSyntax(Version version) + { + return string.Empty; + } + + public string GetAttribute(string name) + { + return string.Empty; + } + + public string GetVersionedAttribute(string name, System.Version version) + { + return string.Empty; + } + + public string GetInsertionText(CssTextSource textSource, ITrackingSpan typingSpan) + { + string text = DisplayText; + bool needsQuote = text.IndexOf(' ') != -1; + if (text == "Pick from file...") + { + return string.Empty; + } + + if (needsQuote) + { + // Prefer to use single quotes, but if the inline style uses single quotes, then use double quotes. + char quote = (textSource == CssTextSource.InlineStyleSingleQuote) ? '"' : '\''; + + if (typingSpan != null) + { + // If the user already typed a quote, then use it + + string typingText = typingSpan.GetText(typingSpan.TextBuffer.CurrentSnapshot); + + if (!string.IsNullOrEmpty(typingText) && (typingText[0] == '"' || typingText[0] == '\'')) + { + quote = typingText[0]; + } + } + + if (text != null && text.IndexOf(quote) == -1) + { + text = quote.ToString() + text + quote.ToString(); + } + } + + return text; + } + + public StandardGlyphGroup StandardGlyph + { + get { return StandardGlyphGroup.GlyphGroupEnumMember; } + } + + public bool AllowQuotedString + { + get { return true; } + } + + public bool IsBuilder + { + get { return DisplayText == "Pick from file..."; } + } + + public int SortingPriority + { + get { return 0; } + } + + + public bool IsSupported(BrowserVersion browser) + { + return true; + } + + public bool IsSupported(Version cssVersion) + { + return true; + } + } +} diff --git a/EditorExtensions/Completion/RegionCompletionListEntry.cs b/EditorExtensions/Completion/RegionCompletionListEntry.cs new file mode 100644 index 000000000..8c5c8fd08 --- /dev/null +++ b/EditorExtensions/Completion/RegionCompletionListEntry.cs @@ -0,0 +1,69 @@ +using System; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + internal class RegionCompletionListEntry : ICssCompletionListEntry + { + public string Description + { + get { return string.Empty; } + } + + public string DisplayText + { + get { return "Add region..."; } + } + + public string GetSyntax(Version version) + { + return string.Empty; + } + + public StandardGlyphGroup StandardGlyph + { + get { return StandardGlyphGroup.GlyphCSharpExpansion; } + } + + public string GetAttribute(string name) + { + return string.Empty; + } + + public string GetInsertionText(CssTextSource textSource, ITrackingSpan typingSpan) + { + return "region";//"/*#region MyRegion */\n\n\n\n/*#endregion*/"; + } + + public string GetVersionedAttribute(string name, Version version) + { + return GetAttribute(name); + } + + public bool AllowQuotedString + { + get { return false; } + } + + public bool IsBuilder + { + get { return true; } + } + + public int SortingPriority { get; set; } + + + public bool IsSupported(BrowserVersion browser) + { + return true; + } + + public bool IsSupported(Version cssVersion) + { + return true; + } + } +} diff --git a/EditorExtensions/Completion/UrlPickerCompletionListEntry.cs b/EditorExtensions/Completion/UrlPickerCompletionListEntry.cs new file mode 100644 index 000000000..cf9d8cee5 --- /dev/null +++ b/EditorExtensions/Completion/UrlPickerCompletionListEntry.cs @@ -0,0 +1,89 @@ +using System; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + internal class UrlPickerCompletionListEntry : ICssCompletionListEntry + { + private string _name; + + public UrlPickerCompletionListEntry(string name) + { + _name = name; + } + + public bool AllowQuotedString + { + get { return false; } + } + + public string Description + { + get { return string.Empty; } + } + + public string DisplayText + { + get { return _name; } + } + + public string GetSyntax(Version version) + { + return string.Empty; + } + + public int SortingPriority + { + get { return IsFolder ? 1 : 0; } + } + + public bool IsBuilder + { + get { return false; } + } + + public StandardGlyphGroup StandardGlyph + { + get { return IsFolder ? StandardGlyphGroup.GlyphClosedFolder : StandardGlyphGroup.GlyphBscFile; } + } + + public string GetAttribute(string name) + { + return string.Empty; + } + + public string GetInsertionText(CssTextSource textSource, ITrackingSpan typingSpan) + { + if (IsFolder) + { + return DisplayText + "/"; + } + + return DisplayText; + } + + public string GetVersionedAttribute(string name, Version version) + { + return GetAttribute(name); + } + + private bool IsFolder + { + get { return !DisplayText.Contains("."); } + } + + + public bool IsSupported(BrowserVersion browser) + { + return true; + } + + public bool IsSupported(Version cssVersion) + { + return true; + } + } +} diff --git a/EditorExtensions/DropTargets/BundleDrop.cs b/EditorExtensions/DropTargets/BundleDrop.cs new file mode 100644 index 000000000..61dc38798 --- /dev/null +++ b/EditorExtensions/DropTargets/BundleDrop.cs @@ -0,0 +1,83 @@ +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Editor.DragDrop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IDropHandlerProvider))] + [DropFormat("CF_VSSTGPROJECTITEMS")] + [Name("BundleDropDropHandler")] + [ContentType("XML")] + [Order(Before = "DefaultFileDropHandler")] + internal class BundleDropHandlerProvider : IDropHandlerProvider + { + public IDropHandler GetAssociatedDropHandler(IWpfTextView view) + { + return view.Properties.GetOrCreateSingletonProperty(() => new BundleDropHandler(view)); + } + } + + internal class BundleDropHandler : IDropHandler + { + private IWpfTextView _view; + private readonly List _allowedExtensions = new List { ".css", ".less", ".js", ".coffee", ".ts" }; + private string _draggedFilename; + private string _format = Environment.NewLine + "\t/{0}"; + + public BundleDropHandler(IWpfTextView view) + { + this._view = view; + } + + public DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo) + { + string reference = FileHelpers.RelativePath(ProjectHelpers.GetRootFolder(), _draggedFilename); + + if (reference.StartsWith("http://localhost:")) + { + int index = reference.IndexOf('/', 20); + if (index > -1) + reference = reference.Substring(index + 1).ToLowerInvariant(); + } + + _view.TextBuffer.Insert(dragDropInfo.VirtualBufferPosition.Position.Position, string.Format(_format, reference)); + + return DragDropPointerEffects.Copy; + } + + public void HandleDragCanceled() + { + + } + + public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public bool IsDropEnabled(DragDropInfo dragDropInfo) + { + _draggedFilename = FontDropHandler.GetImageFilename(dragDropInfo); + + if (!string.IsNullOrEmpty(_draggedFilename)) + { + string fileExtension = Path.GetExtension(_draggedFilename).ToLowerInvariant(); + if (this._allowedExtensions.Contains(fileExtension)) + { + return true; + } + } + + return false; + } + } +} diff --git a/EditorExtensions/DropTargets/FontDrop.cs b/EditorExtensions/DropTargets/FontDrop.cs new file mode 100644 index 000000000..9c8aeb693 --- /dev/null +++ b/EditorExtensions/DropTargets/FontDrop.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Windows.Forms; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Editor.DragDrop; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IDropHandlerProvider))] + [DropFormat("FileDrop")] + [DropFormat("CF_VSSTGPROJECTITEMS")] + [Name("FontDropHandler")] + [ContentType("CSS")] + [ContentType("LESS")] + [Order(Before = "DefaultFileDropHandler")] + internal class FontDropHandlerProvider : IDropHandlerProvider + { + public IDropHandler GetAssociatedDropHandler(IWpfTextView view) + { + return view.Properties.GetOrCreateSingletonProperty(() => new FontDropHandler(view)); + } + } + + internal class FontDropHandler : IDropHandler + { + IWpfTextView view; + private readonly Dictionary formats = new Dictionary() + { + {".ttf", " format('truetype')"}, + {".woff", ""}, + {".eot", ""}, + {".otf", " format('opentype')"} + }; + private string draggedFilename; + private string fontName = string.Empty; + string fontFace = "@font-face {{\n\tfont-family: {0};\n\tsrc: {1};\n}}"; + string fontUrls = "url('{0}'){1}"; + //ITextDocument document; + + public FontDropHandler(IWpfTextView view) + { + this.view = view; + //view.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document); + } + + public DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo) + { + if (File.Exists(draggedFilename)) + { + //var files = GetRelativeFiles(draggedFilename); + //string[] sources = new string[files.Count()]; + + //for (int i = 0; i < files.Count(); i++) + //{ + // string file = files.ElementAt(i); + // string extension = Path.GetExtension(file).ToLowerInvariant(); + // string reference = RelativePath(document.FilePath, file); + + // if (reference.StartsWith("http://localhost:")) + // { + // int index = reference.IndexOf('/', 24); + // if (index > -1) + // reference = reference.Substring(index + 1).ToLowerInvariant(); + // } + + // sources[i] = string.Format(fontUrls, reference, formats[extension]); + //} + + //string sourceUrls = string.Join(", ", sources); + string fontFamily; + view.TextBuffer.Insert(dragDropInfo.VirtualBufferPosition.Position.Position, GetCodeFromFile(draggedFilename, out fontFamily)); + + return DragDropPointerEffects.Copy; + } + else if (draggedFilename.StartsWith("http://localhost:")) + { + //int index = draggedFilename.IndexOf('/', 24); + //if (index > -1) + // draggedFilename = draggedFilename.Substring(index).ToLowerInvariant(); + + //string extension = Path.GetExtension(draggedFilename).ToLowerInvariant(); + //string sourceUrl = string.Format(fontUrls, draggedFilename, formats[extension]); + + view.TextBuffer.Insert(dragDropInfo.VirtualBufferPosition.Position.Position, GetCodeFromLocalhost(draggedFilename)); + + return DragDropPointerEffects.Copy; + } + else + { + return DragDropPointerEffects.None; + } + } + + public string GetCodeFromFile(string fileName, out string fontFamily) + { + var files = GetRelativeFiles(fileName); + string[] sources = new string[files.Count()]; + + for (int i = 0; i < files.Count(); i++) + { + string file = files.ElementAt(i); + string extension = Path.GetExtension(file).ToLowerInvariant(); + string reference = FileHelpers.RelativePath(EditorExtensionsPackage.DTE.ActiveDocument.FullName, file); + + if (reference.StartsWith("http://localhost:")) + { + int index = reference.IndexOf('/', 24); + if (index > -1) + reference = reference.Substring(index + 1).ToLowerInvariant(); + } + + sources[i] = string.Format(fontUrls, reference, formats[extension]); + } + + string sourceUrls = string.Join(", ", sources); + fontFamily = fontName; + return string.Format(fontFace, fontName, sourceUrls); + } + + private string GetCodeFromLocalhost(string fileName) + { + int index = draggedFilename.IndexOf('/', 24); + if (index > -1) + draggedFilename = draggedFilename.Substring(index).ToLowerInvariant(); + + string extension = Path.GetExtension(draggedFilename).ToLowerInvariant(); + string sourceUrl = string.Format(fontUrls, draggedFilename, formats[extension]); + + return string.Format(fontFace, "MyFontName", sourceUrl); + } + + private IEnumerable GetRelativeFiles(string fileName) + { + var fi = new FileInfo(fileName); + fontName = fi.Name.Replace(fi.Extension, string.Empty); + foreach (var file in fi.Directory.GetFiles(fontName + ".*")) + { + string extension = file.Extension.ToLowerInvariant(); + if (formats.ContainsKey(extension)) + yield return file.FullName; + } + } + + public void HandleDragCanceled() + { + } + + public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public bool IsDropEnabled(DragDropInfo dragDropInfo) + { + //if (!Path.GetExtension(document.FilePath).Equals(".css", StringComparison.OrdinalIgnoreCase)) + // return false; + + draggedFilename = GetImageFilename(dragDropInfo); + + if (!string.IsNullOrEmpty(draggedFilename)) + { + string fileExtension = Path.GetExtension(draggedFilename).ToLowerInvariant(); + if (this.formats.ContainsKey(fileExtension)) + { + return true; + } + } + + return false; + } + + public static string GetImageFilename(DragDropInfo info) + { + DataObject data = new DataObject(info.Data); + + if (info.Data.GetDataPresent("FileDrop")) + { + // The drag and drop operation came from the file system + StringCollection files = data.GetFileDropList(); + + if (files != null && files.Count == 1) + { + return files[0]; + } + } + else if (info.Data.GetDataPresent("CF_VSSTGPROJECTITEMS")) + { + // The drag and drop operation came from the VS solution explorer + return data.GetText(); + } + + return null; + } + + //public static string RelativePath(string absPath, string relTo) + //{ + // string[] absDirs = absPath.Split('\\'); + // string[] relDirs = relTo.Split('\\'); + + // // Get the shortest of the two paths + // int len = absDirs.Length < relDirs.Length ? absDirs.Length : + // relDirs.Length; + + // // Use to determine where in the loop we exited + // int lastCommonRoot = -1; + // int index; + + // // Find common root + // for (index = 0; index < len; index++) + // { + // if (absDirs[index] == relDirs[index]) lastCommonRoot = index; + // else break; + // } + + // // If we didn't find a common prefix then throw + // if (lastCommonRoot == -1) + // { + // return relTo; + // } + + // // Build up the relative path + // StringBuilder relativePath = new StringBuilder(); + + // // Add on the .. + // for (index = lastCommonRoot + 2; index < absDirs.Length; index++) + // { + // if (absDirs[index].Length > 0) relativePath.Append("..\\"); + // } + + // // Add on the folders + // for (index = lastCommonRoot + 1; index < relDirs.Length - 1; index++) + // { + // relativePath.Append(relDirs[index] + "\\"); + // } + // relativePath.Append(relDirs[relDirs.Length - 1]); + + // return relativePath.ToString().Replace("\\", "/"); + //} + } +} diff --git a/EditorExtensions/DropTargets/ImageDrop.cs b/EditorExtensions/DropTargets/ImageDrop.cs new file mode 100644 index 000000000..3b71a6d21 --- /dev/null +++ b/EditorExtensions/DropTargets/ImageDrop.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Editor.DragDrop; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IDropHandlerProvider))] + [DropFormat("FileDrop")] + [DropFormat("CF_VSSTGPROJECTITEMS")] + [Name("ImageDropHandler")] + [ContentType("CSS")] + [ContentType("LESS")] + [Order(Before = "DefaultFileDropHandler")] + internal class ImageDropHandlerProvider : IDropHandlerProvider + { + public IDropHandler GetAssociatedDropHandler(IWpfTextView view) + { + return view.Properties.GetOrCreateSingletonProperty(() => new ImageDropHandler(view)); + } + } + + internal class ImageDropHandler : IDropHandler + { + IWpfTextView _view; + private readonly List _imageExtensions = new List { ".jpg", ".jpeg", ".bmp", ".png", ".gif", ".svg", ".tif", ".tiff" }; + private string _imageFilename; + string _background = "background-image: url({0});"; + + public ImageDropHandler(IWpfTextView view) + { + this._view = view; + } + + public DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo) + { + string reference = FileHelpers.RelativePath(EditorExtensionsPackage.DTE.ActiveDocument.FullName, _imageFilename); + + if (reference.Contains("://")) + { + int index = reference.IndexOf('/', 12); + if (index > -1) + reference = reference.Substring(index).ToLowerInvariant(); + } + + _view.TextBuffer.Insert(dragDropInfo.VirtualBufferPosition.Position.Position, string.Format(_background, reference)); + + return DragDropPointerEffects.Copy; + } + + public void HandleDragCanceled() + { + + } + + public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public bool IsDropEnabled(DragDropInfo dragDropInfo) + { + _imageFilename = FontDropHandler.GetImageFilename(dragDropInfo); + + if (!string.IsNullOrEmpty(_imageFilename)) + { + string fileExtension = Path.GetExtension(_imageFilename).ToLowerInvariant(); + if (this._imageExtensions.Contains(fileExtension)) + { + return true; + } + } + + return false; + } + } +} diff --git a/EditorExtensions/DropTargets/StylesheetDrop.cs b/EditorExtensions/DropTargets/StylesheetDrop.cs new file mode 100644 index 000000000..448244ead --- /dev/null +++ b/EditorExtensions/DropTargets/StylesheetDrop.cs @@ -0,0 +1,84 @@ +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Editor.DragDrop; +using Microsoft.VisualStudio.Utilities; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IDropHandlerProvider))] + [DropFormat("StylesheetDrop")] + [DropFormat("CF_VSSTGPROJECTITEMS")] + [Name("StylesheetDropDropHandler")] + [ContentType("CSS")] + [ContentType("LESS")] + [Order(Before = "DefaultFileDropHandler")] + internal class StylesheetDropHandlerProvider : IDropHandlerProvider + { + public IDropHandler GetAssociatedDropHandler(IWpfTextView view) + { + return view.Properties.GetOrCreateSingletonProperty(() => new StylesheetDropHandler(view)); + } + } + + internal class StylesheetDropHandler : IDropHandler + { + IWpfTextView _view; + private readonly List _imageExtensions = new List { ".css", ".less", ".sass", ".scss" }; + private string _imageFilename; + string _background = "@import url('{0}');"; + + public StylesheetDropHandler(IWpfTextView view) + { + this._view = view; + } + + public DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo) + { + string reference = FileHelpers.RelativePath(EditorExtensionsPackage.DTE.ActiveDocument.FullName, _imageFilename); + + if (reference.StartsWith("http://localhost:")) + { + int index = reference.IndexOf('/', 24); + if (index > -1) + reference = reference.Substring(index).ToLowerInvariant(); + } + + _view.TextBuffer.Insert(dragDropInfo.VirtualBufferPosition.Position.Position, string.Format(_background, reference)); + + return DragDropPointerEffects.Copy; + } + + public void HandleDragCanceled() + { + + } + + public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public bool IsDropEnabled(DragDropInfo dragDropInfo) + { + _imageFilename = FontDropHandler.GetImageFilename(dragDropInfo); + + if (!string.IsNullOrEmpty(_imageFilename)) + { + string fileExtension = Path.GetExtension(_imageFilename).ToLowerInvariant(); + if (this._imageExtensions.Contains(fileExtension)) + { + return true; + } + } + + return false; + } + } +} diff --git a/EditorExtensions/DropTargets/TypeScriptDrop.cs b/EditorExtensions/DropTargets/TypeScriptDrop.cs new file mode 100644 index 000000000..dd0b7af1b --- /dev/null +++ b/EditorExtensions/DropTargets/TypeScriptDrop.cs @@ -0,0 +1,86 @@ +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Editor.DragDrop; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IDropHandlerProvider))] + [DropFormat("CF_VSSTGPROJECTITEMS")] + [Name("TypeScriptDropHandler")] + [ContentType("TypeScript")] + [Order(Before = "DefaultFileDropHandler")] + internal class TypeScriptDropHandlerProvider : IDropHandlerProvider + { + public IDropHandler GetAssociatedDropHandler(IWpfTextView view) + { + return view.Properties.GetOrCreateSingletonProperty(() => new TypeScriptDropHandler(view)); + } + } + + internal class TypeScriptDropHandler : IDropHandler + { + IWpfTextView _view; + private readonly List _imageExtensions = new List { ".ts", ".js" }; + private string _imageFilename; + string _background = "/// "; + + public TypeScriptDropHandler(IWpfTextView view) + { + this._view = view; + } + + public DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo) + { + string reference = FileHelpers.RelativePath(EditorExtensionsPackage.DTE.ActiveDocument.FullName, _imageFilename); + + if (reference.StartsWith("http://localhost:")) + { + int index = reference.IndexOf('/', 24); + if (index > -1) + reference = reference.Substring(index).ToLowerInvariant(); + } + + reference = reference.Trim('/'); + string comment = string.Format(_background, reference); + + _view.TextBuffer.Insert(0, comment + Environment.NewLine); + + return DragDropPointerEffects.Copy; + } + + public void HandleDragCanceled() + { + + } + + public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo) + { + return DragDropPointerEffects.All; + } + + public bool IsDropEnabled(DragDropInfo dragDropInfo) + { + _imageFilename = FontDropHandler.GetImageFilename(dragDropInfo); + + if (!string.IsNullOrEmpty(_imageFilename)) + { + string fileExtension = Path.GetExtension(_imageFilename).ToLowerInvariant(); + if (this._imageExtensions.Contains(fileExtension)) + { + return true; + } + } + + return false; + } + } +} diff --git a/EditorExtensions/EditorExtensions.vsct b/EditorExtensions/EditorExtensions.vsct new file mode 100644 index 000000000..4236bb5b9 --- /dev/null +++ b/EditorExtensions/EditorExtensions.vsct @@ -0,0 +1,753 @@ + + + + + + + + + + + + Encode Selection + Encode Selection + + + + + + Transform Selection + Transform Selection + + + + + DynamicVisibility + + Web Essentials + Web Essentials + + + + + + Web Essentials + Web Essentials + + + + + + Web Essentials + Web Essentials + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EditorExtensions/EditorExtensionsPackage.cs b/EditorExtensions/EditorExtensionsPackage.cs new file mode 100644 index 000000000..d620163c0 --- /dev/null +++ b/EditorExtensions/EditorExtensionsPackage.cs @@ -0,0 +1,227 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System; +using System.ComponentModel.Design; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + // The key for registering option pages in Text Editors -> CSS + //HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\Languages\Language Services\CSS\EditorToolsOptions\Format + + + [PackageRegistration(UseManagedResourcesOnly = true)] + [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] + [Guid(GuidList.guidEditorExtensionsPkgString)] + [ProvideMenuResource("Menus.ctmenu", 1)] + [ProvideAutoLoad(UIContextGuids80.SolutionExists)] + [ProvideOptionPage(typeof(GeneralOptions), "Web Essentials", "General", 101, 101, true, new[] { "ZenCoding", "Mustache", "Handlebars", "Comments", "Bundling", "Bundle" })] + [ProvideOptionPage(typeof(CssOptions), "Web Essentials", "CSS", 101, 102, true, new[] { "Minify", "Minification", "W3C", "CSS3" })] + [ProvideOptionPage(typeof(JsHintOptions), "Web Essentials", "JSHint", 101, 103, true, new[] { "JSLint", "Lint" })] + //[ProvideOptionPage(typeof(TypeScriptOptions), "Web Essentials", "TypeScript", 101, 104, true, new[] { "Minify", "Minification" })] + [ProvideOptionPage(typeof(LessOptions), "Web Essentials", "LESS", 101, 105, true)] + [ProvideOptionPage(typeof(CoffeeScriptOptions), "Web Essentials", "CoffeeScript", 101, 106, true, new[] { "Iced", "JavaScript", "JS", "JScript" })] + [ProvideOptionPage(typeof(JavaScriptOptions), "Web Essentials", "JavaScript", 101, 107, true, new[] { "JScript", "JS", "Minify", "Minification", "EcmaScript" })] + //[ProvideOptionPage(typeof(ScssOptions), "Web Essentials", "SCSS", 101, 108, true)] + [ProvideSearchProvider(typeof(Microsoft.MSDNSearch.VSSearchProvider), "VS Gallery Search")] + public sealed class EditorExtensionsPackage : ExtensionPointPackage + { + private static DTE2 _dte; + private static IVsRegisterPriorityCommandTarget _pct; + + public EditorExtensionsPackage() + { + } + + internal static DTE2 DTE + { + get + { + if (_dte == null) + { + _dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE2; + Debug.Assert(_dte != null); + } + + return _dte; + } + } + + internal static IVsRegisterPriorityCommandTarget PriorityCommandTarget + { + get + { + if (_pct == null) + { + _pct = ServiceProvider.GlobalProvider.GetService(typeof(SVsRegisterPriorityCommandTarget)) as IVsRegisterPriorityCommandTarget; + } + + return _pct; + } + } + + public static EditorExtensionsPackage Instance { get; private set; } + + protected override void Initialize() + { + base.Initialize(); + Instance = this; + JsDocComments.Register(); + + OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; + if (null != mcs) + { + HandleMenuVisibility(mcs); + + //EncodingMenu encoding = new EncodingMenu(DTE, mcs); + //encoding.SetupCommands(); + + TransformMenu transform = new TransformMenu(DTE, mcs); + transform.SetupCommands(); + + //CssSortPropertiesMenu cssTasks = new CssSortPropertiesMenu(DTE, mcs); + //cssTasks.SetupCommands(); + + //CssRemoveDuplicates cssRemoveDuplicates = new CssRemoveDuplicates(DTE, mcs); + //cssRemoveDuplicates.SetupCommands(); + + //CssAddMissingVendor cssAddMissingVendor = new CssAddMissingVendor(DTE, mcs); + //cssAddMissingVendor.SetupCommands(); + + //CssAddMissingStandard cssAddMissingStandard = new CssAddMissingStandard(DTE, mcs); + //cssAddMissingStandard.SetupCommands(); + + DiffMenu diffMenu = new DiffMenu(DTE, mcs); + diffMenu.SetupCommands(); + + MinifyFileMenu minifyMenu = new MinifyFileMenu(DTE, mcs); + minifyMenu.SetupCommands(); + + BundleFilesMenu bundleMenu = new BundleFilesMenu(DTE, mcs); + bundleMenu.SetupCommands(); + + JsHintMenu jsHintMenu = new JsHintMenu(DTE, mcs); + jsHintMenu.SetupCommands(); + + ProjectSettingsMenu projectSettingsMenu = new ProjectSettingsMenu(DTE, mcs); + projectSettingsMenu.SetupCommands(); + + SolutionColorsMenu solutionColorsMenu = new SolutionColorsMenu(DTE, mcs); + solutionColorsMenu.SetupCommands(); + + BuildMenu buildMenu = new BuildMenu(DTE, mcs); + buildMenu.SetupCommands(); + + MarkdownStylesheetMenu markdownMenu = new MarkdownStylesheetMenu(DTE, mcs); + markdownMenu.SetupCommands(); + + //CssExtractToFileMenu extractToFileMenu = new CssExtractToFileMenu(DTE, mcs); + //extractToFileMenu.SetupCommands(); + } + + // Hook up event handlers + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => + { + DTE.Events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone; + DTE.Events.SolutionEvents.Opened += delegate { Settings.UpdateCache(); Settings.UpdateStatusBar("applied"); }; + DTE.Events.SolutionEvents.AfterClosing += delegate { DTE.StatusBar.Clear(); }; + + }), DispatcherPriority.ApplicationIdle, null); + } + + private void BuildEvents_OnBuildDone(vsBuildScope Scope, vsBuildAction Action) + { + if (Action != vsBuildAction.vsBuildActionClean) + { + //if (WESettings.GetBoolean(WESettings.Keys.CompileTypeScriptOnBuild)) + // _dte.Commands.Raise(GuidList.guidBuildCmdSetString, (int)PkgCmdIDList.cmdBuildTypeScript, null, null); + //new TypeScriptMargin().CompileProjectFiles(null); + + if (WESettings.GetBoolean(WESettings.Keys.LessCompileOnBuild)) + _dte.Commands.Raise(GuidList.guidBuildCmdSetString, (int)PkgCmdIDList.cmdBuildLess, null, null); + //LessProjectCompiler.CompileProject(); + + if (WESettings.GetBoolean(WESettings.Keys.CoffeeScriptCompileOnBuild)) + _dte.Commands.Raise(GuidList.guidBuildCmdSetString, (int)PkgCmdIDList.cmdBuildCoffeeScript, null, null); + + //BundleFilesMenu.UpdateBundles(null, true); + _dte.Commands.Raise(GuidList.guidBuildCmdSetString, (int)PkgCmdIDList.cmdBuildBundles, null, null); + + if (WESettings.GetBoolean(WESettings.Keys.RunJsHintOnBuild)) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => JsHintProjectRunner.RunOnAllFilesInProject()), DispatcherPriority.ApplicationIdle, null); + } + } + else if (Action == vsBuildAction.vsBuildActionClean) + { + System.Threading.Tasks.Task.Run(() => JsHintRunner.Reset()); + } + } + + public static void ExecuteCommand(string commandName) + { + var command = EditorExtensionsPackage.DTE.Commands.Item(commandName); + if (command.IsAvailable) + { + EditorExtensionsPackage.DTE.ExecuteCommand(commandName); + } + } + + private void HandleMenuVisibility(OleMenuCommandService mcs) + { + CommandID commandId = new CommandID(GuidList.guidCssIntellisenseCmdSet, (int)PkgCmdIDList.CssIntellisenseSubMenu); + OleMenuCommand menuCommand = new OleMenuCommand((s, e) => { }, commandId); + menuCommand.BeforeQueryStatus += menuCommand_BeforeQueryStatus; + mcs.AddCommand(menuCommand); + } + + private readonly string[] _supported = new[] { "CSS", "LESS", "SCSS", "JAVASCRIPT", "PROJECTION", "TYPESCRIPT", "MARKDOWN" }; + + void menuCommand_BeforeQueryStatus(object sender, EventArgs e) + { + OleMenuCommand menu = (OleMenuCommand)sender; + var buffer = ProjectHelpers.GetCurentTextBuffer(); + + menu.Visible = buffer != null && _supported.Contains(buffer.ContentType.DisplayName.ToUpperInvariant()); + } + + public static T GetGlobalService(Type type = null) where T : class + { + return Microsoft.VisualStudio.Shell.Package.GetGlobalService(type ?? typeof(T)) as T; + } + + public static IComponentModel ComponentModel + { + get { return GetGlobalService(typeof(SComponentModel)); } + } + + //internal static IVsHierarchy GetIVsHierarchy(Project project) + //{ + // IVsSolution solution = (IVsSolution)ServiceProvider.GlobalProvider.GetService(typeof(IVsSolution)); + // if (solution == null) + // { + // return null; + // } + + // IVsHierarchy hier; + + // Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(solution.GetProjectOfUniqueName(project.UniqueName, out hier)); + + // if (hier == null) + // { + // return null; + // } + // else + // { + // return hier; + // } + //} + } +} diff --git a/EditorExtensions/ErrorTags/Filters/Backslash9CssErrorFilter.cs b/EditorExtensions/ErrorTags/Filters/Backslash9CssErrorFilter.cs new file mode 100644 index 000000000..0940a2a10 --- /dev/null +++ b/EditorExtensions/ErrorTags/Filters/Backslash9CssErrorFilter.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssErrorFilter))] + [Name("Backslash9CssErrorFilter")] + [Order(After = "Default")] + internal class Backslash9CssErrorFilter : ICssErrorFilter + { + public void FilterErrorList(IList errors, ICssCheckerContext context) + { + for (int i = errors.Count - 1; i > -1; i--) + { + ICssError error = errors[i]; + Declaration dec = error.Item.FindType(); + + if (dec != null && dec.Text.Contains("\\9")) + { + errors.RemoveAt(i); + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Filters/CustomCssErrorFilter.cs b/EditorExtensions/ErrorTags/Filters/CustomCssErrorFilter.cs new file mode 100644 index 000000000..a1f6d8ba1 --- /dev/null +++ b/EditorExtensions/ErrorTags/Filters/CustomCssErrorFilter.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssErrorFilter))] + [Name("Custom Errors")] + [Order(After = "Default")] + internal class CustomCssErrorFilter : ICssErrorFilter + { + private readonly Dictionary _messsages = new Dictionary() + { + { "cursorhand", "Consider using \"pointer\" instead." }, + { "cursornormal", "Consider using \"default\" instead." } + }; + + public void FilterErrorList(IList errors, ICssCheckerContext context) + { + for (int i = errors.Count - 1; i > -1; i--) + { + ICssError error = errors[i]; + if (error.Item.IsValid) + { + Declaration dec = error.Item.FindType(); + if (dec != null && dec.IsValid && dec.PropertyName.Text == "cursor") + { + if (error.Item.Text == "hand") + { + errors.RemoveAt(i); + errors.Insert(i, CreateNewError(error, "cursorhand")); + } + else if (error.Item.Text == "normal") + { + errors.RemoveAt(i); + errors.Insert(i, CreateNewError(error, "cursornormal")); + } + } + } + } + } + + private SimpleErrorTag CreateNewError(ICssError error, string messageKey) + { + string message = error.Text + " " + _messsages[messageKey]; + return new SimpleErrorTag(error.Item, message, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Filters/MsFilterCssErrorFilter.cs b/EditorExtensions/ErrorTags/Filters/MsFilterCssErrorFilter.cs new file mode 100644 index 000000000..29f23083e --- /dev/null +++ b/EditorExtensions/ErrorTags/Filters/MsFilterCssErrorFilter.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssErrorFilter))] + [Name("MsFilterCssErrorFilter")] + [Order(After = "Default")] + internal class MsFilterCssErrorFilter : ICssErrorFilter + { + public void FilterErrorList(IList errors, ICssCheckerContext context) + { + for (int i = errors.Count - 1; i > -1; i--) + { + ICssError error = errors[i]; + Declaration dec = error.Item.FindType(); + if (dec != null && dec.IsValid && dec.PropertyName.Text == "-ms-filter") + { + errors.RemoveAt(i); + errors.Insert(i, CreateNewError(error)); + } + } + } + + private SimpleErrorTag CreateNewError(ICssError error) + { + string message = error.Text + " " + " The value must be wrapped in single or double qoutation marks."; + return new SimpleErrorTag(error.Item, message, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Filters/MsKeyframesCssErrorFilter.cs b/EditorExtensions/ErrorTags/Filters/MsKeyframesCssErrorFilter.cs new file mode 100644 index 000000000..df4c4e6e6 --- /dev/null +++ b/EditorExtensions/ErrorTags/Filters/MsKeyframesCssErrorFilter.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssErrorFilter))] + [Name("MsKeyframesCssErrorFilter")] + [Order(After = "Default")] + internal class MsKeyframesCssErrorFilter : ICssErrorFilter + { + private static readonly string _message = " IE only supportes the standard @keyframes implementation."; + + public void FilterErrorList(IList errors, ICssCheckerContext context) + { + for (int i = errors.Count - 1; i > -1; i--) + { + ICssError error = errors[i]; + if (error.Item.IsValid) + { + AtDirective atDir = error.Item.FindType(); + if (atDir != null && atDir.IsValid && atDir.Keyword.Text == "-ms-keyframes") + { + errors.RemoveAt(i); + ICssError tag = new SimpleErrorTag(error.Item, error.Text + _message, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed); + errors.Insert(i, tag); + } + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Filters/ScssErrorFilter.cs b/EditorExtensions/ErrorTags/Filters/ScssErrorFilter.cs new file mode 100644 index 000000000..055314037 --- /dev/null +++ b/EditorExtensions/ErrorTags/Filters/ScssErrorFilter.cs @@ -0,0 +1,33 @@ +//using System.Collections.Generic; +//using System.ComponentModel.Composition; +//using Microsoft.CSS.Core; +//using Microsoft.VisualStudio.Utilities; +//using System.IO; +//using System; + +//namespace MadsKristensen.EditorExtensions +//{ +// [Export(typeof(ICssErrorFilter))] +// [Name("ScssErrorFilter")] +// [Order(After = "Default")] +// internal class ScssErrorFilter : ICssErrorFilter +// { +// public void FilterErrorList(IList errors, ICssCheckerContext context) +// { +// var document = EditorExtensionsPackage.DTE.ActiveDocument; + +// if (document == null || !Path.GetExtension(document.FullName).Equals(ScssContentTypeDefinition.ScssFileExtension, StringComparison.OrdinalIgnoreCase)) +// return; + +// for (int i = errors.Count - 1; i > -1; i--) +// { +// ICssError error = errors[i]; + +// if ((error.Flags & CssErrorFlags.TaskListError) == CssErrorFlags.TaskListError) +// { +// errors.RemoveAt(i); +// } +// } +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/ColorValuesInRangeErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/ColorValuesInRangeErrorTagProvider.cs new file mode 100644 index 000000000..3ad98f643 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/ColorValuesInRangeErrorTagProvider.cs @@ -0,0 +1,86 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("ColorValuesInRangeErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class ColorValuesInRangeErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + FunctionColor function = (FunctionColor)item; + + if (!function.IsValid || context == null) + return ItemCheckResult.Continue; + + if (function.FunctionName.Text.StartsWith("rgb")) + { + ValidateRgb(context, function); + } + //else if (function.FunctionName.Text.StartsWith("hsl")) + //{ + // ValidateHsl(context, function); + //} + + return ItemCheckResult.Continue; + } + + private static void ValidateRgb(ICssCheckerContext context, FunctionColor function) + { + for (int i = 0; i < function.Arguments.Count; i++) + { + var argument = function.Arguments[i]; + string text = argument.Text.Trim(','); + + if (i < 3) + { + int value; + if (int.TryParse(text, out value) && (value < 0 || value > 255)) + context.AddError(new SimpleErrorTag(argument, Resources.ValidationColorValuesInRange, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + else + { + ValidateAlphaValue(context, argument, text); + } + } + } + + private static void ValidateHsl(ICssCheckerContext context, FunctionColor function) + { + for (int i = 0; i < function.Arguments.Count; i++) + { + var argument = function.Arguments[i]; + string text = argument.Text.Trim(',','%'); + + if (i < 3) + { + int value; + if (int.TryParse(text, out value) && (value < 0 || value > 100)) + context.AddError(new SimpleErrorTag(argument, "Validation: Values must be between 0 and 100%", CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + else + { + ValidateAlphaValue(context, argument, text); + } + } + } + + private static void ValidateAlphaValue(ICssCheckerContext context, ParseItem argument, string text) + { + double value; + if (double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value) && (value < 0 || value > 1)) + context.AddError(new SimpleErrorTag(argument, "Validation: The opacity value must be between 0 and 1", CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(FunctionColor) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/DisplayInlineErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/DisplayInlineErrorTagProvider.cs new file mode 100644 index 000000000..34e93107e --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/DisplayInlineErrorTagProvider.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using Microsoft.VisualStudio.Utilities; +using System.Reflection; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewConnectionListener))] + [ContentType(Microsoft.Web.Editor.CssContentTypeDefinition.CssContentType)] + [TextViewRole(PredefinedTextViewRoles.Document)] + class DisplayInlineTextViewCreationListener : IWpfTextViewConnectionListener + { + public void SubjectBuffersConnected(IWpfTextView textView, ConnectionReason reason, Collection subjectBuffers) + { + foreach (ITextBuffer buffer in subjectBuffers) + { + CssEditorDocument doc = CssEditorDocument.FromTextBuffer(buffer); + doc.Tree.ItemsChanged += Tree_ItemsChanged; + doc.Tree.TreeUpdated += Tree_TreeUpdated; + InitializeCache(doc.Tree.StyleSheet); + } + } + + void Tree_TreeUpdated(object sender, CssTreeUpdateEventArgs e) + { + InitializeCache(e.Tree.StyleSheet); + } + + private void InitializeCache(StyleSheet stylesheet) + { + _cache.Clear(); + + var visitor = new CssItemCollector(true); + stylesheet.Accept(visitor); + + foreach (Declaration dec in visitor.Items.Where(d => d.PropertyName != null)) + { + if (dec.PropertyName.Text == "display" && dec.Values.Any(v => v.Text == "inline")) + _cache.Add(dec); + } + } + + public void SubjectBuffersDisconnected(IWpfTextView textView, ConnectionReason reason, Collection subjectBuffers) + { + foreach (ITextBuffer buffer in subjectBuffers) + { + CssEditorDocument doc = CssEditorDocument.FromTextBuffer(buffer); + doc.Tree.ItemsChanged -= Tree_ItemsChanged; + } + } + + private HashSet _cache = new HashSet(); + + void Tree_ItemsChanged(object sender, CssItemsChangedEventArgs e) + { + CssTree tree = (CssTree)sender; + + foreach (ParseItem item in e.InsertedItems) + { + var visitor = new CssItemCollector(true); + item.Accept(visitor); + + foreach (Declaration dec in visitor.Items) + { + if (dec.PropertyName != null && dec.PropertyName.Text == "display" && dec.Values.Any(v => v.Text == "inline")) + { + _cache.Add(dec); + + ParseItem rule = dec.Parent; + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => Update(rule, tree)), DispatcherPriority.Normal); + } + } + } + + foreach (ParseItem item in e.DeletedItems) + { + var visitor = new CssItemCollector(true); + item.Accept(visitor); + + foreach (Declaration deleted in visitor.Items) + { + if (_cache.Contains(deleted)) + { + _cache.Remove(deleted); + + ParseItem rule = deleted.Parent; + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => Update(rule, tree)), DispatcherPriority.Normal); + } + } + } + } + + private static void Update(ParseItem rule, CssTree tree) + { + BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod; + object[] parameters = new object[3]; + parameters[0] = new ParseItemList(); + parameters[1] = new ParseItemList(); + parameters[2] = new ParseItemList() { rule }; + + typeof(CssTree).InvokeMember("FireOnItemsChanged", flags, null, tree, parameters); + } + } + + [Export(typeof(ICssItemChecker))] + [Name("DisplayInlineErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class DisplayInlineErrorTagProvider : ICssItemChecker + { + private static string[] invalidProperties = new[] { "margin-top", "margin-bottom", "height", "width" }; + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + RuleBlock rule = (RuleBlock)item; + + if (!rule.IsValid || context == null) + return ItemCheckResult.Continue; + + bool isInline = rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == "display" && d.Values.Any(v => v.Text == "inline")); + if (!isInline) + return ItemCheckResult.Continue; + + IEnumerable invalids = rule.Declarations.Where(d => invalidProperties.Contains(d.PropertyName.Text)); + + foreach (Declaration invalid in invalids) + { + string error = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeInlineIncompat, invalid.PropertyName.Text); + context.AddError(new SimpleErrorTag(invalid.PropertyName, error)); + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(RuleBlock) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/DuplicatePropertyErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/DuplicatePropertyErrorTagProvider.cs new file mode 100644 index 000000000..e489d7497 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/DuplicatePropertyErrorTagProvider.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("DuplicatePropertyErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class DuplicatePropertyErrorTagProvider : ICssItemChecker + { + // The rules of this error is specified here: https://github.com/stubbornella/csslint/wiki/Disallow-duplicate-properties + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + RuleBlock rule = (RuleBlock)item; + + if (!rule.IsValid || context == null) + return ItemCheckResult.Continue; + + Dictionary dic = new Dictionary(); + + foreach (Declaration declaration in rule.Declarations) + { + ParseItem prop = declaration.PropertyName; + if (prop == null || prop.Text == "filter") + continue; + + string error = null; + + if (!dic.ContainsKey(declaration.Text)) + { + if (dic.ContainsValue(prop.Text) && dic.Last().Value != prop.Text) + { + // The same property name is specified, but not by the immidiate previous declaration + error = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeDuplicatePropertyInRule, prop.Text); + } + + dic.Add(declaration.Text, prop.Text); + } + else + { + // The same property and value exist more than once in the rule. The exact declaration duplicate + error = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeDuplicatePropertyWithSameValueInRule, prop.Text); + } + + if (error != null) + { + context.AddError(new SimpleErrorTag(prop, error)); + } + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(RuleBlock) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/DuplicateSelectorErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/DuplicateSelectorErrorTagProvider.cs new file mode 100644 index 000000000..7aaccfd1b --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/DuplicateSelectorErrorTagProvider.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("DuplicateSelectorErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class DuplicateSelectorErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + RuleSet rule = (RuleSet)item; + + if (!rule.IsValid || context == null) + return ItemCheckResult.Continue; + + List cache = context.GetState(this) as List; + + if (cache == null || (cache.Count > 0 && cache[0].Rule.Parent != rule.Parent)) + { + cache = BuildCache(rule); + context.SetState(this, cache); + } + + string ruleText = GetSelectorText(rule); + int start = rule.Start; + RuleResult dupe = null; + for (int i = 0; i < cache.Count; i++) + { + if (cache[i].Start >= start) + break; + + if (ruleText == cache[i].Value) + { + dupe = cache[i]; + break; + } + } + + if (dupe != null) + { + int length = GetSelectorLength(rule); + int lineNo = FindLineNumber(dupe); + + string errorMessage = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeDuplicateSelectors, lineNo); + SelectorErrorTag tag = new SelectorErrorTag(rule.Selectors, errorMessage); + context.AddError(tag); + } + + return ItemCheckResult.Continue; + } + + // TODO: Is there a better way to find the line number? + private static int FindLineNumber(RuleResult ost) + { + string text = ost.Rule.StyleSheet.Text.Substring(0, ost.Start); + return text.Count(t => t == '\n') + 1; + } + + private static string GetSelectorText(RuleSet rule) + { + var selectorsText = rule.Selectors.OrderBy(s => s.Text.Trim(',')).Select(s => s.Text.Trim(',')); + return string.Concat(selectorsText); + } + + private static int GetSelectorLength(RuleSet rule) + { + var selector = rule.Selectors.Last(); + return selector.AfterEnd - rule.Start; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(RuleSet) }; } + } + + private List BuildCache(RuleSet rule) + { + var visitor = new CssItemCollector(); + rule.Parent.Accept(visitor); + List list = new List(); + + foreach (RuleSet rs in visitor.Items) + { + RuleResult result = new RuleResult(rs, rs.Start, GetSelectorText(rs)); + list.Add(result); + } + + return list; + } + + private class RuleResult + { + public RuleResult(RuleSet rule, int start, string value) + { + Rule = rule; + Start = start; + Value = value; + } + + public RuleSet Rule; + public int Start; + public string Value; + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/EmbedImagesErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/EmbedImagesErrorTagProvider.cs new file mode 100644 index 000000000..78dd1e091 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/EmbedImagesErrorTagProvider.cs @@ -0,0 +1,46 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("EmbedImagesErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class EmbedImagesErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + UrlItem url = (UrlItem)item; + + if (!WESettings.GetBoolean(WESettings.Keys.ValidateEmbedImages) || !url.IsValid || url.UrlString.Text.Contains("base64,") || context == null) + return ItemCheckResult.Continue; + + string fileName = ImageQuickInfo.GetFileName(url.UrlString.Text); + if (fileName.Contains("://")) + return ItemCheckResult.Continue; + + FileInfo file = new FileInfo(fileName); + + if (file.Exists && file.Length < (1024 * 3)) + { + Declaration dec = url.FindType(); + if (dec != null && dec.PropertyName != null && dec.PropertyName.Text[0] != '*' && dec.PropertyName.Text[0] != '_') + { + string error = string.Format(Resources.PerformanceEmbedImageAsDataUri, file.Length); + context.AddError(new SimpleErrorTag(url.UrlString, error)); + } + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(UrlItem) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/HoverOrderErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/HoverOrderErrorTagProvider.cs new file mode 100644 index 000000000..2cc31f619 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/HoverOrderErrorTagProvider.cs @@ -0,0 +1,79 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("HoverOrderErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class HoverOrderErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (item.Text.TrimStart(':').StartsWith("-")) + return ItemCheckResult.Continue; + + ParseItem next = item.NextSibling; + //ParseItem prev = item.PreviousSibling; + SimpleSelector sel = item.FindType(); + + //if (item.Text == ":hover" && prev != null && _invalids.Contains(prev.Text)) + //{ + // string error = string.Format(Resources.ValidationHoverOrder, prev.Text); + // context.AddError(new SimpleErrorTag(item, error, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed)); + //} + + if (next != null) + { + if (next.Text.StartsWith(":") && item.IsPseudoElement() && !next.IsPseudoElement()) + { + string error = string.Format(Resources.ValidationPseudoOrder, item.Text, next.Text); + context.AddError(new SimpleErrorTag(item, error, CssErrorFlags.TaskListError | CssErrorFlags.UnderlineRed)); + } + + else if (!next.Text.StartsWith(":") && item.AfterEnd == next.Start) + { + string error = string.Format(Resources.BestPracticePseudosAfterOtherSelectors, next.Text); + context.AddError(new SimpleErrorTag(next, error)); + } + } + + return ItemCheckResult.Continue; + } + + //public static bool IsPseudoElement(ParseItem item) + //{ + // if (item.Text.StartsWith("::")) + // return true; + + // var schema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + // return schema.GetPseudo(":" + item.Text) != null; + //} + + private static List _invalids = new List() + { + ":before", + "::before", + ":after", + "::after", + }; + + public IEnumerable ItemTypes + { + get + { + return new[] + { + typeof(PseudoClassSelector), + typeof(PseudoClassFunctionSelector), + typeof(PseudoElementFunctionSelector), + typeof(PseudoElementSelector), + }; + } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/Ie10PrefixErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/Ie10PrefixErrorTagProvider.cs new file mode 100644 index 000000000..39e274743 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/Ie10PrefixErrorTagProvider.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("Ie10PrefixErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class Ie10PrefixErrorTagProvider : ICssItemChecker + { + private static readonly string _message = "Validation (WE): {0} no longer applies to Internet Explorer 10. Use the standard implementation instead."; + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + Declaration dec = (Declaration)item; + + if (context == null || !dec.IsValid) + return ItemCheckResult.Continue; + + string text = dec.PropertyName.Text; + + if (text.StartsWith("-ms-transition", StringComparison.Ordinal) || text.StartsWith("-ms-animation", StringComparison.Ordinal)) + { + string error = string.Format(_message, text); + ICssError tag = new SimpleErrorTag(dec.PropertyName, error); + context.AddError(tag); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(Declaration) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/InvalidVendorErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/InvalidVendorErrorTagProvider.cs new file mode 100644 index 000000000..7273f1131 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/InvalidVendorErrorTagProvider.cs @@ -0,0 +1,126 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("InvalidVendorDeclarationErrorTagProvider")] + [Order(After = "Ie10PrefixErrorTagProvider")] + internal class InvalidVendorDeclarationErrorTagProvider : ICssItemChecker + { + //private HashSet _deprecated = new HashSet() + //{ + // "-moz-opacity", + // "-moz-outline", + // "-moz-outline-style", + //}; + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (!WESettings.GetBoolean(WESettings.Keys.ValidateVendorSpecifics)) + return ItemCheckResult.Continue; + + Declaration dec = (Declaration)item; + + if (!dec.IsValid || !dec.IsVendorSpecific() || context == null) + return ItemCheckResult.Continue; + + ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, item); + + //if (_deprecated.Contains(dec.PropertyName.Text)) + //{ + // string message = string.Format(Resources.ValidationDeprecatedVendorDeclaration, dec.PropertyName.Text); + // context.AddError(new SimpleErrorTag(dec.PropertyName, message)); + // return ItemCheckResult.CancelCurrentItem; + //} + if (schema.GetProperty(dec.PropertyName.Text) == null) + { + string message = string.Format(Resources.ValidationVendorDeclarations, dec.PropertyName.Text); + context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(Declaration) }; } + } + } + + [Export(typeof(ICssItemChecker))] + [Name("InvalidVendorPseudoErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class InvalidVendorPseudoErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (!WESettings.GetBoolean(WESettings.Keys.ValidateVendorSpecifics)) + return ItemCheckResult.Continue; + + if (!item.IsValid || context == null) + return ItemCheckResult.Continue; + + ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, item); + + string normalized = item.Text.Trim(':'); + + if (normalized.Length > 0 && normalized[0] == '-' && schema.GetPseudo(item.Text) == null) + { + string message = string.Format(Resources.ValidationVendorPseudo, item.Text); + context.AddError(new SimpleErrorTag(item, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(PseudoClassSelector), typeof(PseudoElementSelector) }; } + } + } + + [Export(typeof(ICssItemChecker))] + [Name("InvalidVendorDirectiveErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class InvalidVendorDirectiveErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (!WESettings.GetBoolean(WESettings.Keys.ValidateVendorSpecifics)) + return ItemCheckResult.Continue; + + AtDirective dir = item as AtDirective; + + if (!dir.IsValid || !dir.IsVendorSpecific() || context == null) + return ItemCheckResult.Continue; + + + ICssSchemaInstance rootSchema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, dir); + + if (schema.GetAtDirective("@" + dir.Keyword.Text) == null) + { + string message = string.Format(Resources.ValidationVendorDirective, dir.Keyword.Text); + context.AddError(new SimpleErrorTag(dir.Keyword, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(AtDirective) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/MissingStandardDirectiveErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/MissingStandardDirectiveErrorTagProvider.cs new file mode 100644 index 000000000..5a3bd2b19 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/MissingStandardDirectiveErrorTagProvider.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Intellisense; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("MissingStandardDirectiveErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class MissingStandardDirectiveErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + AtDirective directive = (AtDirective)item; + + if (context == null || !directive.IsValid || !directive.IsVendorSpecific()) + return ItemCheckResult.Continue; + + ICssCompletionListEntry entry = VendorHelpers.GetMatchingStandardEntry(directive, context); + + if (entry != null) + { + var visitor = new CssItemCollector(); + directive.Parent.Accept(visitor); + if (!visitor.Items.Any(a => "@" + a.Keyword.Text == entry.DisplayText)) + { + string message = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeAddMissingStandardDirective, entry.DisplayText); + context.AddError(new SimpleErrorTag(directive.Keyword, message)); + return ItemCheckResult.CancelCurrentItem; + } + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(AtDirective) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/MissingVendorDirectiveErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/MissingVendorDirectiveErrorTagProvider.cs new file mode 100644 index 000000000..6cfe2a944 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/MissingVendorDirectiveErrorTagProvider.cs @@ -0,0 +1,45 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.CSS.Editor.SyntaxCheck; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("MissingVendorDirectiveErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class MissingVendorDirectiveErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + AtDirective directive = (AtDirective)item; + + if (!directive.IsValid || directive.IsVendorSpecific() || context == null) + return ItemCheckResult.Continue; + + ICssSchemaInstance schema = CssEditorChecker.GetSchemaForItem(context, item); + var missingEntries = directive.GetMissingVendorSpecifics(schema); + + if (missingEntries.Any()) + { + string error = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeAddMissingVendorSpecificDirective, directive.Keyword.Text, string.Join(", ", missingEntries)); + ICssError tag = new SimpleErrorTag(directive.Keyword, error); + context.AddError(tag); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(AtDirective) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/MissingVendorErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/MissingVendorErrorTagProvider.cs new file mode 100644 index 000000000..f0cc4f0c2 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/MissingVendorErrorTagProvider.cs @@ -0,0 +1,53 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.CSS.Editor.SyntaxCheck; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("MissingVendorErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class MissingVendorErrorTagProvider : ICssItemChecker + { + private static string[] _vendorIgnoreList = new[] { "filter", "zoom", "behavior" }; + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + Declaration dec = (Declaration)item; + + if (!dec.IsValid || dec.IsVendorSpecific() || IgnoreProperty(dec) || context == null) + return ItemCheckResult.Continue; + + ICssSchemaInstance schema = CssEditorChecker.GetSchemaForItem(context, item); + var missingEntries = dec.GetMissingVendorSpecifics(schema); + + if (missingEntries.ToArray().Length > 0) + { + var missingPrefixes = missingEntries.Select(e => e.Substring(0, e.IndexOf('-', 1) + 1)); + string error = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeAddMissingVendorSpecific, dec.PropertyName.Text, string.Join(", ", missingPrefixes)); + ICssError tag = new SimpleErrorTag(dec.PropertyName, error); + context.AddError(tag); + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + private static bool IgnoreProperty(Declaration declaration) + { + return _vendorIgnoreList.Contains(declaration.PropertyName.Text); + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(Declaration) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/MissingVendorPseudoErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/MissingVendorPseudoErrorTagProvider.cs new file mode 100644 index 000000000..47a0bd591 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/MissingVendorPseudoErrorTagProvider.cs @@ -0,0 +1,116 @@ +//using Microsoft.CSS.Core; +//using Microsoft.CSS.Editor; +//using Microsoft.VisualStudio.Utilities; +//using System; +//using System.Collections.Generic; +//using System.ComponentModel.Composition; +//using System.Linq; + +//namespace MadsKristensen.EditorExtensions +//{ +// [Export(typeof(ICssItemChecker))] +// [Name("MissingVendorPseudoErrorTagProvider")] +// [Order(After = "Default Declaration")] +// internal class MissingVendorPseudoErrorTagProvider : ICssItemChecker +// { +// public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) +// { +// string name = item.Text.TrimStart(':'); +// RuleSet rule = item.FindType(); +// var buffer = ProjectHelpers.GetCurentTextBuffer(); + +// if (rule == null || buffer == null) +// return ItemCheckResult.Continue; + +// ICssSchemaInstance root = CssSchemaManager.SchemaManager.GetSchemaRootForBuffer(buffer); +// ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(root, item); +// string selector = GetSelectorText(rule); +// string standardName = StandardizeName(name); + +// //if (standardName == "selection" || standardName == "progress-bar") +// // return ItemCheckResult.Continue; + +// IEnumerable missingPseudos = FindMissingPseudos(standardName, selector, schema).Where(p => p != item.Text); + +// if (missingPseudos.Any()) +// { +// string message = string.Format("Browser compatibility: Add selector to the rule with missing pseudo element/class ({0})", string.Join(", ", missingPseudos)); +// context.AddError(new SimpleErrorTag(item, message)); +// } + +// return ItemCheckResult.Continue; +// } + +// public static string StandardizeName(string name) +// { +// if (name.StartsWith("-")) +// { +// int index = name.IndexOf('-', 1); +// if (index > -1) +// return name.Substring(index + 1); +// } + +// return name; +// } + +// public static IEnumerable FindMissingPseudos(string name, string selector, ICssSchemaInstance schema) +// { +// ICssCompletionListEntry standard = FindPseudo(schema, name); + +// if (standard != null && !selector.Contains(standard.DisplayText)) +// yield return standard.DisplayText; + +// foreach (string prefix in VendorHelpers.GetPrefixes(schema)) +// { +// string text = GetPseudoName(prefix, name); +// ICssCompletionListEntry pseudo = FindPseudo(schema, text); + +// if (pseudo != null) +// { +// if (!selector.Contains(pseudo.DisplayText)) +// yield return pseudo.DisplayText; +// } +// } +// } + +// private static ICssCompletionListEntry FindPseudo(ICssSchemaInstance schema, string text) +// { +// ICssCompletionListEntry pseudo = schema.GetPseudo(":" + text); + +// if (pseudo == null) +// { +// pseudo = schema.GetPseudo("::" + text); +// } + +// return pseudo; +// } + +// private static string GetPseudoName(string prefix, string name) +// { +// if (prefix == "-moz-") +// { +// if (name.EndsWith("input-placeholder")) +// return "-moz-placeholder"; +// } +// else +// { +// if (name == "placeholder") +// return prefix + "input-placeholder"; +// } + +// return prefix + name; +// } + +// public static string GetSelectorText(RuleSet rule) +// { +// IEnumerable text = rule.Selectors.Select(s => s.Text); + +// return string.Join(",", text); +// } + +// public IEnumerable ItemTypes +// { +// get { return new[] { typeof(PseudoClassSelector) }; } +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/MsViewState.cs b/EditorExtensions/ErrorTags/Providers/MsViewState.cs new file mode 100644 index 000000000..2cbb88f34 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/MsViewState.cs @@ -0,0 +1,45 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("MsViewState")] + [Order(After = "Default Declaration")] + internal class MsViewStateErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + var media = item as MediaExpression; + + if (media == null || context == null || !IsWindowsWebApp()) + return ItemCheckResult.Continue; + + int index = media.Text.IndexOf("-ms-view-state", StringComparison.OrdinalIgnoreCase); + + if (index > -1) + { + var property = item.StyleSheet.ItemAfterPosition(media.Start + index); + + string message = "The -ms-view-state has been deprecated in Internet Explorer 11"; + context.AddError(new SimpleErrorTag(property, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + + return ItemCheckResult.Continue; + } + + private bool IsWindowsWebApp() + { + // Add logic to determine if the current project is WWA + return true; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(MediaExpression) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/OverQualifiedSelectorErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/OverQualifiedSelectorErrorTagProvider.cs new file mode 100644 index 000000000..b8c627938 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/OverQualifiedSelectorErrorTagProvider.cs @@ -0,0 +1,44 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("OverQualifiedSelectorErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class OverQualifiedSelectorErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + Selector sel = (Selector)item; + + if (!WESettings.GetBoolean(WESettings.Keys.ValidateOverQualifiedSelector) || !sel.IsValid || context == null) + return ItemCheckResult.Continue; + + int index = sel.Text.IndexOf('#'); + + if (index > 0) + { + string idName = sel.ItemAfterPosition(sel.Start + index).Text; + string remove = sel.Text.Substring(0, index); + string errorMessage = string.Format(CultureInfo.InvariantCulture, Resources.PerformanceDontOverQualifySelectors, idName, remove); + + SimpleErrorTag tag = new SimpleErrorTag(sel, errorMessage, index); + + context.AddError(tag); + } + + return ItemCheckResult.Continue; + } + + + public IEnumerable ItemTypes + { + get { return new[] { typeof(Selector) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/OverriddenPropertyErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/OverriddenPropertyErrorTagProvider.cs new file mode 100644 index 000000000..a7330adc5 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/OverriddenPropertyErrorTagProvider.cs @@ -0,0 +1,55 @@ +//using Microsoft.CSS.Core; +//using Microsoft.VisualStudio.Utilities; +//using System; +//using System.Collections.Generic; +//using System.ComponentModel.Composition; +//using System.Linq; + +//namespace MadsKristensen.EditorExtensions +//{ +// [Export(typeof(ICssItemChecker))] +// [Name("OverriddenPropertyErrorTagProvider")] +// [Order(After = "Default Declaration")] +// internal class OverriddenPropertyErrorTagProvider : ICssItemChecker +// { +// public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) +// { +// Declaration dec = (Declaration)item; +// RuleBlock rule = item.Parent as RuleBlock; + +// if (!dec.IsValid || context == null || rule == null) +// return ItemCheckResult.Continue; + +// List list = new List(); + +// foreach (Declaration declaration in rule.Declarations.Where(d => d.PropertyName != null)) +// { +// if (declaration == dec) // Don't look beyond current declaration in the RuleBlock +// break; + +// ParseItem prop = declaration.PropertyName; +// if (prop == null || prop.Text == "border-radius" || dec.PropertyName.Text == "background" || dec.Values.Any(v => v.Text.StartsWith("-"))) +// continue; + +// if (prop.Length > dec.PropertyName.Length && prop.Text.StartsWith(dec.PropertyName.Text)) +// { +// list.Add(prop.Text); +// } +// } + +// if (list.Count > 0) +// { +// string message = "Best practice: '{0}' is overriding previously declared properties in the same rule block ({1})"; +// string error = string.Format(message, dec.PropertyName.Text, string.Join(", ", list.ToArray())); +// context.AddError(new SimpleErrorTag(dec.PropertyName, error)); +// } + +// return ItemCheckResult.Continue; +// } + +// public IEnumerable ItemTypes +// { +// get { return new[] { typeof(Declaration) }; } +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/ShorthandErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/ShorthandErrorTagProvider.cs new file mode 100644 index 000000000..c1fa565f2 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/ShorthandErrorTagProvider.cs @@ -0,0 +1,60 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("ShorthandErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class ShorthandErrorTagProvider : ICssItemChecker + { + private static Dictionary _cache = new Dictionary() + { + {"margin", new [] { "margin-top", "margin-right", "margin-bottom", "margin-left" }}, + {"padding", new [] { "padding-top", "padding-right", "padding-bottom", "padding-left" }}, + {"border", new [] { "border-width", "border-style", "border-color" }}, + {"border-color", new [] { "border-left-color", "border-top-color", "border-right-color", "border-bottom-color" }}, + {"border-style", new [] { "border-left-style", "border-top-style", "border-right-style", "border-bottom-style" }}, + {"border-radius", new [] { "border-top-left-radius", "border-top-right-radius", "border-bottom-left-radius", "border-bottom-right-radius" }}, + {"outline", new [] { "outline-width", "outline-style", "outline-color" }}, + {"list-style", new [] { "list-style-type", "list-style-position", "list-style-image" }}, + {"text-decoration", new [] { "text-decoration-color", "text-decoration-style", "text-decoration-line" }}, + }; + + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + RuleBlock rule = (RuleBlock)item; + + if (!rule.IsValid || context == null) + return ItemCheckResult.Continue; + + IEnumerable properties = from d in rule.Declarations + where d.PropertyName != null && d.Values.Count < 2 + select d.PropertyName.Text; + + + foreach (string shorthand in _cache.Keys) + { + if (_cache[shorthand].All(p => properties.Contains(p))) + { + Declaration dec = rule.Declarations.First(p => p.PropertyName != null && _cache[shorthand].Contains(p.PropertyName.Text)); + string message = string.Format(Resources.PerformanceUseShorthand, string.Join(", ", _cache[shorthand]), shorthand); + + context.AddError(new SimpleErrorTag(dec, message)); + } + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(RuleBlock) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/StarSelectorErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/StarSelectorErrorTagProvider.cs new file mode 100644 index 000000000..abbe1ba90 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/StarSelectorErrorTagProvider.cs @@ -0,0 +1,44 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("StarSelectorErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class StarSelectorErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + SimpleSelector sel = (SimpleSelector)item; + + if (!WESettings.GetBoolean(WESettings.Keys.ValidateStarSelector) || !sel.IsValid || context == null) + return ItemCheckResult.Continue; + + if (sel.Text == "*") + { + //string afterStar = sel.Text.Length > index + 1 ? sel.Text.Substring(index + 1) : null; + //if (afterStar == null || !afterStar.Trim().StartsWith("html", StringComparison.OrdinalIgnoreCase)) + //{ + string errorMessage = string.Format(CultureInfo.InvariantCulture, Resources.PerformanceDontUseStarSelector); + + SimpleErrorTag tag = new SimpleErrorTag(sel, errorMessage); + + context.AddError(tag); + //} + } + + return ItemCheckResult.Continue; + } + + + public IEnumerable ItemTypes + { + get { return new[] { typeof(SimpleSelector) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/UnknownTagErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/UnknownTagErrorTagProvider.cs new file mode 100644 index 000000000..dd43890c3 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/UnknownTagErrorTagProvider.cs @@ -0,0 +1,163 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("UnknownTagErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class UnknownTagErrorTagProvider : ICssItemChecker + { + private HashSet _cache = new HashSet(){ + "*", + "a", + "abbr", + "acronym", + "address", + "applet", + "area", + "article", + "aside", + "audio", + "b", + "base", + "basefont", + "bdi", + "bdo", + "big", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "center", + "cite", + "code", + "col", + "colgroup", + "command", + "datalist", + "dd", + "del", + "details", + "dfn", + "dir", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "font", + "footer", + "form", + "frame", + "frameset", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "keygen", + "kbd", + "label", + "legend", + "li", + "link", + "map", + "mark", + "menu", + "meta", + "meter", + "nav", + "noframes", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "small", + "source", + "span", + "strike", + "strong", + "style", + "sub", + "summary", + "sup", + "svg", + "table", + "tbody", + "td", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "tt", + "u", + "ul", + "var", + "video", + "wbr" + }; + + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + ItemName itemName = (ItemName)item; + + if (!itemName.IsValid || context == null || (item.PreviousSibling != null && item.PreviousSibling.Text == "[")) + return ItemCheckResult.Continue; + + if (!_cache.Contains(itemName.Text.ToLowerInvariant())) + { + string error = "Validation: \"" + itemName.Text + "\" isn't a valid HTML tag."; + ICssError tag = new SimpleErrorTag(itemName, error); + context.AddError(tag); + + return ItemCheckResult.CancelCurrentItem; + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(ItemName) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/VendorOrderErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/VendorOrderErrorTagProvider.cs new file mode 100644 index 000000000..94cdcae82 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/VendorOrderErrorTagProvider.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Utilities; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.SyntaxCheck; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("VendorOrderErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class VendorOrderErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + Declaration dec = (Declaration)item; + + if (context == null || !dec.IsValid) + return ItemCheckResult.Continue; + + RuleBlock rule = dec.FindType(); + if (!rule.IsValid) + return ItemCheckResult.Continue; + + if (!dec.IsVendorSpecific()) + { + ICssSchemaInstance schema = CssEditorChecker.GetSchemaForItem(context, item); + bool hasVendor = VendorHelpers.HasVendorLaterInRule(dec, schema); + if (hasVendor) + { + context.AddError(new SimpleErrorTag(dec.PropertyName, Resources.BestPracticeStandardPropertyOrder)); + return ItemCheckResult.CancelCurrentItem; + } + } + else + { + ICssCompletionListEntry entry = VendorHelpers.GetMatchingStandardEntry(dec, context); + if (entry != null && !rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == entry.DisplayText)) + { + if (entry.DisplayText != "filter" && entry.DisplayText != "zoom" && entry.DisplayText != "behavior") + { + string message = string.Format(CultureInfo.InvariantCulture, Resources.BestPracticeAddMissingStandardProperty, entry.DisplayText); + context.AddError(new SimpleErrorTag(dec.PropertyName, message)); + return ItemCheckResult.CancelCurrentItem; + } + } + } + + return ItemCheckResult.Continue; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(Declaration) }; } + } + } +} diff --git a/EditorExtensions/ErrorTags/Providers/W3cOnlyErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/W3cOnlyErrorTagProvider.cs new file mode 100644 index 000000000..11d3c7c10 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/W3cOnlyErrorTagProvider.cs @@ -0,0 +1,109 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("W3cOnlyErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class W3cOnlyErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (!WESettings.GetBoolean(WESettings.Keys.OnlyW3cAllowed)) + return ItemCheckResult.Continue; + + if (item is Declaration) + { + HandleDeclaration(item, context); + } + else if (item is AtDirective) + { + HandleDirective(item, context); + } + + else if (item is PseudoClassFunctionSelector || item is PseudoClassSelector || item is PseudoElementFunctionSelector || item is PseudoElementSelector) + { + HandlePseudo(item, context); + } + + return ItemCheckResult.Continue; + } + + private static void HandleDeclaration(ParseItem item, ICssCheckerContext context) + { + Declaration dec = (Declaration)item; + + if (dec == null || dec.PropertyName == null) + return; + + if (dec.IsVendorSpecific()) + { + string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C property", dec.PropertyName.Text); + context.AddError(new SimpleErrorTag(dec.PropertyName, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + + foreach (var value in dec.Values) + { + string text = value.Text; + if (!(value is NumericalValue) && text.StartsWith("-", StringComparison.Ordinal)) + { + int index = text.IndexOf('('); + + if (index > -1) + { + text = text.Substring(0, index); + } + + string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C value", text); + context.AddError(new SimpleErrorTag(value, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + } + } + + private static void HandleDirective(ParseItem item, ICssCheckerContext context) + { + AtDirective dir = (AtDirective)item; + + if (dir == null || dir.Keyword == null) + return; + + if (dir.IsVendorSpecific()) + { + string message = string.Format("Validation (W3C): \"@{0}\" is not a valid W3C @-directive", dir.Keyword.Text); + context.AddError(new SimpleErrorTag(dir.Keyword, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + } + + private static void HandlePseudo(ParseItem item, ICssCheckerContext context) + { + string text = item.Text.TrimStart(':'); + + if (text.StartsWith("-", StringComparison.Ordinal)) + { + string message = string.Format("Validation (W3C): \"{0}\" is not a valid W3C pseudo class/element", item.Text); + context.AddError(new SimpleErrorTag(item, message, CssErrorFlags.TaskListWarning | CssErrorFlags.UnderlineRed)); + } + } + + public IEnumerable ItemTypes + { + get + { + return new[] + { + typeof(Declaration), + typeof(AtDirective), + typeof(PseudoClassFunctionSelector), + typeof(PseudoClassSelector), + typeof(PseudoElementFunctionSelector), + typeof(PseudoElementSelector), + }; + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/Providers/ZeroUnitErrorTagProvider.cs b/EditorExtensions/ErrorTags/Providers/ZeroUnitErrorTagProvider.cs new file mode 100644 index 000000000..89733d6a3 --- /dev/null +++ b/EditorExtensions/ErrorTags/Providers/ZeroUnitErrorTagProvider.cs @@ -0,0 +1,46 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ICssItemChecker))] + [Name("ZeroUnitErrorTagProvider")] + [Order(After = "Default Declaration")] + internal class ZeroUnitErrorTagProvider : ICssItemChecker + { + public ItemCheckResult CheckItem(ParseItem item, ICssCheckerContext context) + { + if (!WESettings.GetBoolean(WESettings.Keys.ValidateZeroUnit)) + return ItemCheckResult.Continue; + + NumericalValue number = (NumericalValue)item; + UnitValue unit = number as UnitValue; + + if (unit == null || context == null) + return ItemCheckResult.Continue; + + if (number.Number.Text == "0" && unit.UnitType != UnitType.Unknown && unit.UnitType != UnitType.Time) + { + string message = string.Format(Resources.BestPracticeZeroUnit, unit.UnitToken.Text); + context.AddError(new SimpleErrorTag(number, message)); + } + + return ItemCheckResult.Continue; + } + + private static UnitType GetUnitType(ParseItem valueItem) + { + UnitValue unitValue = valueItem as UnitValue; + + return (unitValue != null) ? unitValue.UnitType : UnitType.Unknown; + } + + public IEnumerable ItemTypes + { + get { return new[] { typeof(NumericalValue) }; } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/ErrorTags/SelectorErrorTag.cs b/EditorExtensions/ErrorTags/SelectorErrorTag.cs new file mode 100644 index 000000000..b8a954294 --- /dev/null +++ b/EditorExtensions/ErrorTags/SelectorErrorTag.cs @@ -0,0 +1,62 @@ +using Microsoft.CSS.Core; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class SelectorErrorTag : ICssError + { + private SortedRangeList _range; + private string _errorMessage; + + public SelectorErrorTag(SortedRangeList range, string errorMessage) + { + _range = range; + _errorMessage = errorMessage; + Flags = GetLocation(); + } + + private static CssErrorFlags GetLocation() + { + switch ((WESettings.Keys.ErrorLocation)WESettings.GetInt(WESettings.Keys.CssErrorLocation)) + { + case WESettings.Keys.ErrorLocation.Warnings: + return CssErrorFlags.UnderlinePurple | CssErrorFlags.TaskListWarning; + + default: + return CssErrorFlags.UnderlinePurple | CssErrorFlags.TaskListMessage; + } + } + + public bool IsExposedToUser + { + get { return true; } + } + + public ParseItem Item + { + get { return _range.First(); } + } + + public string Text + { + get { return _errorMessage; } + } + + public int AfterEnd + { + get { return _range.Last().AfterEnd; } + } + + public int Length + { + get { return AfterEnd - Start; } + } + + public int Start + { + get { return _range.First().Start; } + } + + public CssErrorFlags Flags {get; set; } + } +} diff --git a/EditorExtensions/ErrorTags/SimpleErrorTag.cs b/EditorExtensions/ErrorTags/SimpleErrorTag.cs new file mode 100644 index 000000000..15c82901b --- /dev/null +++ b/EditorExtensions/ErrorTags/SimpleErrorTag.cs @@ -0,0 +1,79 @@ +using Microsoft.CSS.Core; + +namespace MadsKristensen.EditorExtensions +{ + internal class SimpleErrorTag : ICssError + { + private ParseItem _item; + private string _errorMessage; + private int _length; + + public SimpleErrorTag(ParseItem item, string errorMessage, CssErrorFlags flags = CssErrorFlags.TaskListMessage | CssErrorFlags.UnderlinePurple) + { + _item = item; + _errorMessage = errorMessage; + _length = AfterEnd - Start; + Flags = flags; + } + + public SimpleErrorTag(ParseItem item, string errorMessage) + { + _item = item; + _errorMessage = errorMessage; + _length = AfterEnd - Start; + Flags = GetLocation(); + } + + public SimpleErrorTag(ParseItem item, string errorMessage, int length) + { + _item = item; + _errorMessage = errorMessage; + _length = length; + Flags = GetLocation(); + } + + private static CssErrorFlags GetLocation() + { + switch ((WESettings.Keys.ErrorLocation)WESettings.GetInt(WESettings.Keys.CssErrorLocation)) + { + case WESettings.Keys.ErrorLocation.Warnings: + return CssErrorFlags.UnderlinePurple | CssErrorFlags.TaskListWarning; + + default: + return CssErrorFlags.UnderlinePurple | CssErrorFlags.TaskListMessage; + } + } + + public bool IsExposedToUser + { + get { return true; } + } + + public ParseItem Item + { + get { return _item; } + } + + public string Text + { + get { return _errorMessage; } + } + + public int AfterEnd + { + get { return _item.AfterEnd; } + } + + public int Length + { + get { return _length; } + } + + public int Start + { + get { return _item.Start; } + } + + public CssErrorFlags Flags {get; set; } + } +} diff --git a/EditorExtensions/ExtensionMethods/AtDirectiveExtensions.cs b/EditorExtensions/ExtensionMethods/AtDirectiveExtensions.cs new file mode 100644 index 000000000..7b93e9ac9 --- /dev/null +++ b/EditorExtensions/ExtensionMethods/AtDirectiveExtensions.cs @@ -0,0 +1,64 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal static class AtDirectiveExtensions + { + public static bool IsVendorSpecific(this AtDirective directive) + { + return directive.Keyword.Text[0] == '-'; + } + + + public static bool TryGetStandardPropertyName(this AtDirective directive, out string standardName, ICssSchemaInstance schema) + { + standardName = null; + + string propText = directive.Keyword.Text; + string prefix = VendorHelpers.GetPrefixes(schema).SingleOrDefault(p => propText.IndexOf(p, StringComparison.Ordinal) == 0); + if (prefix != null) + { + standardName = propText.Substring(prefix.Length); + return true; + } + + return false; + } + + public static IEnumerable GetMissingVendorSpecifics(this AtDirective directive, ICssSchemaInstance schema) + { + IEnumerable possible = GetPossibleVendorSpecifics(directive, schema); + + var visitorRules = new CssItemCollector(); + directive.Parent.Accept(visitorRules); + + foreach (string item in possible) + { + if (!visitorRules.Items.Any(d => d.Keyword != null && "@" + d.Keyword.Text == item)) + yield return item; + //if (!rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == item)) + // yield return item; + } + } + + public static IEnumerable GetPossibleVendorSpecifics(this AtDirective directive, ICssSchemaInstance schema) + { + string text = directive.Keyword.Text; + + foreach (string prefix in VendorHelpers.GetPrefixes(schema).Where(p => p != "-o-")) // Remove -o- since the parser doesn't recognize -o-keyframes + { + ICssCompletionListEntry entry = schema.GetAtDirective("@" + prefix + text); + if (entry != null) + { + yield return entry.DisplayText; + } + } + } + } +} diff --git a/EditorExtensions/ExtensionMethods/ColorModelExtensions.cs b/EditorExtensions/ExtensionMethods/ColorModelExtensions.cs new file mode 100644 index 000000000..5908df2f1 --- /dev/null +++ b/EditorExtensions/ExtensionMethods/ColorModelExtensions.cs @@ -0,0 +1,56 @@ +using Microsoft.Web.Editor; +using System.Windows.Media; + +namespace MadsKristensen.EditorExtensions +{ + internal static class ColorModelExtensions + { + private const float _factor = 0.025F; + + public static ColorModel Brighten(this ColorModel color) + { + if ((color.HslLightness + _factor) < 1) + { + color.HslLightness += _factor; + } + + return color; + } + + public static ColorModel Darken(this ColorModel color) + { + if ((color.HslLightness - _factor) > 0) + { + color.HslLightness -= _factor; + } + + return color; + } + + public static ColorModel Invert(this ColorModel color) + { + ColorModel model = new ColorModel() + { + Red = ~(byte)color.Red, + Green = ~(byte)color.Green, + Blue = ~(byte)color.Blue + }; + + return model; + + } + + public static SolidColorBrush ToBrush(this ColorModel color) + { + Color c = Color.FromRgb( + (byte)color.Red, + (byte)color.Green, + (byte)color.Blue + ); + + SolidColorBrush brush = new SolidColorBrush(c); + brush.Freeze(); + return brush; + } + } +} diff --git a/EditorExtensions/ExtensionMethods/DeclarationExtensions.cs b/EditorExtensions/ExtensionMethods/DeclarationExtensions.cs new file mode 100644 index 000000000..a45d5cf4c --- /dev/null +++ b/EditorExtensions/ExtensionMethods/DeclarationExtensions.cs @@ -0,0 +1,62 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal static class DeclarationExtensions + { + public static bool IsVendorSpecific(this Declaration declaration) + { + return declaration.PropertyName.Length > 0 ? declaration.PropertyName.Text[0] == '-' : false; + } + + public static bool TryGetStandardPropertyName(this Declaration declaration, out string standardName, ICssSchemaInstance schema) + { + standardName = null; + + if (declaration.IsVendorSpecific()) + { + string propText = declaration.PropertyName.Text; + string prefix = VendorHelpers.GetPrefixes(schema).SingleOrDefault(p => propText.IndexOf(p, StringComparison.Ordinal) == 0); + if (prefix != null) + { + standardName = propText.Substring(prefix.Length); + return true; + } + } + + return false; + } + + public static IEnumerable GetMissingVendorSpecifics(this Declaration declaration, ICssSchemaInstance schema) + { + RuleBlock rule = declaration.FindType(); + IEnumerable possible = GetPossibleVendorSpecifics(declaration, schema); + + foreach (string item in possible) + { + if (!rule.Declarations.Any(d => d.PropertyName != null && d.PropertyName.Text == item)) + yield return item; + } + } + + public static IEnumerable GetPossibleVendorSpecifics(this Declaration declaration, ICssSchemaInstance schema) + { + string text = declaration.PropertyName.Text; + + foreach (string prefix in VendorHelpers.GetPrefixes(schema)) + { + ICssCompletionListEntry entry = schema.GetProperty(prefix + text); + if (entry != null) + { + yield return entry.DisplayText; + } + } + } + } +} diff --git a/EditorExtensions/ExtensionMethods/IVsExtensions.cs b/EditorExtensions/ExtensionMethods/IVsExtensions.cs new file mode 100644 index 000000000..a19ca8b02 --- /dev/null +++ b/EditorExtensions/ExtensionMethods/IVsExtensions.cs @@ -0,0 +1,38 @@ +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace MadsKristensen.EditorExtensions +{ + public static class IVsExtensions + { + public static void AddHierarchyItem(this ErrorTask task) + { + IVsHierarchy HierarchyItem; + IVsSolution solution = EditorExtensionsPackage.GetGlobalService(typeof(SVsSolution)); + Project project = ProjectHelpers.GetActiveProject(); + + if (solution != null && project != null) + { + int flag = solution.GetProjectOfUniqueName(project.FullName, out HierarchyItem); + + if (0 == flag) + { + task.HierarchyItem = HierarchyItem; + } + } + } + + public static bool IsLink(this ProjectItem item) + { + try + { + return (bool)item.Properties.Item("IsLink").Value; + } + catch + { + return false; + } + } + } +} diff --git a/EditorExtensions/ExtensionMethods/PseudoExtensions.cs b/EditorExtensions/ExtensionMethods/PseudoExtensions.cs new file mode 100644 index 000000000..447b69966 --- /dev/null +++ b/EditorExtensions/ExtensionMethods/PseudoExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; + +namespace MadsKristensen.EditorExtensions +{ + public static class PseudoExtensions + { + public static bool IsPseudoElement(this ParseItem item) + { + if (item.Text.StartsWith("::")) + return true; + + var schema = CssSchemaManager.SchemaManager.GetSchemaRoot(null); + return schema.GetPseudo(":" + item.Text) != null; + } + } +} diff --git a/EditorExtensions/GlobalSuppressions.cs b/EditorExtensions/GlobalSuppressions.cs new file mode 100644 index 000000000..37d942cc4 --- /dev/null +++ b/EditorExtensions/GlobalSuppressions.cs @@ -0,0 +1 @@ +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")] diff --git a/EditorExtensions/Guids.cs b/EditorExtensions/Guids.cs new file mode 100644 index 000000000..e1cdf3e43 --- /dev/null +++ b/EditorExtensions/Guids.cs @@ -0,0 +1,30 @@ +using System; + +namespace MadsKristensen.EditorExtensions +{ + static class GuidList + { + public const string guidEditorExtensionsPkgString = "5fb7364d-2e8c-44a4-95eb-2a382e30fec7"; + public const string guidEditorExtensionsCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e41"; + public const string guidCssCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e50"; + public const string guidCssIntellisensCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e51"; + public const string guidWcfToolsCmdSetString = "1446a66d-7e3e-40ce-808e-89a7202d050d"; + public const string guidDiffCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e59"; + public const string guidMinifyCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e61"; + public const string guidBundleCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e63"; + public const string guidExtractCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e64"; + public const string guidBuildCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e65"; + public const string guidFormattingCmdSetString = "e396b698-e00e-444b-9f5f-3dcb1ef74e66"; + + public static readonly Guid guidEditorExtensionsCmdSet = new Guid(guidEditorExtensionsCmdSetString); + public static readonly Guid guidCssCmdSet = new Guid(guidCssCmdSetString); + public static readonly Guid guidCssIntellisenseCmdSet = new Guid(guidCssIntellisensCmdSetString); + public static readonly Guid guidWcfToolsCmdSet = new Guid(guidWcfToolsCmdSetString); + public static readonly Guid guidDiffCmdSet = new Guid(guidDiffCmdSetString); + public static readonly Guid guidMinifyCmdSet = new Guid(guidMinifyCmdSetString); + public static readonly Guid guidBundleCmdSet = new Guid(guidBundleCmdSetString); + public static readonly Guid guidExtractCmdSet = new Guid(guidExtractCmdSetString); + public static readonly Guid guidBuildCmdSet = new Guid(guidBuildCmdSetString); + public static readonly Guid guidFormattingCmdSet = new Guid(guidFormattingCmdSetString); + }; +} \ No newline at end of file diff --git a/EditorExtensions/HTML/Base64ChromeAction.cs b/EditorExtensions/HTML/Base64ChromeAction.cs new file mode 100644 index 000000000..4a55bae9d --- /dev/null +++ b/EditorExtensions/HTML/Base64ChromeAction.cs @@ -0,0 +1,71 @@ +//using System; +//using System.IO; +//using System.Text; +//using System.Xml; +//using Microsoft.VisualStudio.Text; +//using Microsoft.VisualStudio.Text.Editor; +//using Microsoft.VisualStudio.Web.HTML.Chrome; + +//namespace MadsKristensen.EditorExtensions +//{ +// [ChromeAction, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] +// internal class Base64ChromeAction : IChromeAction +// { +// string IChromeAction.Name { get { return "Convert to dataURI"; } } + +// void IChromeAction.Execute(IWpfTextView view, string tagName, int tagPosition) +// { +// string line = view.TextBuffer.CurrentSnapshot.GetText(tagPosition, view.TextBuffer.CurrentSnapshot.Length - tagPosition); +// int length = line.IndexOf('>') + 1; + +// if (length > 0) +// { +// string element = line.Substring(0, length); +// XmlNode img = ConvertToXml(element); + +// if (img != null && img.Attributes["src"] != null) +// { +// XmlAttribute src = img.Attributes["src"]; +// string dataUri = ConvertToDataUri(src); + +// if (!string.IsNullOrEmpty(dataUri)) +// { +// src.InnerText = dataUri; +// view.TextBuffer.Replace(new Span(tagPosition, length), img.OuterXml); +// } +// } +// } +// } + +// private static string ConvertToDataUri(XmlAttribute src) +// { +// string fileName = ProjectHelpers.ToAbsoluteFilePath(src.InnerText); +// if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName)) +// { +// return FileHelpers.ConvertToBase64(fileName); +// } + +// return null; +// } + +// private static XmlNode ConvertToXml(string element) +// { +// StringBuilder sb = new StringBuilder(); + +// using (XmlWriter writer = XmlWriter.Create(sb)) +// { +// writer.WriteRaw(element); +// } + +// XmlDocument doc = new XmlDocument(); +// doc.LoadXml(sb.ToString()); + +// return doc.SelectSingleNode("//img"); +// } + +// bool IChromeAction.IsAvailable(IWpfTextView view, string tagName, int tagPosition) +// { +// return tagName.Equals("img", StringComparison.OrdinalIgnoreCase); +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/HTML/MathMlSchemaFileInfoProvider.cs b/EditorExtensions/HTML/MathMlSchemaFileInfoProvider.cs new file mode 100644 index 000000000..4c40f3325 --- /dev/null +++ b/EditorExtensions/HTML/MathMlSchemaFileInfoProvider.cs @@ -0,0 +1,33 @@ +//using System.Collections.Generic; +//using System.ComponentModel.Composition; +//using System.IO; +//using Microsoft.VisualStudio.Utilities; +//using Microsoft.VisualStudio.Web.HTML.Schemas; + +//namespace MadsKristensen.EditorExtensions +//{ +// [Export(typeof(IHtmlSchemaFileInfoProvider))] +// [Name("MathML")] +// [Order(Before = "Default")] +// internal class MathMlSchemaFileInfoProvider : IHtmlSchemaFileInfoProvider +// { +// private const string _file = @"C:\Users\madsk\Documents\mathml.xsd"; + +// public IEnumerable GetSchemas(string defaultSchemaPath, string defaultRegistryPath) +// { +// if (!File.Exists(_file)) +// yield break; + +// SchemaFileInfo info = new SchemaFileInfo() +// { +// File = _file, +// FriendlyName = "MathML", +// Uri = "http://www.w3.org/1998/Math/MathML", +// IsMobile = true, +// IsNonBrowsable = true, +// }; + +// yield return info; +// } +// } +//} diff --git a/EditorExtensions/Helpers/CssItemCollector.cs b/EditorExtensions/Helpers/CssItemCollector.cs new file mode 100644 index 000000000..4760a7094 --- /dev/null +++ b/EditorExtensions/Helpers/CssItemCollector.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using Microsoft.CSS.Core; + +namespace MadsKristensen.EditorExtensions +{ + /// + /// Creates a list of CSS ParseItems of a certain type + /// (when passed in as the visitor to any item's Accept() function) + /// + internal class CssItemCollector : ICssSimpleTreeVisitor where T : ParseItem + { + public IList Items { get; private set; } + private bool _includeChildren; + + public CssItemCollector() : this(false) { } + + public CssItemCollector(bool includeChildren) + { + _includeChildren = includeChildren; + Items = new List(); + } + + public VisitItemResult Visit(ParseItem parseItem) + { + var item = parseItem as T; + + if (item != null) + { + Items.Add(item); + return (_includeChildren) ? VisitItemResult.Continue : VisitItemResult.SkipChildren; + } + + return VisitItemResult.Continue; + } + } +} diff --git a/EditorExtensions/Helpers/FileHelpers.cs b/EditorExtensions/Helpers/FileHelpers.cs new file mode 100644 index 000000000..9c44d7164 --- /dev/null +++ b/EditorExtensions/Helpers/FileHelpers.cs @@ -0,0 +1,92 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + public static class FileHelpers + { + public static string ConvertToBase64(string fileName) + { + string format = "data:{0};base64,{1}"; + byte[] buffer = File.ReadAllBytes(fileName); + string extension = Path.GetExtension(fileName).Substring(1); + string contentType = GetMimeType(extension); + + return string.Format(CultureInfo.InvariantCulture, format, contentType, Convert.ToBase64String(buffer)); + } + + private static string GetMimeType(string extension) + { + switch (extension) + { + case "png": + case "jpg": + case "jpeg": + case "gif": + return "image/" + extension; + + case "woff": + return "font/x-woff"; + + case "otf": + return "font/otf"; + + case "eot": + return "application/vnd.ms-fontobject"; + + case "ttf": + return "application/octet-stream"; + + default: + return "text/plain"; + } + } + + public static string RelativePath(string absPath, string relTo) + { + string[] absDirs = absPath.Split('\\'); + string[] relDirs = relTo.Split('\\'); + + // Get the shortest of the two paths + int len = absDirs.Length < relDirs.Length ? absDirs.Length : + relDirs.Length; + + // Use to determine where in the loop we exited + int lastCommonRoot = -1; + int index; + + // Find common root + for (index = 0; index < len; index++) + { + if (absDirs[index] == relDirs[index]) lastCommonRoot = index; + else break; + } + + // If we didn't find a common prefix then throw + if (lastCommonRoot == -1) + { + return relTo; + } + + // Build up the relative path + StringBuilder relativePath = new StringBuilder(); + + // Add on the .. + for (index = lastCommonRoot + 2; index < absDirs.Length; index++) + { + if (absDirs[index].Length > 0) relativePath.Append("..\\"); + } + + // Add on the folders + for (index = lastCommonRoot + 1; index < relDirs.Length - 1; index++) + { + relativePath.Append(relDirs[index] + "\\"); + } + relativePath.Append(relDirs[relDirs.Length - 1]); + + return relativePath.ToString().Replace("\\", "/"); + } + } +} diff --git a/EditorExtensions/Helpers/OptionHelpers.cs b/EditorExtensions/Helpers/OptionHelpers.cs new file mode 100644 index 000000000..d55c390fa --- /dev/null +++ b/EditorExtensions/Helpers/OptionHelpers.cs @@ -0,0 +1,87 @@ +using System; +using System.Windows.Media; +using VS = Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.Web.Editor; + +namespace MadsKristensen.EditorExtensions +{ + internal static class OptionHelpers + { + private static int _fontSize; + private static ColorModel _backgroundColor; + private static object _syncRoot = new object(); + + // TODO: Compensate for the current line highlighting + public static ColorModel BackgroundColor + { + get + { + if (_backgroundColor == null) + { + lock (_syncRoot) + { + if (_backgroundColor == null) + { + GetSize(); + } + } + } + + return _backgroundColor; + } + } + + public static int FontSize + { + get + { + if (_fontSize == 0) + { + lock (_syncRoot) + { + if (_fontSize == 0) + { + GetSize(); + } + } + } + + return _fontSize; + } + } + + private static void GetSize() + { + try + { + IVsFontAndColorStorage storage = (IVsFontAndColorStorage)EditorExtensionsPackage.GetGlobalService(typeof(IVsFontAndColorStorage)); + var guid = new Guid("A27B4E24-A735-4d1d-B8E7-9716E1E3D8E0"); + if (storage != null && storage.OpenCategory(ref guid, (uint)(__FCSTORAGEFLAGS.FCSF_READONLY | __FCSTORAGEFLAGS.FCSF_LOADDEFAULTS)) == VS.VSConstants.S_OK) + { + LOGFONTW[] Fnt = new LOGFONTW[] { new LOGFONTW() }; + FontInfo[] Info = new FontInfo[] { new FontInfo() }; + storage.GetFont(Fnt, Info); + _fontSize = (int)Info[0].wPointSize; + } + + if (storage != null && storage.OpenCategory(ref guid, (uint)(__FCSTORAGEFLAGS.FCSF_NOAUTOCOLORS | __FCSTORAGEFLAGS.FCSF_LOADDEFAULTS)) == VS.VSConstants.S_OK) + { + var info = new ColorableItemInfo[1]; + storage.GetItem("Plain Text", info); + _backgroundColor = ConvertFromWin32Color((int)info[0].crBackground); + } + + } + catch { } + } + + public static ColorModel ConvertFromWin32Color(int color) + { + int r = color & 0x000000FF; + int g = (color & 0x0000FF00) >> 8; + int b = (color & 0x00FF0000) >> 16; + return new ColorModel() { Red = r, Green = g, Blue = b }; + } + } +} diff --git a/EditorExtensions/Helpers/ProjectHelpers.cs b/EditorExtensions/Helpers/ProjectHelpers.cs new file mode 100644 index 000000000..6fd3b4042 --- /dev/null +++ b/EditorExtensions/Helpers/ProjectHelpers.cs @@ -0,0 +1,229 @@ +using EnvDTE; +using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.Editor; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.TextManager.Interop; +using System; +using System.Collections.Generic; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + internal static class ProjectHelpers + { + public static string GetRootFolder() + { + try + { + EnvDTE80.DTE2 dte = EditorExtensionsPackage.DTE; + Project activeProject = null; + + if (dte.Solution.Projects.Count == 1 && !string.IsNullOrEmpty(dte.Solution.Projects.Item(1).FullName)) + { + return dte.Solution.Projects.Item(1).Properties.Item("FullPath").Value.ToString(); + } + + Array activeSolutionProjects = dte.ActiveSolutionProjects as Array; + + if (activeSolutionProjects != null && activeSolutionProjects.Length > 0) + { + activeProject = activeSolutionProjects.GetValue(0) as Project; + } + + return activeProject.Properties.Item("FullPath").Value.ToString(); + } + catch (Exception ex) + { + Logger.Log(ex); + return string.Empty; + } + } + + internal static bool AddFileToActiveProject(string fileName, string itemType = null) + { + Project project = GetActiveProject(); + + if (project != null) + { + string projectFilePath = project.Properties.Item("FullPath").Value.ToString(); + string projectDirPath = Path.GetDirectoryName(projectFilePath); + + if (fileName.StartsWith(projectDirPath, StringComparison.OrdinalIgnoreCase)) + { + ProjectItem item = project.ProjectItems.AddFromFile(fileName); + + if (itemType != null && item != null && !project.FullName.Contains("://")) + { + try + { + item.Properties.Item("ItemType").Value = itemType; + } + catch { } + } + } + } + + return false; + } + + public static Project GetActiveProject() + { + Project activeProject = null; + + try + { + Array activeSolutionProjects = EditorExtensionsPackage.DTE.ActiveSolutionProjects as Array; + + if (activeSolutionProjects != null && activeSolutionProjects.Length > 0) + { + activeProject = activeSolutionProjects.GetValue(0) as Project; + } + } + catch + { + Logger.Log("Error getting the active project"); + } + + return activeProject; + } + + public static string ToAbsoluteFilePath(string relativeUrl, string rootFolder = null) + { + string imageUrl = relativeUrl.Trim(new[] { '\'', '"' }); + string filePath = string.Empty; + + if (imageUrl.StartsWith("/", StringComparison.Ordinal)) + { + string root = rootFolder ?? ProjectHelpers.GetRootFolder(); + + if (root.Contains("://")) + { + filePath = root + imageUrl; + } + else if (!string.IsNullOrEmpty(root)) + { + if (!Directory.Exists(root)) + { + filePath = new FileInfo(root).Directory + imageUrl; + } + else + { + return root + imageUrl.Replace("/", "\\"); + } + } + } + else + { + FileInfo fi = new FileInfo(EditorExtensionsPackage.DTE.ActiveDocument.FullName); + DirectoryInfo dir = fi.Directory; + + while (imageUrl.Contains("../")) + { + imageUrl = imageUrl.Remove(imageUrl.IndexOf("../", StringComparison.Ordinal), 3); + dir = dir.Parent; + } + + filePath = Path.Combine(dir.FullName, imageUrl.Replace("/", "\\")); + } + + return filePath; + } + + public static ITextBuffer GetCurentTextBuffer() + { + return GetCurentTextView().TextBuffer; + } + + public static IWpfTextView GetCurentTextView() + { + var componentModel = GetComponentModel(); + var editorAdapter = componentModel.GetService(); + var textManager = (IVsTextManager)ServiceProvider.GlobalProvider.GetService(typeof(SVsTextManager)); + + IVsTextView activeView = null; + textManager.GetActiveView(1, null, out activeView); + + return editorAdapter.GetWpfTextView(activeView); + } + + public static IComponentModel GetComponentModel() + { + return (IComponentModel)ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel)); + } + + public static IEnumerable GetSelectedItemPaths() + { + var items = (Array)EditorExtensionsPackage.DTE.ToolWindows.SolutionExplorer.SelectedItems; + foreach (UIHierarchyItem selItem in items) + { + var item = selItem.Object as ProjectItem; + if (item != null) + { + yield return item.Properties.Item("FullPath").Value.ToString(); + } + } + } + + public static bool CheckOutFileFromSourceControl(string fileName) + { + try + { + var dte = EditorExtensionsPackage.DTE; + + if (File.Exists(fileName) && dte.Solution.FindProjectItem(fileName) != null) + { + if (dte.SourceControl.IsItemUnderSCC(fileName) && !dte.SourceControl.IsItemCheckedOut(fileName)) + { + dte.SourceControl.CheckOutItem(fileName); + } + + return true; + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + + return false; + } + + public static string GetSolutionFolderPath() + { + EnvDTE.Solution solution = EditorExtensionsPackage.DTE.Solution; + + if (solution == null || string.IsNullOrEmpty(solution.FullName)) + return null; + + return Path.GetDirectoryName(solution.FullName); + } + + public static string GetProjectFolder(string fileNameOrFolder) + { + if (string.IsNullOrEmpty(fileNameOrFolder)) + return GetRootFolder(); + + ProjectItem item = EditorExtensionsPackage.DTE.Solution.FindProjectItem(fileNameOrFolder); + + if (item == null || item.ContainingProject == null || string.IsNullOrEmpty(item.ContainingProject.FullName)) // Solution items + return null; + + return item.ContainingProject.Properties.Item("FullPath").Value.ToString(); + } + + public static IEnumerable GetSelectedItems() + { + var items = (Array)EditorExtensionsPackage.DTE.ToolWindows.SolutionExplorer.SelectedItems; + foreach (UIHierarchyItem selItem in items) + { + var item = selItem.Object as ProjectItem; + if (item != null) + { + yield return item; + } + } + } + } +} diff --git a/EditorExtensions/Helpers/VendorHelpers.cs b/EditorExtensions/Helpers/VendorHelpers.cs new file mode 100644 index 000000000..beb27b859 --- /dev/null +++ b/EditorExtensions/Helpers/VendorHelpers.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.SyntaxCheck; + +namespace MadsKristensen.EditorExtensions +{ + internal static class VendorHelpers + { + private static object _syncRoot = new object(); + private static Dictionary prefixes = new Dictionary(); + + public static string[] GetPrefixes(ICssSchemaInstance schema) + { + int version = schema.Version.GetHashCode(); + int browser = schema.Filter.Name.GetHashCode(); + int hash = version ^ browser; + + if (!prefixes.ContainsKey(hash)) + { + CssSchemaManager.SchemaManager.CurrentSchemaChanged += CurrentSchemaChanged; + var properties = schema.Properties; + List list = new List(); + + foreach (ICssCompletionListEntry property in properties) + { + string text = property.DisplayText; + if (text[0] == '-') + { + int end = text.IndexOf('-', 1); + if (end > -1) + { + string prefix = text.Substring(0, end + 1); + if (!list.Contains(prefix)) + { + list.Add(prefix); + } + } + } + } + + prefixes.Add(hash, list.ToArray()); + } + + return prefixes[hash]; + } + + private static void CurrentSchemaChanged(object sender, EventArgs e) + { + CssSchemaManager.SchemaManager.CurrentSchemaChanged -= CurrentSchemaChanged; + } + + public static bool HasVendorLaterInRule(Declaration declaration, ICssSchemaInstance schema) + { + Declaration next = declaration.NextSibling as Declaration; + + while (next != null) + { + if (next.IsValid && next.IsVendorSpecific()) + { + foreach (string prefix in GetPrefixes(schema)) + { + if (next.PropertyName.Text == prefix + declaration.PropertyName.Text) + return true; + } + } + + next = next.NextSibling as Declaration; + } + + return false; + } + + public static IEnumerable GetMatchingVendorEntriesInRule(Declaration declaration, RuleBlock rule, ICssSchemaInstance schema) + { + foreach (Declaration d in rule.Declarations.Where(d => d.IsValid && d.IsVendorSpecific())) + foreach (string prefix in GetPrefixes(schema)) + { + if (d.PropertyName.Text == prefix + declaration.PropertyName.Text) + { + yield return d; + break; + } + } + } + + public static ICssCompletionListEntry GetMatchingStandardEntry(Declaration declaration, ICssSchemaInstance rootSchema) + { + string standardName; + if (declaration.TryGetStandardPropertyName(out standardName, rootSchema)) + { + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, declaration); + return schema.GetProperty(standardName); + } + + return null; + } + + public static ICssCompletionListEntry GetMatchingStandardEntry(Declaration declaration, ICssCheckerContext context) + { + string standardName; + if (declaration.TryGetStandardPropertyName(out standardName, CssEditorChecker.GetSchemaForItem(context, declaration))) + { + ICssSchemaInstance schema = CssEditorChecker.GetSchemaForItem(context, declaration); + return schema.GetProperty(standardName); + } + + return null; + } + + public static ICssCompletionListEntry GetMatchingStandardEntry(AtDirective directive, ICssCheckerContext context) + { + string standardName; + if (directive.TryGetStandardPropertyName(out standardName, CssEditorChecker.GetSchemaForItem(context, directive))) + { + ICssSchemaInstance schema = CssEditorChecker.GetSchemaForItem(context, directive); + return schema.GetAtDirective("@" + standardName); + } + + return null; + } + + public static ICssCompletionListEntry GetMatchingStandardEntry(AtDirective directive, ICssSchemaInstance rootSchema) + { + string standardName; + if (directive.TryGetStandardPropertyName(out standardName, rootSchema)) + { + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(rootSchema, directive); + return schema.GetAtDirective("@" + standardName); + } + + return null; + } + } +} diff --git a/EditorExtensions/Key.snk b/EditorExtensions/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..d9d7495d7795d1c2909ce6754c46e9be7d46ea53 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098ueOv%*&a3a&<@aDp=-({HD55&wHUyEf z`WwMSO9@W$9#n{L!HeJ*G-+GZNqfgX;KCO-nkjIFAKwG=7Pe|*`e_$e@;lbS#HbSh z>-~*ltt<^|kJmvG)Q%SL0}Lw?aviPoUeX^Ka0npUBYZGc{^-N&7X)eP6$6y^_qE|& zBL+Wp{k6F{4M_!4C;S!M_dpI~YsHD4?$H}HmuT|gWY`}Ngl;j&c->TT|2Y;?f5Xq@ zOwiW^vFk=(RE_>sz%fMAVBW4*O#Zku8?GY8=t9-uBK6%5PAzrREd7dt`(C78m*v~X z=G{VchTn08q~SK11rTFpLmhf9r2gXFr1|4gEwFzQN|ZacMyT51gD2tE*MfqT=e<&7 z&aWm~YOakB|5!>63ri*`UdUH7oEYkJQE-y|XjiSe@H+JkfNYB8)L6l{p;yPOX%S?A z!2Dg5)~|&K2YB0_?LQ3fd&OiV2INIqN%q{!1f+&qJx41Gr6m5dupi{PDtK>Eq?4i3 z2|jF*o^N+H3g|E9IZQJwO@KjOAUA7RqiXSE-px;zz)qh8+e"; + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/CoffeeScriptMargin.cs b/EditorExtensions/Margin/CoffeeScriptMargin.cs new file mode 100644 index 000000000..21c43404c --- /dev/null +++ b/EditorExtensions/Margin/CoffeeScriptMargin.cs @@ -0,0 +1,178 @@ +using Microsoft.VisualStudio.Text; +using System; +using System.IO; +using System.Text; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + class CoffeeScriptMargin : MarginBase + { + public const string MarginName = "CoffeeScriptMargin"; + private CoffeeScriptCompiler _compiler; + private int _projectFileCount, _projectFileStep; + + public CoffeeScriptMargin(string contentType, string source, bool showMargin, ITextDocument document) + : base(source, MarginName, contentType, showMargin, document) + { + _compiler = new CoffeeScriptCompiler(Dispatcher); + _compiler.Completed += _compiler_Completed; //+= (s, e) => { OnCompilationDone(e.Result, e.State); }; + } + + public CoffeeScriptMargin() + { + // Used for project compilation + } + + public void CompileProject(EnvDTE.Project project) + { + if (string.IsNullOrEmpty(project.FullName)) + return; + + Logger.Log("Compiling CoffeeScript..."); + _projectFileCount = 0; + + try + { + string fullPath = project.Properties.Item("FullPath").Value.ToString(); + + if (project != null && !string.IsNullOrEmpty(fullPath)) + { + string dir = Path.GetDirectoryName(fullPath); + var files = Directory.GetFiles(dir, "*.coffee", SearchOption.AllDirectories); + + foreach (string file in files) + { + string jsFile = GetCompiledFileName(file, ".js", UseCompiledFolder); + + if (EditorExtensionsPackage.DTE.Solution.FindProjectItem(file) != null && + File.Exists(jsFile)) + { + _projectFileCount++; + + CoffeeScriptCompiler compiler = new CoffeeScriptCompiler(Dispatcher.CurrentDispatcher); + compiler.Completed += compiler_Completed; + compiler.Compile(File.ReadAllText(file), file); + } + } + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + + void compiler_Completed(object sender, CompilerEventArgs e) + { + _projectFileStep++; + string file = GetCompiledFileName(e.State, ".js", UseCompiledFolder); + + ProjectHelpers.CheckOutFileFromSourceControl(file); + + using (StreamWriter writer = new StreamWriter(file, false, new UTF8Encoding(true))) + { + writer.Write(e.Result); + } + + MinifyFile(e.State, e.Result); + + if (_projectFileStep == _projectFileCount) + Logger.Log("CoffeeScript compiled"); + } + + protected override void StartCompiler(string source) + { + string fileName = GetCompiledFileName(Document.FilePath, ".js", UseCompiledFolder);//Document.FilePath.Replace(".coffee", ".js"); + + if (_isFirstRun && File.Exists(fileName)) + { + OnCompilationDone(File.ReadAllText(fileName), Document.FilePath); + return; + } + + Logger.Log("CoffeeScript: Compiling " + Path.GetFileName(Document.FilePath)); + _compiler.Compile(source, Document.FilePath); + } + + private void _compiler_Completed(object sender, CompilerEventArgs e) + { + if (e.Result.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase)) + { + CompilerError error = ParseError(e.Result); + CreateTask(error); + } + + OnCompilationDone(e.Result, e.State); + } + + private CompilerError ParseError(string error) + { + string message = error.Replace("ERROR:", string.Empty).Replace("Error:", string.Empty); + int index = message.IndexOf(':'); + int line = 0; + + if (index > -1) + { + int start = message.LastIndexOf(' ', index); + if (start > -1) + { + int length = index - start - 1; + string part = message.Substring(start + 1, length); + int.TryParse(part, out line); + } + } + + CompilerError result = new CompilerError() + { + Message = "CoffeeScript: " + message, + FileName = Document.FilePath, + Line = line, + }; + + return result; + } + + public override void MinifyFile(string fileName, string source) + { + if (WESettings.GetBoolean(WESettings.Keys.CoffeeScriptMinify)) + { + string content = MinifyFileMenu.MinifyString(".js", source); + string minFile = GetCompiledFileName(fileName, ".min.js", UseCompiledFolder);//fileName.Replace(".coffee", ".min.js"); + bool fileExist = File.Exists(minFile); + + ProjectHelpers.CheckOutFileFromSourceControl(minFile); + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + + if (!fileExist) + AddFileToProject(fileName, minFile); + } + } + + public override bool UseCompiledFolder + { + get { return WESettings.GetBoolean(WESettings.Keys.CoffeeScriptCompileToFolder); } + } + + public override bool IsSaveFileEnabled + { + get { return WESettings.GetBoolean(WESettings.Keys.GenerateJsFileFromCoffeeScript); } + } + + protected override bool CanWriteToDisk(string source) + { + return !string.IsNullOrWhiteSpace(source); + } + } +} + +//static class Iced +//{ +// [Export] +// [FileExtension(".iced")] +// [ContentType("CoffeeScript")] +// internal static FileExtensionToContentTypeDefinition IcedFileExtensionDefinition; +//} \ No newline at end of file diff --git a/EditorExtensions/Margin/CompilerError.cs b/EditorExtensions/Margin/CompilerError.cs new file mode 100644 index 000000000..c4b9548c0 --- /dev/null +++ b/EditorExtensions/Margin/CompilerError.cs @@ -0,0 +1,11 @@ + +namespace MadsKristensen.EditorExtensions +{ + public class CompilerError + { + public int Line { get; set; } + public int Column { get; set; } + public string FileName { get; set; } + public string Message { get; set; } + } +} diff --git a/EditorExtensions/Margin/CompilerResult.cs b/EditorExtensions/Margin/CompilerResult.cs new file mode 100644 index 000000000..38f5f3120 --- /dev/null +++ b/EditorExtensions/Margin/CompilerResult.cs @@ -0,0 +1,16 @@ + +namespace MadsKristensen.EditorExtensions +{ + public class CompilerResult + { + public CompilerResult(string fileName) + { + FileName = fileName; + } + + public bool IsSuccess { get; set; } + public string FileName { get; set; } + public string Result { get; set; } + public CompilerError Error { get; set; } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/EditorMarginFactory.cs b/EditorExtensions/Margin/EditorMarginFactory.cs new file mode 100644 index 000000000..7786115c8 --- /dev/null +++ b/EditorExtensions/Margin/EditorMarginFactory.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewMarginProvider))] + [Name(LessMargin.MarginName)] + [Order(After = PredefinedMarginNames.RightControl)] + [MarginContainer(PredefinedMarginNames.Right)] + [ContentType("LESS")] + [ContentType("CoffeeScript")] + //[ContentType("TypeScript")] + [ContentType("Markdown")] + [TextViewRole(PredefinedTextViewRoles.Debuggable)] + internal sealed class MarginFactory : IWpfTextViewMarginProvider + { + public IWpfTextViewMargin CreateMargin(IWpfTextViewHost textViewHost, IWpfTextViewMargin containerMargin) + { + string source = textViewHost.TextView.TextBuffer.CurrentSnapshot.GetText(); + ITextDocument document; + + if (textViewHost.TextView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document)) + { + switch (textViewHost.TextView.TextBuffer.ContentType.DisplayName) + { + case "LESS": + bool showLess = WESettings.GetBoolean(WESettings.Keys.ShowLessPreviewWindow); + return new LessMargin("CSS", source, showLess, document); + + //case "scss": + // return new ScssMargin("CSS", source, true, document); + + case "CoffeeScript": + bool showCoffee = WESettings.GetBoolean(WESettings.Keys.ShowCoffeeScriptPreviewWindow); + return new CoffeeScriptMargin("JavaScript", source, showCoffee, document); + + //case "TypeScript": + // if (!document.FilePath.EndsWith(".d.ts")) + // { + // bool showType = WESettings.GetBoolean(WESettings.Keys.ShowTypeScriptPreviewWindow); + // return new TypeScriptMargin("TypeScript", source, showType, document); + // } + // break; + + case "markdown": + return new MarkdownMargin("text", source, true, document); + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/LessCompiler.cs b/EditorExtensions/Margin/LessCompiler.cs new file mode 100644 index 000000000..2d91e2e67 --- /dev/null +++ b/EditorExtensions/Margin/LessCompiler.cs @@ -0,0 +1,147 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace MadsKristensen.EditorExtensions +{ + public class LessCompiler + { + public LessCompiler(Action callback) + { + Callback = callback; + } + + public Action Callback { get; set; } + + public void Compile(string fileName) + { + string output = Path.GetTempFileName(); + + ProcessStartInfo start = new ProcessStartInfo(@"cscript"); + start.WindowStyle = ProcessWindowStyle.Hidden; + start.CreateNoWindow = true; + start.Arguments = "//nologo //s \"" + GetExecutablePath() + "\" \"" + fileName + "\" \"" + output + "\""; + start.EnvironmentVariables["output"] = output; + start.EnvironmentVariables["fileName"] = fileName; + start.UseShellExecute = false; + start.RedirectStandardError = true; + + Process p = new Process(); + p.StartInfo = start; + p.EnableRaisingEvents = true; + p.Exited += ProcessExited; + p.Start(); + } + + private void ProcessExited(object sender, EventArgs e) + { + using (Process process = (Process)sender) + { + string fileName = process.StartInfo.EnvironmentVariables["fileName"]; + CompilerResult result = new CompilerResult(fileName); + + try + { + ProcessResult(process, result); + } + catch (Exception ex) + { + Logger.Log(ex); + Callback(result); + } + + process.Exited -= ProcessExited; + + Logger.Log(Path.GetFileName(fileName) + " compiled"); + } + } + + private void ProcessResult(Process process, CompilerResult result) + { + string output = process.StartInfo.EnvironmentVariables["output"]; + + if (File.Exists(output)) + { + if (process.ExitCode == 0) + { + result.IsSuccess = true; + result.Result = File.ReadAllText(output); + } + else + { + using (StreamReader reader = process.StandardError) + { + result.Error = ParseError(reader.ReadToEnd()); + } + } + + File.Delete(output); + } + + Callback(result); + } + + private CompilerError ParseError(string error) + { + CompilerError result = new CompilerError(); + string[] lines = error.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < lines.Length; i++) + { + string line = lines[i]; + + if (error.Contains("message:")) + { + string[] args = line.Split(new[] { ':' }, 2); + + if (args[0].Trim() == "message") + result.Message = args[1].Trim(); + + if (args[0].Trim() == "filename") + result.FileName = args[1].Trim(); + + int lineNo = 0; + if (args[0].Trim() == "line" && int.TryParse(args[1], out lineNo)) + result.Line = lineNo; + + int columnNo = 0; + if (args[0].Trim() == "column" && int.TryParse(args[1], out columnNo)) + result.Column = columnNo; + } + else + { + if (i == 1 || i == 2) + result.Message += " " + line; + + if (i == 3) + { + string[] lineCol = line.Split(','); + + int lineNo = 0; + if (int.TryParse(lineCol[0].Replace("on line", string.Empty).Trim(), out lineNo)) + result.Line = lineNo; + + int columnNo = 0; + if (int.TryParse(lineCol[0].Replace("column", string.Empty).Trim(':').Trim(), out columnNo)) + result.Column = columnNo; + + result.Message = result.Message.Trim(); + } + + } + } + + return result; + } + + private static string GetExecutablePath() + { + string assembly = Assembly.GetExecutingAssembly().Location; + string folder = Path.GetDirectoryName(assembly).ToLowerInvariant(); + string file = Path.Combine(folder, "resources\\scripts\\lessc.wsf"); + + return file; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/LessMargin.cs b/EditorExtensions/Margin/LessMargin.cs new file mode 100644 index 000000000..fbc52b24a --- /dev/null +++ b/EditorExtensions/Margin/LessMargin.cs @@ -0,0 +1,89 @@ +using EnvDTE; +using Microsoft.VisualStudio.Text; +using System.IO; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + public class LessMargin : MarginBase + { + public const string MarginName = "LessMargin"; + + public LessMargin(string contentType, string source, bool showMargin, ITextDocument document) + : base(source, MarginName, contentType, showMargin, document) + { } + + protected override void StartCompiler(string source) + { + string fileName = GetCompiledFileName(Document.FilePath, ".css", UseCompiledFolder);// Document.FilePath.Replace(".less", ".css"); + + if (_isFirstRun && File.Exists(fileName)) + { + OnCompilationDone(File.ReadAllText(fileName), Document.FilePath); + } + else + { + Logger.Log("LESS: Compiling " + Path.GetFileName(Document.FilePath)); + + System.Threading.Tasks.Task.Run(() => + { + LessCompiler compiler = new LessCompiler(Completed); + compiler.Compile(Document.FilePath); + }); + } + } + + private void Completed(CompilerResult result) + { + if (result.IsSuccess) + { + OnCompilationDone(result.Result, result.FileName); + } + else + { + result.Error.Message = "LESS: " + result.Error.Message; + + CreateTask(result.Error); + + base.OnCompilationDone("ERROR:", Document.FilePath); + } + } + + public override void MinifyFile(string fileName, string source) + { + if (WESettings.GetBoolean(WESettings.Keys.LessMinify) && !Path.GetFileName(fileName).StartsWith("_")) + { + string content = MinifyFileMenu.MinifyString(".css", source); + string minFile = GetCompiledFileName(fileName, ".min.css", UseCompiledFolder);// fileName.Replace(".less", ".min.css"); + bool fileExist = File.Exists(minFile); + + ProjectHelpers.CheckOutFileFromSourceControl(minFile); + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + + if (!fileExist) + AddFileToProject(Document.FilePath, minFile); + } + } + + public override bool UseCompiledFolder + { + get { return WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder); } + } + + public override bool IsSaveFileEnabled + { + get { return WESettings.GetBoolean(WESettings.Keys.GenerateCssFileFromLess) && !Path.GetFileName(Document.FilePath).StartsWith("_"); } + } + + protected override bool CanWriteToDisk(string source) + { + //var parser = new Microsoft.CSS.Core.CssParser(); + //StyleSheet stylesheet = parser.Parse(source, false); + + return true;// !string.IsNullOrWhiteSpace(stylesheet.Text); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/LessProjectCompiler.cs b/EditorExtensions/Margin/LessProjectCompiler.cs new file mode 100644 index 000000000..cdcd99757 --- /dev/null +++ b/EditorExtensions/Margin/LessProjectCompiler.cs @@ -0,0 +1,116 @@ +using EnvDTE; +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + internal class LessProjectCompiler + { + public static void CompileProject(Project project) + { + if (project != null && !string.IsNullOrEmpty(project.FullName)) + { + Task.Run(() => Compile(project)); + } + } + + private static void Compile(Project project) + { + LessCompiler compiler = new LessCompiler(Completed); + + string dir = Path.GetDirectoryName(project.Properties.Item("FullPath").Value.ToString()); + var files = Directory.GetFiles(dir, "*.less", SearchOption.AllDirectories).Where(f => CanCompile(f)); + + foreach (string file in files) + { + compiler.Compile(file); + } + } + + private static bool CanCompile(string fileName) + { + if (EditorExtensionsPackage.DTE.Solution.FindProjectItem(fileName) == null) + return false; + + if (Path.GetFileName(fileName).StartsWith("_")) + return false; + + string minFile = MarginBase.GetCompiledFileName(fileName, ".min.css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder)); + if (File.Exists(minFile) && WESettings.GetBoolean(WESettings.Keys.LessMinify)) + return true; + + string cssFile = MarginBase.GetCompiledFileName(fileName, ".css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder)); + if (!File.Exists(cssFile)) + return false; + + + return true; + } + + private static void Completed(CompilerResult result) + { + if (result.IsSuccess) + { + string cssFileName = MarginBase.GetCompiledFileName(result.FileName, ".css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder));// result.FileName.Replace(".less", ".css"); + + if (File.Exists(cssFileName)) + { + string old = File.ReadAllText(cssFileName); + + if (old != result.Result) + { + ProjectHelpers.CheckOutFileFromSourceControl(cssFileName); + try + { + using (StreamWriter writer = new StreamWriter(cssFileName, false, new UTF8Encoding(true))) + { + writer.Write(result.Result); + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + } + + MinifyFile(result.FileName, result.Result); + } + else if (result.Error != null && !string.IsNullOrEmpty(result.Error.Message)) + { + Logger.Log(result.Error.Message); + } + else + { + Logger.Log("Error compiling LESS file: " + result.FileName); + } + } + + public static void MinifyFile(string lessFileName, string source) + { + if (WESettings.GetBoolean(WESettings.Keys.LessMinify)) + { + string content = MinifyFileMenu.MinifyString(".css", source); + string minFile = MarginBase.GetCompiledFileName(lessFileName, ".min.css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder)); //lessFileName.Replace(".less", ".min.css"); + string old = File.ReadAllText(minFile); + + if (old != content) + { + bool fileExist = File.Exists(minFile); + + ProjectHelpers.CheckOutFileFromSourceControl(minFile); + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + + if (!fileExist) + MarginBase.AddFileToProject(lessFileName, minFile); + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/MarginBase.cs b/EditorExtensions/Margin/MarginBase.cs new file mode 100644 index 000000000..7371d5ddc --- /dev/null +++ b/EditorExtensions/Margin/MarginBase.cs @@ -0,0 +1,448 @@ +using EnvDTE; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System; +using System.IO; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + public abstract class MarginBase : DockPanel, IWpfTextViewMargin + { + private bool _isDisposed = false; + private IWpfTextViewHost _viewHost; + private string _marginName; + protected string _settingsKey; + private bool _showMargin; + protected bool _isFirstRun = true; + private Dispatcher _dispatcher; + private ErrorListProvider _provider; + + public MarginBase() + { + _dispatcher = Dispatcher.CurrentDispatcher; + } + + public MarginBase(string source, string name, string contentType, bool showMargin, ITextDocument document) + { + Document = document; + _marginName = name; + _settingsKey = _marginName + "_width"; + _showMargin = showMargin; + _dispatcher = Dispatcher.CurrentDispatcher; + _provider = new ErrorListProvider(EditorExtensionsPackage.Instance); + + Document.FileActionOccurred += Document_FileActionOccurred; + + if (showMargin) + { + _dispatcher.BeginInvoke( + new Action(() => Initialize(contentType, source)), DispatcherPriority.ApplicationIdle, null); + } + } + + protected virtual void Document_FileActionOccurred(object sender, TextDocumentFileActionEventArgs e) + { + if (e.FileActionType == FileActionTypes.ContentSavedToDisk) + { + _dispatcher.BeginInvoke(new Action(() => + { + _provider.Tasks.Clear(); + StartCompiler(File.ReadAllText(e.FilePath)); + }), DispatcherPriority.ApplicationIdle, null); + } + } + + public abstract bool IsSaveFileEnabled { get; } + public abstract bool UseCompiledFolder { get; } + protected ITextDocument Document { get; set; } + + private void Initialize(string contentType, string source) + { + _viewHost = CreateTextViewHost(contentType); + CreateControls(_viewHost, source); + StartCompiler(source); + } + + private IWpfTextViewHost CreateTextViewHost(string contentType) + { + var componentModel = ProjectHelpers.GetComponentModel(); + var service = componentModel.GetService(); + var type = service.GetContentType(contentType); + + var textBufferFactory = componentModel.GetService(); + var textViewFactory = componentModel.GetService(); + + ITextBuffer textBuffer = textBufferFactory.CreateTextBuffer(string.Empty, type); + ITextViewRoleSet roles = textViewFactory.CreateTextViewRoleSet(PredefinedTextViewRoles.Interactive, PredefinedTextViewRoles.Document); + IWpfTextView textView = textViewFactory.CreateTextView(textBuffer, roles); + IWpfTextViewHost host = textViewFactory.CreateTextViewHost(textView, false); + + return host; + } + + protected virtual void CreateControls(IWpfTextViewHost host, string source) + { + int width; + + using (var key = EditorExtensionsPackage.Instance.UserRegistryRoot) + { + var raw = key.GetValue("WE_" + _settingsKey); + width = raw != null ? (int)raw : -1; + } + + width = width == -1 ? 400 : width; + + host.TextView.VisualElement.MinWidth = width; + host.TextView.VisualElement.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + host.TextView.Options.SetOptionValue(DefaultTextViewHostOptions.GlyphMarginId, false); + host.TextView.Options.SetOptionValue(DefaultTextViewHostOptions.LineNumberMarginId, true); + host.TextView.VisualElement.KeyDown += VisualElement_KeyUp; + + //host.GetTextViewMargin(PredefinedMarginNames.BottomControl).VisualElement.Height = 0; + + Grid grid = new Grid(); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Star) }); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(5, GridUnitType.Pixel) }); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) }); + grid.RowDefinitions.Add(new RowDefinition()); + + grid.Children.Add(host.HostControl); + this.Children.Add(grid); + + Grid.SetColumn(host.HostControl, 2); + Grid.SetRow(host.HostControl, 0); + + GridSplitter splitter = new GridSplitter(); + splitter.Width = 5; + splitter.ResizeDirection = GridResizeDirection.Columns; + splitter.VerticalAlignment = System.Windows.VerticalAlignment.Stretch; + splitter.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + splitter.DragCompleted += splitter_DragCompleted; + + grid.Children.Add(splitter); + Grid.SetColumn(splitter, 1); + Grid.SetRow(splitter, 0); + } + + void splitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) + { + //Settings.SetValue(_settingsKey, (int)_viewHost.HostControl.ActualWidth); + //Settings.Save(); + using (var key = EditorExtensionsPackage.Instance.UserRegistryRoot) + { + key.SetValue("WE_" + _settingsKey, (int)_viewHost.HostControl.ActualWidth); + } + } + + protected void VisualElement_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) + { + if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control) + Clipboard.SetText(_viewHost.TextView.TextBuffer.CurrentSnapshot.GetText(_viewHost.TextView.Selection.Start.Position.Position, _viewHost.TextView.Selection.End.Position.Position - _viewHost.TextView.Selection.Start.Position.Position)); + else if (e.Key == Key.PageDown) + _viewHost.TextView.ViewScroller.ScrollViewportVerticallyByPage(ScrollDirection.Down); + else if (e.Key == Key.PageUp) + _viewHost.TextView.ViewScroller.ScrollViewportVerticallyByPage(ScrollDirection.Up); + else if (e.Key == Key.Down) + _viewHost.TextView.ViewScroller.ScrollViewportVerticallyByLine(ScrollDirection.Down); + else if (e.Key == Key.Up) + _viewHost.TextView.ViewScroller.ScrollViewportVerticallyByLine(ScrollDirection.Up); + else if (e.Key == Key.Home) + _viewHost.TextView.ViewScroller.EnsureSpanVisible(new SnapshotSpan(_viewHost.TextView.TextBuffer.CurrentSnapshot, 0, 0)); + else if (e.Key == Key.End) + _viewHost.TextView.ViewScroller.EnsureSpanVisible(new SnapshotSpan(_viewHost.TextView.TextBuffer.CurrentSnapshot, _viewHost.TextView.TextBuffer.CurrentSnapshot.Length, 0)); + } + + public void SetText(string text) + { + if (!_showMargin) + return; + + if (!string.IsNullOrEmpty(text)) + { + int position = _viewHost.TextView.TextViewLines.FirstVisibleLine.Extent.Start.Position; + using (var edit = _viewHost.TextView.TextBuffer.CreateEdit()) + { + edit.Replace(new Span(0, _viewHost.TextView.TextBuffer.CurrentSnapshot.Length), text); + edit.Apply(); + } + + try + { + _viewHost.HostControl.Opacity = 1; + _viewHost.TextView.ViewScroller.ScrollViewportVerticallyByLines(ScrollDirection.Down, _viewHost.TextView.TextSnapshot.GetLineNumberFromPosition(position)); + _viewHost.TextView.ViewScroller.ScrollViewportHorizontallyByPixels(-9999); + } + catch + { + // Threading issues when called from TypeScript + } + } + else + { + _viewHost.HostControl.Opacity = 0.3; + } + } + + protected abstract void StartCompiler(string source); + + protected void OnCompilationDone(string result, string state) + { + bool isSuccess = !result.StartsWith("ERROR:"); + + _dispatcher.BeginInvoke(new Action(() => + { + if (isSuccess) + { + SetText(result); + + if (!_isFirstRun) + { + if (IsSaveFileEnabled) + WriteCompiledFile(result, state); + + MinifyFile(state, result); + } + } + else + { + result = result.Replace("ERROR:", string.Empty); + SetText("/*\r\n\r\nCompile Error. \r\nSee error list for details\r\n" + result + "\r\n\r\n*/"); + } + + _isFirstRun = false; + }), DispatcherPriority.Normal, null); + } + + public abstract void MinifyFile(string fileName, string source); + + protected void WriteCompiledFile(string content, string currentFileName) + { + string extension = Path.GetExtension(currentFileName); + string fileName = null; + + switch (extension.ToLowerInvariant()) + { + case ".less": + case ".scss": + fileName = GetCompiledFileName(currentFileName, ".css", UseCompiledFolder); + break; + + case ".coffee": + case ".ts": + fileName = GetCompiledFileName(currentFileName, ".js", UseCompiledFolder); + break; + + default: // For the Diff view + return; + } + + bool fileExist = File.Exists(fileName); + bool fileWritten = false; + + ProjectHelpers.CheckOutFileFromSourceControl(fileName); + fileWritten = WriteFile(content, fileName, fileExist, fileWritten); + + if (!fileExist && fileWritten) + { + AddFileToProject(currentFileName, fileName); + } + } + + public static string GetCompiledFileName(string sourceFileName, string compiledExtension, bool useFolder) + { + string sourceExtension = Path.GetExtension(sourceFileName); + string compiledFileName = Path.GetFileName(sourceFileName).Replace(sourceExtension, compiledExtension); + string sourceDir = Path.GetDirectoryName(sourceFileName); + + if (useFolder) + { + string compiledDir = Path.Combine(sourceDir, compiledExtension.Replace(".min.", string.Empty).Replace(".", string.Empty)); + + if (!Directory.Exists(compiledDir)) + { + Directory.CreateDirectory(compiledDir); + } + + return Path.Combine(compiledDir, compiledFileName); + } + + return Path.Combine(sourceDir, compiledFileName); + } + + public static void AddFileToProject(string parentFileName, string fileName) + { + if (!File.Exists(fileName)) + return; + + var item = EditorExtensionsPackage.DTE.Solution.FindProjectItem(parentFileName); + + if (item != null && item.ContainingProject != null && !string.IsNullOrEmpty(item.ContainingProject.FullName)) + { + if (item.ProjectItems != null && Path.GetDirectoryName(parentFileName) == Path.GetDirectoryName(fileName)) + { + // WAP + item.ProjectItems.AddFromFile(fileName); + } + else + { // Website + item.ContainingProject.ProjectItems.AddFromFile(fileName); + } + } + } + + private bool WriteFile(string content, string fileName, bool fileExist, bool fileWritten) + { + try + { + if (fileExist || (!fileExist && CanWriteToDisk(content))) + { + using (StreamWriter writer = new StreamWriter(fileName, false, new UTF8Encoding(true))) + { + writer.Write(content); + fileWritten = true; + } + } + } + catch (Exception ex) + { + var error = new CompilerError + { + FileName = Document.FilePath, + Column = 0, + Line = 0, + Message = "Could not write to " + Path.GetFileName(fileName) + }; + + CreateTask(error); + + Logger.Log(ex); + } + + return fileWritten; + } + + protected void CreateTask(CompilerError error) + { + ErrorTask task = new ErrorTask() + { + Line = error.Line, + Column = error.Column, + ErrorCategory = TaskErrorCategory.Error, + Category = TaskCategory.Html, + Document = error.FileName, + Priority = TaskPriority.Low, + Text = error.Message, + }; + + task.AddHierarchyItem(); + + task.Navigate += task_Navigate; + _provider.Tasks.Add(task); + } + + private void task_Navigate(object sender, EventArgs e) + { + Task task = sender as Task; + + _provider.Navigate(task, new Guid(EnvDTE.Constants.vsViewKindPrimary)); + + if (task.Column > 0) + { + var doc = (TextDocument)EditorExtensionsPackage.DTE.ActiveDocument.Object("textdocument"); + doc.Selection.MoveToLineAndOffset(task.Line, task.Column, false); + } + } + + protected abstract bool CanWriteToDisk(string source); + + private void ThrowIfDisposed() + { + if (_isDisposed) + throw new ObjectDisposedException("MarginBase"); + } + + #region IWpfTextViewMargin Members + + /// + /// The that implements the visual representation + /// of the margin. + /// + public System.Windows.FrameworkElement VisualElement + { + // Since this margin implements Canvas, this is the object which renders + // the margin. + get + { + ThrowIfDisposed(); + return this; + } + } + + #endregion + + #region ITextViewMargin Members + + public double MarginSize + { + // Since this is a horizontal margin, its width will be bound to the width of the text view. + // Therefore, its size is its height. + get + { + ThrowIfDisposed(); + return this.ActualHeight; + } + } + + public bool Enabled + { + // The margin should always be enabled + get + { + ThrowIfDisposed(); + return true; + } + } + + /// + /// Returns an instance of the margin if this is the margin that has been requested. + /// + /// The name of the margin requested + /// An instance of EditorMargin1 or null + public ITextViewMargin GetTextViewMargin(string marginName) + { + return (marginName == this._marginName) ? (IWpfTextViewMargin)this : null; + } + + public void Dispose() + { + GC.SuppressFinalize(this); + Dispose(_isDisposed); + } + + protected virtual void Dispose(bool isDisposed) + { + if (!_isDisposed) + { + _isDisposed = true; + + if (_viewHost != null) + { + _viewHost.Close(); + } + + Document.FileActionOccurred -= Document_FileActionOccurred; + _provider.Tasks.Clear(); + _provider.Dispose(); + } + } + #endregion + + } +} diff --git a/EditorExtensions/Margin/MarkdownMargin.cs b/EditorExtensions/Margin/MarkdownMargin.cs new file mode 100644 index 000000000..c5b304711 --- /dev/null +++ b/EditorExtensions/Margin/MarkdownMargin.cs @@ -0,0 +1,150 @@ +using EnvDTE; +using EnvDTE80; +using MarkdownSharp; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; + +namespace MadsKristensen.EditorExtensions +{ + internal class MarkdownMargin : MarginBase + { + public const string MarginName = "MarkdownMargin"; + private Markdown _compiler; + private WebBrowser _browser; + private const string _stylesheet = "WE-Markdown.css"; + + public MarkdownMargin(string contentType, string source, bool showMargin, ITextDocument document) + : base(source, MarginName, contentType, showMargin, document) + { + } + + private void InitializeCompiler() + { + if (_compiler == null) + { + MarkdownOptions options = new MarkdownOptions(); + options.AutoHyperlink = true; + + _compiler = new Markdown(options); + } + } + + protected override void StartCompiler(string source) + { + InitializeCompiler(); + + string result = _compiler.Transform(source); + + string html = "" + + GetStylesheet() + + "" + + "" + result + ""; + + _browser.NavigateToString(html); + } + + public static string GetStylesheet() + { + string folder = ProjectHelpers.GetSolutionFolderPath(); + + if (!string.IsNullOrEmpty(folder)) + { + string file = Path.Combine(folder, _stylesheet); + + if (File.Exists(file)) + { + string linkFormat = ""; + return string.Format(linkFormat, file); + } + } + + return string.Empty; + } + + public static void CreateStylesheet() + { + string file = Path.Combine(ProjectHelpers.GetSolutionFolderPath(), _stylesheet); + + using (StreamWriter writer = new StreamWriter(file, false, new UTF8Encoding(true))) + { + writer.Write("body { background: yellow; }"); + } + + Solution2 solution = EditorExtensionsPackage.DTE.Solution as Solution2; + Project project = solution.Projects + .OfType() + .FirstOrDefault(p => p.Name.Equals(Settings._solutionFolder, StringComparison.OrdinalIgnoreCase)); + + if (project == null) + { + project = solution.AddSolutionFolder(Settings._solutionFolder); + } + + project.ProjectItems.AddFromFile(file); + } + + protected override void CreateControls(IWpfTextViewHost host, string source) + { + int width = WESettings.GetInt(_settingsKey); + width = width == -1 ? 400 : width; + + _browser = new WebBrowser(); + _browser.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + + Grid grid = new Grid(); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Star) }); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(5, GridUnitType.Pixel) }); + grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(width) }); + grid.RowDefinitions.Add(new RowDefinition()); + + grid.Children.Add(_browser); + this.Children.Add(grid); + + Grid.SetColumn(_browser, 2); + Grid.SetRow(_browser, 0); + + GridSplitter splitter = new GridSplitter(); + splitter.Width = 5; + splitter.ResizeDirection = GridResizeDirection.Columns; + splitter.VerticalAlignment = System.Windows.VerticalAlignment.Stretch; + splitter.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch; + splitter.DragCompleted += splitter_DragCompleted; + + grid.Children.Add(splitter); + Grid.SetColumn(splitter, 1); + Grid.SetRow(splitter, 0); + } + + void splitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) + { + Settings.SetValue(_settingsKey, (int)this.ActualWidth); + Settings.Save(); + } + + public override void MinifyFile(string fileName, string source) + { + // Nothing to minify + } + + public override bool UseCompiledFolder + { + get { return false; } + } + + public override bool IsSaveFileEnabled + { + get { return false; } + } + + protected override bool CanWriteToDisk(string source) + { + return false; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/ScriptRunnerBase.cs b/EditorExtensions/Margin/ScriptRunnerBase.cs new file mode 100644 index 000000000..cfa9cea2d --- /dev/null +++ b/EditorExtensions/Margin/ScriptRunnerBase.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using System.Windows.Threading; + +[ComVisible(true)] +public abstract class ScriptRunnerBase : IDisposable +{ + private WebBrowser _browser = new WebBrowser(); + private bool _disposed; + private Dispatcher _dispatcher; + + public ScriptRunnerBase(Dispatcher dispatcher) + { + _dispatcher = dispatcher; + } + + protected abstract string CreateHtml(string source, string state); + + public void Compile(string source, string state) + { + _dispatcher.BeginInvoke(new Action(() => + { + _browser.ObjectForScripting = this; + _browser.ScriptErrorsSuppressed = true; + _browser.DocumentText = CreateHtml(source, state); + + }), DispatcherPriority.ApplicationIdle, null); + } + + public void Execute(string result, string state) + { + OnCompleted(result, state); + } + + protected static string ReadResourceFile(string resourceFile) + { + using (Stream s = typeof(JsHintCompiler).Assembly.GetManifestResourceStream(resourceFile)) + using (var reader = new StreamReader(s)) + { + return reader.ReadToEnd(); + } + } + + public event EventHandler Completed; + + protected void OnCompleted(string message, string data) + { + if (Completed != null) + { + Completed(this, new CompilerEventArgs() { Result = message, State = data }); + } + } + + public void Dispose() + { + if (!_disposed) + { + Completed = null; + + if (_browser != null) + { + _browser.Dispose(); + } + + _browser = null; + _disposed = true; + } + } +} + +public class CompilerEventArgs : EventArgs +{ + public string Result { get; set; } + public string State { get; set; } +} \ No newline at end of file diff --git a/EditorExtensions/Margin/ScssMargin.cs b/EditorExtensions/Margin/ScssMargin.cs new file mode 100644 index 000000000..e16c0fb69 --- /dev/null +++ b/EditorExtensions/Margin/ScssMargin.cs @@ -0,0 +1,158 @@ +//using EnvDTE; +//using Microsoft.CSS.Core; +//using Microsoft.VisualStudio.Text; +//using SassAndCoffee.Ruby.Sass; +//using System; +//using System.IO; +//using System.Linq; +//using System.Threading.Tasks; + +//namespace MadsKristensen.EditorExtensions +//{ +// /// +// /// A class detailing the margin's visual definition including both size and content. +// /// +// class ScssMargin : MarginBase +// { +// public const string MarginName = "ScssMargin"; +// private SassCompiler _compiler; + +// public ScssMargin() +// : base() +// { +// _compiler = new SassCompiler(); +// } + +// public ScssMargin(string contentType, string source, bool showMargin, ITextDocument document) +// : base(source, MarginName, contentType, showMargin, document) +// { +// _compiler = new SassCompiler(); +// } + +// public void CompileProject() +// { +// Project project = ProjectHelpers.GetActiveProject(); + +// if (project != null && !string.IsNullOrEmpty(project.FullName)) +// { +// Task.Run(() => +// { +// string dir = Path.GetDirectoryName(project.FullName); +// var files = Directory.GetFiles(dir, "*.scss", SearchOption.AllDirectories).Where(f => CanCompile(f)); + +// Parallel.ForEach(files, file => +// { +// EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Compiling " + Path.GetFileName(file); +// string result = CompileFile(file); +// base.WriteCompiledFile(result, file); +// this.MinifyFile(file, result); +// }); + +// EditorExtensionsPackage.DTE.StatusBar.Clear(); +// }); +// } +// } + +// private static bool CanCompile(string fileName) +// { +// if (EditorExtensionsPackage.DTE.Solution.FindProjectItem(fileName) == null) +// return false; + +// if (Path.GetFileName(fileName).StartsWith("_")) +// return false; + +// string minFile = MarginBase.GetCompiledFileName(fileName, ".min.css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder)); +// if (File.Exists(minFile) && WESettings.GetBoolean(WESettings.Keys.LessMinify)) +// return true; + +// string cssFile = MarginBase.GetCompiledFileName(fileName, ".css", WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder)); +// if (!File.Exists(cssFile)) +// return false; + + +// return true; +// } + + +// protected override void StartCompiler(string source) +// { +// string fileName = GetCompiledFileName(Document.FilePath, ".css", UseCompiledFolder); + +// if (_isFirstRun && File.Exists(fileName)) +// { +// OnCompilationDone(File.ReadAllText(fileName), Document.FilePath); +// return; +// } +// else if (!Path.GetFileName(Document.FilePath).StartsWith("_")) +// { +// Task.Run(() => +// { +// Compile(Document.FilePath); +// }); +// } +// } + +// private void Compile(string fileName) +// { +// EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Compiling " + Path.GetFileName(fileName); + +// string result = CompileFile(fileName); +// OnCompilationDone(result, Document.FilePath); + +// EditorExtensionsPackage.DTE.StatusBar.Clear(); +// } + +// private string CompileFile(string fileName) +// { +// try +// { +// string result = _compiler.Compile(fileName, false, null); + +// CssFormatter formatter = new CssFormatter(); +// result = formatter.Format(result); + +// return result; +// } +// catch (Exception ex) +// { +// return "ERROR: " + ex.Message; +// } +// } + +// public override void MinifyFile(string fileName, string source) +// { +// if (WESettings.GetBoolean(WESettings.Keys.ScssMinify)) +// { +// string content = MinifyFileMenu.MinifyString(".css", source); +// string minFile = GetCompiledFileName(fileName, ".min.css", UseCompiledFolder); +// bool fileExist = File.Exists(minFile); + +// ProjectHelpers.CheckOutFileFromSourceControl(minFile); +// File.WriteAllText(minFile, content); + +// if (!fileExist) +// AddFileToProject(Document.FilePath, minFile); +// } +// } + +// public override bool CanTakeFocus +// { +// get { return true; } +// } + +// public override bool IsSaveFileEnabled +// { +// get { return WESettings.GetBoolean(WESettings.Keys.GenerateCssFileFromScss) && !Path.GetFileName(Document.FilePath).StartsWith("_"); } +// } + +// public override bool UseCompiledFolder +// { +// get { return WESettings.GetBoolean(WESettings.Keys.ScssCompileToFolder); } +// } + +// protected override bool CanWriteToDisk(string source) +// { +// return !string.IsNullOrWhiteSpace(source); +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/Margin/TypeScriptMargin.cs b/EditorExtensions/Margin/TypeScriptMargin.cs new file mode 100644 index 000000000..6d3e4fc53 --- /dev/null +++ b/EditorExtensions/Margin/TypeScriptMargin.cs @@ -0,0 +1,314 @@ +using Microsoft.Ajax.Utilities; +using Microsoft.VisualStudio.Text; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions +{ + internal class TypeScriptMargin : MarginBase + { + public const string MarginName = "TypeScriptMargin"; + private string _executablePath; + + public TypeScriptMargin(string contentType, string source, bool showMargin, ITextDocument document) + : base(source, MarginName, contentType, showMargin, document) + { + _executablePath = GetExecutablePath(); + } + + public TypeScriptMargin() + : base() + { + _executablePath = GetExecutablePath(); + } + + public void CompileProjectFiles(EnvDTE.Project project) + { + try + { + if (!File.Exists(_executablePath) || string.IsNullOrEmpty(project.FullName)) + return; + + string fullPath = project.Properties.Item("FullPath").Value.ToString(); + + if (project != null && !string.IsNullOrEmpty(fullPath)) + { + string dir = Path.GetDirectoryName(fullPath); + var files = Directory.GetFiles(dir, "*.ts", SearchOption.AllDirectories); + + Parallel.ForEach(files, file => + { + if (!file.EndsWith(".d.ts") && EditorExtensionsPackage.DTE.Solution.FindProjectItem(file) != null) + { + StartProcess(file, CompileProjectExited); + } + }); + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + + private void CompileProjectExited(object sender, EventArgs e) + { + Process p = (Process)sender; + string file = p.StartInfo.EnvironmentVariables["file"]; + + p.Exited -= CompileProjectExited; + p.Dispose(); + + string js = file.Replace(".ts", ".js"); + + if (File.Exists(js)) + { + try + { + string content = File.ReadAllText(js); + MinifyFile(file, content); + ResaveWithBom(js, content); + Logger.Log("TypeScript: Compiling " + Path.GetFileName(file)); + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptAddGeneratedFilesToProject)) + { + AddFileToProject(file); + } + } + + private void ResaveWithBom(string fileName, string content) + { + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptResaveWithUtf8BOM)) + { + using (StreamWriter writer = new StreamWriter(fileName, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + } + } + + public override void MinifyFile(string fileName, string source) + { + if (!WESettings.GetBoolean(WESettings.Keys.TypeScriptMinify)) + return; + + try + { + string filePath = fileName.Replace(".ts", ".js"); + if (File.Exists(filePath)) + { + Minifier minifier = new Minifier(); + CodeSettings settings = new CodeSettings() { EvalTreatment = EvalTreatment.MakeImmediateSafe, PreserveImportantComments = false }; + + string content = minifier.MinifyJavaScript(source, settings); + string minFile = fileName.Replace(".ts", ".min.js"); + bool fileExist = File.Exists(minFile); + + using (StreamWriter writer = new StreamWriter(minFile, false, new UTF8Encoding(true))) + { + writer.Write(content); + } + + if (!fileExist && WESettings.GetBoolean(WESettings.Keys.TypeScriptAddGeneratedFilesToProject)) + AddFileToProject(fileName, minFile); + } + } + catch (Exception ex) + { + Logger.Log(ex); + } + } + + private static void AddFileToProject(string file) + { + string[] files = GetChildren(file); + + foreach (string generated in files) + { + if (EditorExtensionsPackage.DTE.Solution.FindProjectItem(generated) != null) + continue; + + if (File.Exists(generated)) + { + AddFileToProject(file, generated); + } + } + } + + private static string[] GetChildren(string file) + { + return new string[] { + file.Replace(".ts", ".js"), + file.Replace(".ts", ".min.js"), + file.Replace(".ts", ".js.map") + }; + } + + protected override void StartCompiler(string source) + { + string fileName = Document.FilePath.Replace(".ts", ".js"); + + if (_isFirstRun && File.Exists(fileName)) + { + OnCompilationDone(File.ReadAllText(fileName), Document.FilePath); + } + else if (!fileName.EndsWith(".d.ts") && WESettings.GetBoolean(WESettings.Keys.GenerateJsFileFromTypeScript)) + { + if (EditorExtensionsPackage.DTE.Solution.SolutionBuild.BuildState == EnvDTE.vsBuildState.vsBuildStateInProgress) + return; + + if (File.Exists(_executablePath)) + { + _isFirstRun = false; + System.Threading.Tasks.Task.Run(() => + { + StartProcess(Document.FilePath, CompilerExited); + }); + } + else + { + base.OnCompilationDone("ERROR: The TypeScript compiler couldn't be found. Download http://www.typescriptlang.org/#Download", Document.FilePath); + } + } + else + { + base.OnCompilationDone("// JavaScript generation is disabled in Tools -> Options", Document.FilePath); + } + } + + private static string GetExecutablePath() + { + string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string path = Path.Combine(programFiles, @"Microsoft SDKs\TypeScript\tsc.exe"); + + if (!File.Exists(path)) + { + path = Path.Combine(programFiles, @"Microsoft SDKs\TypeScript\0.8.1.1\tsc.exe"); + } + + if (!File.Exists(path)) + { + path = Path.Combine(programFiles, @"Microsoft SDKs\TypeScript\0.8.1.0\tsc.exe"); + } + + if (!File.Exists(path)) + { + path = Path.Combine(programFiles, @"Microsoft SDKs\TypeScript\0.8.0.0\tsc.exe"); + } + + return path; + } + + private void StartProcess(string file, EventHandler eventHandler) + { + CheckOutChildren(file); + + Logger.Log("Compiling TypeScript..."); + + ProcessStartInfo start = new ProcessStartInfo(); + start.WindowStyle = ProcessWindowStyle.Hidden; + start.CreateNoWindow = true; + start.Arguments = "\"" + file + "\"" + GenerateArguments(); + start.FileName = _executablePath; + start.UseShellExecute = false; + start.EnvironmentVariables.Add("file", file); + start.RedirectStandardError = true; + + Process p = new Process(); + p.StartInfo = start; + p.EnableRaisingEvents = true; + p.Exited += eventHandler; + + p.Start(); + } + + private static void CheckOutChildren(string file) + { + var files = GetChildren(file).Where(f => File.Exists(f)); + + foreach (string child in files) + { + ProjectHelpers.CheckOutFileFromSourceControl(child); + } + } + + private static string GenerateArguments() + { + string args = string.Empty; + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptUseAmdModule)) + args += " --module amd"; + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptCompileES3)) + args += " --target ES3"; + else + args += " --target ES5"; + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptProduceSourceMap)) + args += " -sourcemap"; + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptKeepComments)) + args += " -c"; + + return args; + + } + + private void CompilerExited(object sender, EventArgs e) + { + Process p = (Process)sender; + + if (p.ExitCode == 0) + { + string fileName = Document.FilePath.Replace(".ts", ".js"); + + if (File.Exists(fileName)) + { + string content = File.ReadAllText(fileName); + + ResaveWithBom(fileName, content); + + if (WESettings.GetBoolean(WESettings.Keys.TypeScriptAddGeneratedFilesToProject)) + { + AddFileToProject(Document.FilePath); + } + + Logger.Log("TypeScript: Compiling " + Path.GetFileName(fileName)); + base.OnCompilationDone(content, Document.FilePath); + } + } + else + { + base.OnCompilationDone("ERROR: " + p.StandardError.ReadToEnd(), Document.FilePath); + } + + p.Exited -= CompilerExited; + p.Dispose(); + } + + public override bool IsSaveFileEnabled + { + get { return false; } + } + + public override bool UseCompiledFolder + { + get { return false; } + } + + protected override bool CanWriteToDisk(string source) + { + return false; + } + } +} diff --git a/EditorExtensions/MenuItems/BuildMenu.cs b/EditorExtensions/MenuItems/BuildMenu.cs new file mode 100644 index 000000000..b36afb26f --- /dev/null +++ b/EditorExtensions/MenuItems/BuildMenu.cs @@ -0,0 +1,145 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using System; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.IO; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class BuildMenu + { + private static DTE2 _dte; + private OleMenuCommandService _mcs; + + public BuildMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID cmdBundles = new CommandID(GuidList.guidBuildCmdSet, (int)PkgCmdIDList.cmdBuildBundles); + OleMenuCommand menuBundles = new OleMenuCommand((s, e) => UpdateBundleFiles(), cmdBundles); + _mcs.AddCommand(menuBundles); + + CommandID cmdLess = new CommandID(GuidList.guidBuildCmdSet, (int)PkgCmdIDList.cmdBuildLess); + OleMenuCommand menuLess = new OleMenuCommand((s, e) => BuildLess(), cmdLess); + _mcs.AddCommand(menuLess); + + //CommandID cmdTS = new CommandID(GuidList.guidBuildCmdSet, (int)PkgCmdIDList.cmdBuildTypeScript); + //OleMenuCommand menuTS = new OleMenuCommand((s, e) => BuildTypeScript(), cmdTS); + //_mcs.AddCommand(menuTS); + + CommandID cmdMinify = new CommandID(GuidList.guidBuildCmdSet, (int)PkgCmdIDList.cmdBuildMinify); + OleMenuCommand menuMinify = new OleMenuCommand((s, e) => Minify(), cmdMinify); + _mcs.AddCommand(menuMinify); + + CommandID cmdCoffee = new CommandID(GuidList.guidBuildCmdSet, (int)PkgCmdIDList.cmdBuildCoffeeScript); + OleMenuCommand menuCoffee = new OleMenuCommand((s, e) => BuildCoffeeScript(), cmdCoffee); + _mcs.AddCommand(menuCoffee); + } + + private void BuildCoffeeScript() + { + foreach (Project project in _dte.Solution.Projects) + { + CoffeeScriptMargin margin = new CoffeeScriptMargin(); + margin.CompileProject(project); + } + } + + private void UpdateBundleFiles() + { + //Logger.Log("Updating bundles..."); + BundleFilesMenu.UpdateBundles(null, true); + //Logger.Log("Bundles updated"); + } + + private void BuildLess() + { + foreach (Project project in _dte.Solution.Projects) + { + LessProjectCompiler.CompileProject(project); + } + } + + //private void BuildTypeScript() + //{ + // foreach (Project project in _dte.Solution.Projects) + // { + // new TypeScriptMargin().CompileProjectFiles(project); + // } + //} + + private void Minify() + { + _dte.StatusBar.Text = "Web Essentials: Minifying files..."; + var files = GetFiles(); + + foreach (string path in files) + { + string extension = Path.GetExtension(path); + string minPath = MinifyFileMenu.GetMinFileName(path, extension); + + if (!path.EndsWith(".min" + extension) && File.Exists(minPath) && _dte.Solution.FindProjectItem(path) != null) + { + if (extension.Equals(".js", StringComparison.OrdinalIgnoreCase)) + { + JavaScriptSaveListener.Minify(path, minPath, false); + } + else + { + CssSaveListener.Minify(path, minPath); + } + } + } + + _dte.StatusBar.Text = "Web Essentials: Files minified"; + } + + private IEnumerable GetFiles() + { + //Project project = ProjectHelpers.GetActiveProject(); + + foreach (Project project in _dte.Solution.Projects) + { + if (string.IsNullOrEmpty(project.FullName)) + continue; + + string dir = Path.GetDirectoryName(project.FullName); + + List list = new List(); + list.AddRange(Directory.GetFiles(dir, "*.css", SearchOption.AllDirectories)); + list.AddRange(Directory.GetFiles(dir, "*.js", SearchOption.AllDirectories)); + + foreach (string file in list.Where(f => !f.Contains(".min."))) + { + string extension = Path.GetExtension(file); + + if (extension == ".css") + { + if (!File.Exists(file.Replace(".css", ".less")) && + !File.Exists(file.Replace(".css", ".scss")) && + !File.Exists(file + ".bundle")) + + yield return file; + } + if (extension == ".js") + { + if (!File.Exists(file.Replace(".js", ".coffee")) && + !File.Exists(file.Replace(".js", ".ts")) && + !File.Exists(file + ".bundle")) + + yield return file; + } + } + } + + yield break; + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/BundleFiles.cs b/EditorExtensions/MenuItems/BundleFiles.cs new file mode 100644 index 000000000..0ce185c0b --- /dev/null +++ b/EditorExtensions/MenuItems/BundleFiles.cs @@ -0,0 +1,400 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Design; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Threading; +using System.Xml; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IWpfTextViewCreationListener))] + [ContentType("CSS")] + [ContentType("JavaScript")] + [ContentType("XML")] + [TextViewRole(PredefinedTextViewRoles.Document)] + internal class BundleFilesMenu : IWpfTextViewCreationListener + { + private static DTE2 _dte; + private OleMenuCommandService _mcs; + public const string _ext = ".bundle"; + + public BundleFilesMenu() + { + // Used by the IWpfTextViewCreationListener + _dte = EditorExtensionsPackage.DTE; + } + + public BundleFilesMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void TextViewCreated(IWpfTextView textView) + { + ITextDocument document; + textView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document); + + if (document != null) + { + document.FileActionOccurred += document_FileActionOccurred; + } + } + + private void document_FileActionOccurred(object sender, TextDocumentFileActionEventArgs e) + { + if (e.FileActionType == FileActionTypes.ContentSavedToDisk) + { + string file = e.FilePath.EndsWith(_ext) ? null : e.FilePath; + + System.Threading.Tasks.Task.Run(() => + { + UpdateBundles(file, file == null); + }); + } + } + + public static void UpdateBundles(string changedFile, bool isBuild) + { + if (string.IsNullOrEmpty(changedFile)) + { + foreach (Project project in EditorExtensionsPackage.DTE.Solution.Projects) + { + if (project.ProjectItems.Count > 1) + { + UpdateBundle(project.ProjectItems.Item(project.ProjectItems.Count).FileNames[1], isBuild); + } + } + } + else + { + UpdateBundle(changedFile, isBuild); + } + } + + private static void UpdateBundle(string changedFile, bool isBuild) + { + string dir = ProjectHelpers.GetProjectFolder(changedFile); + + if (string.IsNullOrEmpty(dir)) + return; + + //if (dir.Contains(".")) + //{ + // dir = Path.GetDirectoryName(dir); + //} + + foreach (string file in Directory.GetFiles(dir, "*" + _ext, SearchOption.AllDirectories)) + { + if (file.IndexOf("\\app_data\\", StringComparison.OrdinalIgnoreCase) > -1) + continue; + + XmlDocument doc = GetXmlDocument(file); + bool enabled = false; + + if (doc != null) + { + XmlNode bundleNode = doc.SelectSingleNode("//bundle"); + if (bundleNode == null) + continue; + + XmlNodeList nodes = doc.SelectNodes("//file"); + foreach (XmlNode node in nodes) + { + string relative = node.InnerText; + string absolute = ProjectHelpers.ToAbsoluteFilePath(relative, dir).Replace("/", "\\").Replace("\\\\", "\\"); + + if (changedFile != null && absolute.Equals(changedFile.Replace("\\\\", "\\"), StringComparison.OrdinalIgnoreCase)) + { + enabled = true; + break; + } + } + + if (isBuild && bundleNode.Attributes["runOnBuild"] != null && bundleNode.Attributes["runOnBuild"].InnerText == "true") + { + enabled = true; + } + + if (enabled) + { + WriteBundleFile(file, doc); + } + } + } + } + + private static XmlDocument GetXmlDocument(string filePath) + { + try + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(File.ReadAllText(filePath)); + return doc; + } + catch (Exception ex) + { + Logger.Log(ex); + return null; + } + } + + public void SetupCommands() + { + CommandID commandCss = new CommandID(GuidList.guidBundleCmdSet, (int)PkgCmdIDList.BundleCss); + OleMenuCommand menuCommandCss = new OleMenuCommand((s, e) => CreateBundlefile(".css"), commandCss); + menuCommandCss.BeforeQueryStatus += (s, e) => { BeforeQueryStatus(s, ".css"); }; + _mcs.AddCommand(menuCommandCss); + + CommandID commandJs = new CommandID(GuidList.guidBundleCmdSet, (int)PkgCmdIDList.BundleJs); + OleMenuCommand menuCommandJs = new OleMenuCommand((s, e) => CreateBundlefile(".js"), commandJs); + menuCommandJs.BeforeQueryStatus += (s, e) => { BeforeQueryStatus(s, ".js"); }; + _mcs.AddCommand(menuCommandJs); + } + + private void BeforeQueryStatus(object sender, string extension) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + //_selectedItems = ProjectHelpers.GetSelectedItems().Where(p => Path.GetExtension(p.FileNames[1]) == extension); + + menuCommand.Enabled = GetSelectedItems(extension).Count() > 1; + } + + private IEnumerable GetSelectedItems(string extension) + { + return ProjectHelpers.GetSelectedItems().Where(p => Path.GetExtension(p.FileNames[1]) == extension); + } + + //private IEnumerable GetSelectedFilePaths(string extension) + //{ + // var raw = ProjectHelpers.GetSelectedItems().Where(p => Path.GetExtension(p.Properties.Item("FullPath").ToString()) == extension); + + // foreach (string file in raw) + // { + // //if (!file.EndsWith(".min" + extension)) + // //{ + // yield return file; + // //} + // } + //} + + private void CreateBundlefile(string extension) + { + //var selectedPaths = GetSelectedFilePaths(extension); + StringBuilder sb = new StringBuilder(); + string firstFile = null; + var items = GetSelectedItems(extension); + + foreach (ProjectItem item in items) + { + if (string.IsNullOrEmpty(firstFile)) + firstFile = item.FileNames[1]; + + string content = File.ReadAllText(item.FileNames[1]); + sb.AppendLine(content); + } + + if (firstFile != null) + { + string dir = Path.GetDirectoryName(firstFile); + + + dir = GetProjectRelativeFolder(items.ElementAt(0)); + + if (Directory.Exists(dir)) + { + string bundleFile = Microsoft.VisualBasic.Interaction.InputBox("Specify the name of the bundle", "Web Essentials", "bundle1"); + + if (!bundleFile.EndsWith(_ext, StringComparison.OrdinalIgnoreCase)) + bundleFile += extension + _ext; + + string bundlePath = Path.Combine(dir, bundleFile); + + if (File.Exists(bundlePath)) + { + MessageBox.Show("The file already exist", "Web Essentials", MessageBoxButton.OK, MessageBoxImage.Warning); + } + else + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => WriteFile(bundlePath, items, extension, bundleFile.Replace(_ext, string.Empty))), + DispatcherPriority.ApplicationIdle, null); + } + } + } + } + + private static string GetProjectRelativeFolder(ProjectItem item) + { + object parent = item.Collection.Parent; + ProjectItem folder = parent as ProjectItem; + Project project = parent as Project; + + if (folder != null) + { + return folder.FileNames[1]; + } + else if (project != null) + { + return project.FullName; + } + + return null; + } + + private void WriteFile(string filePath, IEnumerable files, string extension, string output) + { + string projectRoot = ProjectHelpers.GetProjectFolder(files.ElementAt(0).FileNames[1]); + StringBuilder sb = new StringBuilder(); + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + + using (XmlWriter writer = XmlWriter.Create(sb, settings)) + { + writer.WriteStartElement("bundle"); + writer.WriteAttributeString("minify", "true"); + writer.WriteAttributeString("runOnBuild", "true"); + writer.WriteAttributeString("output", output); + writer.WriteComment("The order of the elements determines the order of them when bundled."); + + foreach (ProjectItem item in files) + { + string relative = item.IsLink() ? item.FileNames[1] : "/" + FileHelpers.RelativePath(projectRoot, item.FileNames[1]); + writer.WriteElementString("file", relative); + } + + writer.WriteEndElement(); + } + + sb.Replace(Encoding.Unicode.WebName, Encoding.UTF8.WebName); + + ProjectHelpers.CheckOutFileFromSourceControl(filePath); + File.WriteAllText(filePath, sb.ToString()); + ProjectHelpers.AddFileToActiveProject(filePath, "None"); + + _dte.ItemOperations.OpenFile(filePath); + + XmlDocument doc = GetXmlDocument(filePath); + + if (doc != null) + { + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => WriteBundleFile(filePath, doc)), DispatcherPriority.ApplicationIdle, null); + } + } + + private static void WriteBundleFile(string filePath, XmlDocument doc) + { + XmlNode bundleNode = doc.SelectSingleNode("//bundle"); + + if (bundleNode == null) + return; + + XmlNode outputAttr = bundleNode.Attributes["output"]; + + if (outputAttr != null && (outputAttr.InnerText.Contains("/") || outputAttr.InnerText.Contains("\\"))) + { + MessageBox.Show("The 'output' attribute is for file names only - not paths", "Web Essentials"); + return; + } + + Dictionary files = new Dictionary(); + string extension = Path.GetExtension(filePath.Replace(_ext, string.Empty)); + XmlNodeList nodes = doc.SelectNodes("//file"); + + foreach (XmlNode node in nodes) + { + string absolute = ProjectHelpers.ToAbsoluteFilePath(node.InnerText, ProjectHelpers.GetProjectFolder(filePath)).Replace("\\\\", "\\"); + + if (node.InnerText.Contains(":\\") || node.InnerText.StartsWith("\\\\")) + { + absolute = node.InnerText; + } + + if (File.Exists(absolute)) + { + if (!files.ContainsKey(absolute)) + files.Add(absolute, node.InnerText); + } + else + { + string error = string.Format("Bundle error: The file '{0}' doesn't exist", node.InnerText); + _dte.ItemOperations.OpenFile(filePath); + MessageBox.Show(error, "Web Essentials"); + return; + } + } + + string bundlePath = outputAttr != null ? Path.Combine(Path.GetDirectoryName(filePath), outputAttr.InnerText) : filePath.Replace(_ext, string.Empty); + StringBuilder sb = new StringBuilder(); + + foreach (string file in files.Keys) + { + //if (extension.Equals(".css", StringComparison.OrdinalIgnoreCase)) + //{ + // sb.AppendLine("/*#source " + files[file] + " */"); + //} + if (extension.Equals(".js", StringComparison.OrdinalIgnoreCase) && WESettings.GetBoolean(WESettings.Keys.GenerateJavaScriptSourceMaps)) + { + sb.AppendLine("///#source 1 1 " + files[file]); + } + + sb.AppendLine(File.ReadAllText(file)); + } + + if (!File.Exists(bundlePath) || File.ReadAllText(bundlePath) != sb.ToString()) + { + ProjectHelpers.CheckOutFileFromSourceControl(bundlePath); + using (StreamWriter writer = new StreamWriter(bundlePath, false, new UTF8Encoding(true))) + { + writer.Write(sb.ToString()); + Logger.Log("Updating bundle: " + Path.GetFileName(bundlePath)); + } + MarginBase.AddFileToProject(filePath, bundlePath); + + if (bundleNode.Attributes["minify"] != null || bundleNode.Attributes["minify"].InnerText == "true") + { + WriteMinFile(filePath, bundlePath, sb.ToString(), extension); + } + } + } + + private static void WriteMinFile(string filePath, string bundlePath, string content, string extension) + { + string minPath = bundlePath.Replace(Path.GetExtension(bundlePath), ".min" + Path.GetExtension(bundlePath)); + + if (extension.Equals(".js", StringComparison.OrdinalIgnoreCase)) + { + JavaScriptSaveListener.Minify(bundlePath, minPath, true); + MarginBase.AddFileToProject(filePath, minPath); + + if (WESettings.GetBoolean(WESettings.Keys.GenerateJavaScriptSourceMaps)) + { + MarginBase.AddFileToProject(filePath, minPath + ".map"); + } + } + else if (extension.Equals(".css", StringComparison.OrdinalIgnoreCase)) + { + string minContent = MinifyFileMenu.MinifyString(extension, content); + + ProjectHelpers.CheckOutFileFromSourceControl(minPath); + + using (StreamWriter writer = new StreamWriter(minPath, false, new UTF8Encoding(true))) + { + writer.Write(minContent); + } + MarginBase.AddFileToProject(filePath, minPath); + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/Diff.cs b/EditorExtensions/MenuItems/Diff.cs new file mode 100644 index 000000000..038baa05f --- /dev/null +++ b/EditorExtensions/MenuItems/Diff.cs @@ -0,0 +1,66 @@ +using System.ComponentModel.Design; +using System.Linq; +using System.Text; +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Shell; +using System; +using System.Collections.Generic; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + internal class DiffMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public DiffMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandId = new CommandID(GuidList.guidDiffCmdSet, (int)PkgCmdIDList.cmdDiff); + OleMenuCommand menuCommand = new OleMenuCommand((s, e) => Sort(), commandId); + menuCommand.BeforeQueryStatus += menuCommand_BeforeQueryStatus; + _mcs.AddCommand(menuCommand); + } + + //private List list = new List() + //{ + // ".txt", ".cs", ".aspx", ".ascx", ".asmx", ".master", ".cshtml", ".vbhtml", ".js", ".coffee", ".css", ".less", ".sass", ".scss", ".xml" + //}; + + private List files; + + void menuCommand_BeforeQueryStatus(object sender, System.EventArgs e) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + files = new List(ProjectHelpers.GetSelectedItemPaths()); + + //if (files.Count == 2) + //{ + // if (list.Contains(Path.GetExtension(files[0]).ToLowerInvariant())) + // { + // if (list.Contains(Path.GetExtension(files[1]).ToLowerInvariant())) + // { + // menuCommand.Enabled = true; + // return; + // } + // } + //} + + menuCommand.Enabled = files.Count == 2; + } + + private void Sort() + { + if (files.Count == 2) + EditorExtensionsPackage.DTE.ExecuteCommand("Tools.DiffFiles \"" + files[0] + "\" \"" + files[1] + "\""); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/Encoding.cs b/EditorExtensions/MenuItems/Encoding.cs new file mode 100644 index 000000000..c3e58763e --- /dev/null +++ b/EditorExtensions/MenuItems/Encoding.cs @@ -0,0 +1,62 @@ +//using System; +//using System.ComponentModel.Design; +//using System.Web; +//using EnvDTE; +//using EnvDTE80; +//using Microsoft.VisualStudio.Shell; + +//namespace MadsKristensen.EditorExtensions +//{ +// internal class EncodingMenu +// { +// private DTE2 _dte; +// private OleMenuCommandService _mcs; +// private delegate string Replacement(string original); + +// public EncodingMenu(DTE2 dte, OleMenuCommandService mcs) +// { +// _dte = dte; +// _mcs = mcs; +// } + +// public void SetupCommands() +// { +// SetupCommand(PkgCmdIDList.htmlEncode, HttpUtility.HtmlEncode); +// SetupCommand(PkgCmdIDList.attrEncode, HttpUtility.HtmlAttributeEncode); +// SetupCommand(PkgCmdIDList.htmlDecode, HttpUtility.HtmlDecode); +// SetupCommand(PkgCmdIDList.urlEncode, HttpUtility.UrlEncode); +// SetupCommand(PkgCmdIDList.urlPathEncode, HttpUtility.UrlPathEncode); +// SetupCommand(PkgCmdIDList.urlDecode, HttpUtility.UrlDecode); +// SetupCommand(PkgCmdIDList.jsEncode, HttpUtility.JavaScriptStringEncode); +// } + +// private void SetupCommand(uint command, Replacement callback) +// { +// CommandID commandId = new CommandID(GuidList.guidEditorExtensionsCmdSet, (int)command); +// OleMenuCommand menuCommand = new OleMenuCommand((s, e) => Replace(callback), commandId); + +// menuCommand.BeforeQueryStatus += (s, e) => +// { +// string selection = GetTextDocument().Selection.Text; +// menuCommand.Enabled = selection.Length > 0 && callback(selection) != selection; +// }; + +// _mcs.AddCommand(menuCommand); +// } + +// private TextDocument GetTextDocument() +// { +// return _dte.ActiveDocument.Object("TextDocument") as TextDocument; +// } + +// private void Replace(Replacement callback) +// { +// TextDocument document = GetTextDocument(); +// string replacement = callback(document.Selection.Text); + +// _dte.UndoContext.Open(callback.Method.Name); +// document.Selection.Insert(replacement, 0); +// _dte.UndoContext.Close(); +// } +// } +//} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/JsHint.cs b/EditorExtensions/MenuItems/JsHint.cs new file mode 100644 index 000000000..9c9b6ec7a --- /dev/null +++ b/EditorExtensions/MenuItems/JsHint.cs @@ -0,0 +1,52 @@ +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.IO; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class JsHintMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public JsHintMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandId = new CommandID(GuidList.guidDiffCmdSet, (int)PkgCmdIDList.cmdJsHint); + OleMenuCommand menuCommand = new OleMenuCommand((s, e) => RunJsHint(), commandId); + menuCommand.BeforeQueryStatus += menuCommand_BeforeQueryStatus; + _mcs.AddCommand(menuCommand); + } + + private List files; + + void menuCommand_BeforeQueryStatus(object sender, System.EventArgs e) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + + var raw = MinifyFileMenu.GetSelectedFilePaths(_dte); + files = raw.Where(f => !JsHintRunner.ShouldIgnore(f)).ToList(); + + menuCommand.Enabled = files.Count > 0; + } + + private void RunJsHint() + { + JsHintRunner.Reset(); + + foreach (string file in files) + { + JsHintRunner runner = new JsHintRunner(file); + runner.RunCompiler(); + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/MarkdownStylesheet.cs b/EditorExtensions/MenuItems/MarkdownStylesheet.cs new file mode 100644 index 000000000..def2b71da --- /dev/null +++ b/EditorExtensions/MenuItems/MarkdownStylesheet.cs @@ -0,0 +1,45 @@ +using System.ComponentModel.Design; +using System.Linq; +using System.Text; +using EnvDTE; +using EnvDTE80; +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Shell; +using System; +using System.Collections.Generic; +using System.IO; + +namespace MadsKristensen.EditorExtensions +{ + internal class MarkdownStylesheetMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public MarkdownStylesheetMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandId = new CommandID(GuidList.guidDiffCmdSet, (int)PkgCmdIDList.cmdMarkdownStylesheet); + OleMenuCommand menuCommand = new OleMenuCommand((s, e) => AddStylesheet(), commandId); + menuCommand.BeforeQueryStatus += menuCommand_BeforeQueryStatus; + _mcs.AddCommand(menuCommand); + } + + void menuCommand_BeforeQueryStatus(object sender, System.EventArgs e) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + + menuCommand.Enabled = string.IsNullOrEmpty(MarkdownMargin.GetStylesheet()); + } + + private void AddStylesheet() + { + MarkdownMargin.CreateStylesheet(); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/MinifyFile.cs b/EditorExtensions/MenuItems/MinifyFile.cs new file mode 100644 index 000000000..036ee59fc --- /dev/null +++ b/EditorExtensions/MenuItems/MinifyFile.cs @@ -0,0 +1,224 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.Ajax.Utilities; +using Microsoft.VisualStudio.Shell; +using System; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.IO; +using System.Linq; +using System.Windows; + +namespace MadsKristensen.EditorExtensions +{ + internal class MinifyFileMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public MinifyFileMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandCss = new CommandID(GuidList.guidMinifyCmdSet, (int)PkgCmdIDList.MinifyCss); + OleMenuCommand menuCommandCss = new OleMenuCommand((s, e) => MinifyFile(".css"), commandCss); + menuCommandCss.BeforeQueryStatus += (s, e) => { BeforeQueryStatus(s, ".css"); }; + _mcs.AddCommand(menuCommandCss); + + CommandID commandJs = new CommandID(GuidList.guidMinifyCmdSet, (int)PkgCmdIDList.MinifyJs); + OleMenuCommand menuCommandJs = new OleMenuCommand((s, e) => MinifyFile(".js"), commandJs); + menuCommandJs.BeforeQueryStatus += (s, e) => { BeforeQueryStatus(s, ".js"); }; + _mcs.AddCommand(menuCommandJs); + + //CommandID commandSelection = new CommandID(GuidList.guidMinifyCmdSet, (int)PkgCmdIDList.MinifySelection); + //OleMenuCommand menuCommandSelection = new OleMenuCommand((s, e) => MinifySelection(), commandSelection); + //menuCommandSelection.BeforeQueryStatus += menuCommandSelection_BeforeQueryStatus; + //_mcs.AddCommand(menuCommandSelection); + } + + private readonly string[] _supported = new[] { "CSS", "JAVASCRIPT" }; + + //void menuCommandSelection_BeforeQueryStatus(object sender, EventArgs e) + //{ + // OleMenuCommand menu = sender as OleMenuCommand; + // var view = ProjectHelpers.GetCurentTextView(); + + // if (view != null && view.Selection.SelectedSpans.Count > 0) + // { + // menu.Enabled = view.Selection.SelectedSpans[0].Length > 0; + // } + // else + // { + // menu.Enabled = false; + // } + //} + + void BeforeQueryStatus(object sender, string extension) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + var selectedPaths = GetSelectedFilePaths(_dte).Where(p => Path.GetExtension(p) == extension); + bool enabled = false; + + foreach (string path in selectedPaths) + { + string minFile = GetMinFileName(path, extension); + + if (!path.EndsWith(".min" + extension) && !File.Exists(minFile)) + { + enabled = true; + break; + } + } + + menuCommand.Enabled = enabled; + } + + //private void MinifySelection() + //{ + // var view = ProjectHelpers.GetCurentTextView(); + + // if (view != null) + // { + // _dte.UndoContext.Open("Minify"); + + // string content = view.Selection.SelectedSpans[0].GetText(); + // string extension = Path.GetExtension(_dte.ActiveDocument.FullName).ToLowerInvariant(); + // string result = MinifyString(extension, content); + + // view.TextBuffer.Replace(view.Selection.SelectedSpans[0].Span, result); + + // _dte.UndoContext.Close(); + // } + //} + + private void MinifyFile(string extension) + { + var selectedPaths = GetSelectedFilePaths(_dte); + + foreach (string path in selectedPaths.Where(p => p.EndsWith(extension, StringComparison.OrdinalIgnoreCase))) + { + string minPath = GetMinFileName(path, extension); + + if (!path.EndsWith(".min" + extension) && !File.Exists(minPath) && _dte.Solution.FindProjectItem(path) != null) + { + if (extension.Equals(".js", StringComparison.OrdinalIgnoreCase)) + { + JavaScriptSaveListener.Minify(path, minPath, false); + } + else + { + CssSaveListener.Minify(path, minPath); + } + + MarginBase.AddFileToProject(path, minPath); + } + } + + EnableSync(extension); + } + + private void EnableSync(string extension) + { + string message = string.Format("Do you also want to enable automatic minification when the source file changes?", extension); + + if (extension.Equals(".css", StringComparison.OrdinalIgnoreCase) && !WESettings.GetBoolean(WESettings.Keys.EnableCssMinification)) + { + var result = MessageBox.Show(message, "Web Essentials", MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + Settings.SetValue(WESettings.Keys.EnableCssMinification, true); + Settings.Save(); + } + } + else if (extension.Equals(".js", StringComparison.OrdinalIgnoreCase) && !WESettings.GetBoolean(WESettings.Keys.EnableJsMinification)) + { + var result = MessageBox.Show(message, "Web Essentials", MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + Settings.SetValue(WESettings.Keys.EnableJsMinification, true); + Settings.Save(); + } + } + } + + public static string GetMinFileName(string path, string extension) + { + return path.Insert(path.Length - extension.Length, ".min"); + } + + public static string MinifyString(string extension, string content) + { + if (extension == ".css") + { + Minifier minifier = new Minifier(); + CssSettings settings = new CssSettings(); + settings.CommentMode = CssComment.None; + + if (WESettings.GetBoolean(WESettings.Keys.KeepImportantComments)) + { + settings.CommentMode = CssComment.Important; + } + + return minifier.MinifyStyleSheet(content, settings); + } + else if (extension == ".js") + { + Minifier minifier = new Minifier(); + CodeSettings settings = new CodeSettings() + { + EvalTreatment = EvalTreatment.MakeImmediateSafe, + PreserveImportantComments = WESettings.GetBoolean(WESettings.Keys.KeepImportantComments) + }; + + return minifier.MinifyJavaScript(content, settings); + } + + return null; + } + + public static IEnumerable GetSelectedFilePaths(DTE2 dte) + { + var selectedPaths = GetSelectedItemPaths(dte); + List list = new List(); + + foreach (string path in selectedPaths) + { + string extension = Path.GetExtension(path); + + if (!string.IsNullOrEmpty(extension)) + { + // file + list.Add(path); + } + else + { + // Folder + if (Directory.Exists(path)) + { + list.AddRange(Directory.GetFiles(path)); + } + } + } + + return list; + } + + private static IEnumerable GetSelectedItemPaths(DTE2 dte) + { + var items = (Array)dte.ToolWindows.SolutionExplorer.SelectedItems; + foreach (UIHierarchyItem selItem in items) + { + var item = selItem.Object as ProjectItem; + if (item != null) + { + yield return item.Properties.Item("FullPath").Value.ToString(); + } + } + } + + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/ProjectSettings.cs b/EditorExtensions/MenuItems/ProjectSettings.cs new file mode 100644 index 000000000..03fb1f5c7 --- /dev/null +++ b/EditorExtensions/MenuItems/ProjectSettings.cs @@ -0,0 +1,95 @@ +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using System.ComponentModel.Design; +using System.IO; +using System.Windows.Forms; + +namespace MadsKristensen.EditorExtensions +{ + internal class ProjectSettingsMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public ProjectSettingsMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandSol = new CommandID(GuidList.guidDiffCmdSet, (int)PkgCmdIDList.cmdSolutionSettings); + OleMenuCommand menuCommandSol = new OleMenuCommand((s, e) => ApplySolutionSettings(), commandSol); + menuCommandSol.BeforeQueryStatus += SolutionBeforeQueryStatus; + _mcs.AddCommand(menuCommandSol); + + ProjectItemsEvents projectEvents = ((Events2)_dte.Events).ProjectItemsEvents; + projectEvents.ItemRemoved += ItemRemoved; + projectEvents.ItemRenamed += ItemRenamed; + + SolutionEvents solutionEvents = ((Events2)_dte.Events).SolutionEvents; + solutionEvents.ProjectRemoved += ProjectRemoved; + } + + private void SolutionBeforeQueryStatus(object sender, System.EventArgs e) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + bool settingsExist = Settings.SolutionSettingsExist; + + menuCommand.Enabled = !settingsExist; + } + + private void ApplySolutionSettings() + { + Settings.CreateSolutionSettings(); + } + + private void ItemRenamed(ProjectItem ProjectItem, string OldName) + { + if (OldName.EndsWith(Settings._fileName) || ProjectItem.Name == Settings._fileName) + Settings.UpdateCache(); + } + + private void ItemRemoved(ProjectItem ProjectItem) + { + if (ProjectItem.Name == Settings._fileName && + ProjectItem.ContainingProject != null && + ProjectItem.ContainingProject.Name == Settings._solutionFolder) + { + DeleteSolutionSettings(); + } + } + + private void ProjectRemoved(Project project) + { + if (project.Name == Settings._solutionFolder) + { + DeleteSolutionSettings(); + } + } + + private static void DeleteSolutionSettings() + { + string file = Settings.GetSolutionFilePath(); + + if (File.Exists(file)) + { + string text = "The Web Essentials setting file still exist in the solution folder.\r\n\r\nDo you want to delete it?"; + DialogResult result = MessageBox.Show(text, "Web Essentials", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + File.Delete(file); + Settings.UpdateCache(); + Settings.UpdateStatusBar("applied"); + } + else + { + Settings.UpdateStatusBar("still applies. The settings file still exist in the solution folder."); + } + } + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/SolutionColors.cs b/EditorExtensions/MenuItems/SolutionColors.cs new file mode 100644 index 000000000..769bbbc19 --- /dev/null +++ b/EditorExtensions/MenuItems/SolutionColors.cs @@ -0,0 +1,39 @@ +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using System.ComponentModel.Design; + +namespace MadsKristensen.EditorExtensions +{ + internal class SolutionColorsMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + + public SolutionColorsMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + CommandID commandSol = new CommandID(GuidList.guidDiffCmdSet, (int)PkgCmdIDList.cmdSolutionColors); + OleMenuCommand menuCommandSol = new OleMenuCommand((s, e) => ApplySolutionSettings(), commandSol); + menuCommandSol.BeforeQueryStatus += SolutionBeforeQueryStatus; + _mcs.AddCommand(menuCommandSol); + } + + private void SolutionBeforeQueryStatus(object sender, System.EventArgs e) + { + OleMenuCommand menuCommand = sender as OleMenuCommand; + bool settingsExist = XmlColorPaletteProvider.SolutionColorsExist; + + menuCommand.Enabled = !settingsExist; + } + + private void ApplySolutionSettings() + { + XmlColorPaletteProvider.CreateSolutionColors(); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/MenuItems/Transform.cs b/EditorExtensions/MenuItems/Transform.cs new file mode 100644 index 000000000..3212ce1f9 --- /dev/null +++ b/EditorExtensions/MenuItems/Transform.cs @@ -0,0 +1,99 @@ +using System; +using System.Security.Cryptography; +using System.Linq; +using System.ComponentModel.Design; +using System.Web; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using System.Globalization; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class TransformMenu + { + private DTE2 _dte; + private OleMenuCommandService _mcs; + private delegate string Replacement(string original); + + public TransformMenu(DTE2 dte, OleMenuCommandService mcs) + { + _dte = dte; + _mcs = mcs; + } + + public void SetupCommands() + { + SetupCommand(PkgCmdIDList.upperCaseTransform, new Replacement(x => x.ToUpperInvariant())); + SetupCommand(PkgCmdIDList.lowerCaseTransform, new Replacement(x => x.ToLowerInvariant())); + SetupCommand(PkgCmdIDList.titleCaseTransform, new Replacement(x => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(x))); + SetupCommand(PkgCmdIDList.reverseTransform, new Replacement(x => new string(x.Reverse().ToArray()))); + SetupCommand(PkgCmdIDList.normalizeTransform, new Replacement(x => RemoveDiacritics(x))); + SetupCommand(PkgCmdIDList.md5Transform, new Replacement(x => Hash(x, new MD5CryptoServiceProvider()))); + SetupCommand(PkgCmdIDList.sha1Transform, new Replacement(x => Hash(x, new SHA1CryptoServiceProvider()))); + SetupCommand(PkgCmdIDList.sha256Transform, new Replacement(x => Hash(x, new SHA256CryptoServiceProvider()))); + SetupCommand(PkgCmdIDList.sha384Transform, new Replacement(x => Hash(x, new SHA384CryptoServiceProvider()))); + SetupCommand(PkgCmdIDList.sha512Transform, new Replacement(x => Hash(x, new SHA512CryptoServiceProvider()))); + } + + public static string RemoveDiacritics(string s) + { + string stFormD = s.Normalize(NormalizationForm.FormD); + StringBuilder sb = new StringBuilder(); + + for (int ich = 0; ich < stFormD.Length; ich++) + { + UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); + if (uc != UnicodeCategory.NonSpacingMark) + { + sb.Append(stFormD[ich]); + } + } + + return (sb.ToString().Normalize(NormalizationForm.FormC)); + } + + private static string Hash(string original, HashAlgorithm algorithm) + { + byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(original)); + StringBuilder sb = new StringBuilder(); + + foreach (byte b in hash) + { + sb.Append(b.ToString("x2").ToLowerInvariant()); + } + + return sb.ToString(); + } + + private void SetupCommand(uint command, Replacement callback) + { + CommandID commandId = new CommandID(GuidList.guidEditorExtensionsCmdSet, (int)command); + OleMenuCommand menuCommand = new OleMenuCommand((s, e) => Replace(callback), commandId); + + menuCommand.BeforeQueryStatus += (s, e) => + { + string selection = GetTextDocument().Selection.Text; + menuCommand.Enabled = selection.Length > 0 && callback(selection) != selection; + }; + + _mcs.AddCommand(menuCommand); + } + + private TextDocument GetTextDocument() + { + return _dte.ActiveDocument.Object("TextDocument") as TextDocument; + } + + private void Replace(Replacement callback) + { + TextDocument document = GetTextDocument(); + string replacement = callback(document.Selection.Text); + + _dte.UndoContext.Open(callback.Method.Name); + document.Selection.Insert(replacement, 0); + _dte.UndoContext.Close(); + } + } +} \ No newline at end of file diff --git a/EditorExtensions/NavigateTo/GoToLineProviderFactory.cs b/EditorExtensions/NavigateTo/GoToLineProviderFactory.cs new file mode 100644 index 000000000..006d903dd --- /dev/null +++ b/EditorExtensions/NavigateTo/GoToLineProviderFactory.cs @@ -0,0 +1,189 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; +using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Text.Outlining; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(INavigateToItemProviderFactory))] + internal sealed class GoToLineProviderFactory : INavigateToItemProviderFactory, INavigateToItemDisplayFactory + { + [Import] + internal IEditorOperationsFactoryService EditorOperationsFactoryService = null; + + [Import] + internal IOutliningManagerService OutliningManagerService = null; + + public bool TryCreateNavigateToItemProvider(IServiceProvider serviceProvider, out INavigateToItemProvider provider) + { + provider = new GoToLineProvider(this); + return true; + } + + public INavigateToItemDisplay CreateItemDisplay(NavigateToItem item) + { + return item.Tag as INavigateToItemDisplay; + } + } + + internal sealed class GoToLineProvider : DisposableObject, INavigateToItemProvider + { + private readonly GoToLineProviderFactory _owner; + + public GoToLineProvider(GoToLineProviderFactory owner) + { + _owner = owner; + } + + public void StartSearch(INavigateToCallback callback, string searchValue) + { + CssParser parser = new CssParser(); + var state = new Tuple(parser, searchValue, callback); + + System.Threading.ThreadPool.QueueUserWorkItem(DoWork, state); + } + + public void DoWork(object state) + { + var tuple = (Tuple)state; + var parser = tuple.Item1; + var searchValue = tuple.Item2; + var callback = tuple.Item3; + + try + { + IEnumerable files = GetFiles(); + + Parallel.For(0, files.Count(), i => + { + string file = files.ElementAt(i); + + IEnumerable items = GetItems(file, parser, searchValue); + + foreach (ParseItem sel in items) + { + callback.AddItem(new NavigateToItem(searchValue, NavigateToItemKind.Field, null, searchValue, new GoToLineTag(sel, file), MatchKind.Exact, _owner)); + } + + callback.ReportProgress(i, files.Count()); + }); + } + catch { } + finally + { + callback.Done(); + } + } + + public void StopSearch() + { + } + + private IEnumerable GetItems(string file, CssParser parser, string searchValue) + { + StyleSheet ss = parser.Parse(File.ReadAllText(file), true); + + var visitorClass = new CssItemCollector(true); + ss.Accept(visitorClass); + + var classes = from c in visitorClass.Items + where c.Text.Contains(searchValue) + select c; + + var visitorIDs = new CssItemCollector(true); + ss.Accept(visitorIDs); + + var ids = from c in visitorIDs.Items + where c.Text.Contains(searchValue) + select c; + + List list = new List(); + list.AddRange(classes); + list.AddRange(ids); + + return list; + } + + private IEnumerable GetFiles() + { + string[] files = Directory.GetFiles(ProjectHelpers.GetRootFolder(), "*.css", SearchOption.AllDirectories); + + foreach (string file in files) + { + if (!file.Contains(".min.") && !file.Contains(".bundle.")) + yield return file; + } + } + } + + internal class GoToLineTag : INavigateToItemDisplay + { + private ParseItem _selector; + private string _file; + + public GoToLineTag(ParseItem selector, string file) + { + _selector = selector; + _file = file; + } + + public string AdditionalInformation + { + get + { + return "CSS selector - " + Path.GetFileName(_file); + } + } + + public string Description + { + get + { + return _selector.Text; + } + } + + public System.Collections.ObjectModel.ReadOnlyCollection DescriptionItems + { + get { return null; } + } + + public System.Drawing.Icon Glyph + { + get { return null; } + } + + public string Name + { + get { return _selector.FindType().Text; } + } + + public void NavigateTo() + { + EditorExtensionsPackage.DTE.ItemOperations.OpenFile(_file); + + Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => + { + var view = ProjectHelpers.GetCurentTextView(); + var textBuffer = ProjectHelpers.GetCurentTextBuffer(); + var span = new SnapshotSpan(textBuffer.CurrentSnapshot, _selector.Start, _selector.Length); + var point = new SnapshotPoint(textBuffer.CurrentSnapshot, _selector.Start + _selector.Length); + + view.ViewScroller.EnsureSpanVisible(span); + view.Caret.MoveTo(point); + view.Selection.Select(span, false); + + + }), DispatcherPriority.ApplicationIdle, null); + } + } +} diff --git a/EditorExtensions/Options/CoffeeScript.cs b/EditorExtensions/Options/CoffeeScript.cs new file mode 100644 index 000000000..1974c3575 --- /dev/null +++ b/EditorExtensions/Options/CoffeeScript.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class CoffeeScriptOptions : DialogPage + { + public CoffeeScriptOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.GenerateJsFileFromCoffeeScript, GenerateJsFileFromCoffeeScript); + Settings.SetValue(WESettings.Keys.ShowCoffeeScriptPreviewWindow, ShowCoffeeScriptPreviewWindow); + Settings.SetValue(WESettings.Keys.WrapCoffeeScriptClosure, WrapCoffeeScriptClosure); + Settings.SetValue(WESettings.Keys.CoffeeScriptMinify, CoffeeScriptMinify); + Settings.SetValue(WESettings.Keys.EnableIcedCoffeeScript, EnableIcedCoffeeScript); + Settings.SetValue(WESettings.Keys.CoffeeScriptCompileToFolder, CoffeeScriptCompileToFolder); + Settings.SetValue(WESettings.Keys.CoffeeScriptCompileOnBuild, CoffeeScriptCompileOnBuild); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + GenerateJsFileFromCoffeeScript = WESettings.GetBoolean(WESettings.Keys.GenerateJsFileFromCoffeeScript); + ShowCoffeeScriptPreviewWindow = WESettings.GetBoolean(WESettings.Keys.ShowCoffeeScriptPreviewWindow); + WrapCoffeeScriptClosure = WESettings.GetBoolean(WESettings.Keys.WrapCoffeeScriptClosure); + CoffeeScriptMinify = WESettings.GetBoolean(WESettings.Keys.CoffeeScriptMinify); + EnableIcedCoffeeScript = WESettings.GetBoolean(WESettings.Keys.EnableIcedCoffeeScript); + CoffeeScriptCompileToFolder = WESettings.GetBoolean(WESettings.Keys.CoffeeScriptCompileToFolder); + CoffeeScriptCompileOnBuild = WESettings.GetBoolean(WESettings.Keys.CoffeeScriptCompileOnBuild); + } + + [LocDisplayName("Generate JavaScript file on save")] + [Description("Generate JavaScript file when CoffeeScript file is saved")] + [Category("CoffeeScript")] + public bool GenerateJsFileFromCoffeeScript { get; set; } + + [LocDisplayName("Show preview window")] + [Description("Show the preview window when editing a CoffeeScript file.")] + [Category("CoffeeScript")] + public bool ShowCoffeeScriptPreviewWindow { get; set; } + + [LocDisplayName("Wrap generated JavaScript")] + [Description("Wrap the generated JavaScript in an anonymous function.")] + [Category("CoffeeScript")] + public bool WrapCoffeeScriptClosure { get; set; } + + [LocDisplayName("Enable Iced CoffeeScript")] + [Description("Switches to use the Iced CoffeeScript compiler.")] + [Category("CoffeeScript")] + public bool EnableIcedCoffeeScript { get; set; } + + [LocDisplayName("Minify generated JavaScript")] + [Description("Creates a minified version of the compiled JavaScript file (file.min.js)")] + [Category("CoffeeScript")] + public bool CoffeeScriptMinify { get; set; } + + [LocDisplayName("Compile to 'js' folder")] + [Description("Compiles all CoffeeScript files into a folder called 'js' in the same directory as the .coffee file")] + [Category("CoffeeScript")] + public bool CoffeeScriptCompileToFolder { get; set; } + + [LocDisplayName("Compile on build")] + [Description("Compiles all CoffeeScript files in the project that has a corresponding .js file.")] + [Category("CoffeeScript")] + public bool CoffeeScriptCompileOnBuild { get; set; } + } +} diff --git a/EditorExtensions/Options/Css.cs b/EditorExtensions/Options/Css.cs new file mode 100644 index 000000000..eaa25b74e --- /dev/null +++ b/EditorExtensions/Options/Css.cs @@ -0,0 +1,135 @@ +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class CssOptions : DialogPage + { + public CssOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.EnableCssSelectorHighligting, EnableCssSelectorHighligting); + Settings.SetValue(WESettings.Keys.AutoCloseCurlyBraces, AutoCloseCurlyBraces); + Settings.SetValue(WESettings.Keys.EnableCssMinification, EnableCssMinification); + Settings.SetValue(WESettings.Keys.ValidateStarSelector, ValidateStarSelector); + Settings.SetValue(WESettings.Keys.ValidateOverQualifiedSelector, ValidateOverQualifiedSelector); + Settings.SetValue(WESettings.Keys.CssErrorLocation, (int)CssErrorLocation); + Settings.SetValue(WESettings.Keys.OnlyW3cAllowed, OnlyW3cAllowed); + Settings.SetValue(WESettings.Keys.SyncVendorValues, SyncVendorValues); + Settings.SetValue(WESettings.Keys.ShowInitialInherit, ShowInitialInherit); + Settings.SetValue(WESettings.Keys.ShowUnsupported, ShowUnsupported); + Settings.SetValue(WESettings.Keys.ShowBrowserTooltip, ShowBrowserTooltip); + Settings.SetValue(WESettings.Keys.ValidateZeroUnit, ValidateZeroUnit); + Settings.SetValue(WESettings.Keys.ValidateVendorSpecifics, ValidateVendorSpecifics); + Settings.SetValue(WESettings.Keys.EnableSpeedTyping, EnableSpeedTyping); + + OnChanged(); + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + EnableCssSelectorHighligting = WESettings.GetBoolean(WESettings.Keys.EnableCssSelectorHighligting); + AutoCloseCurlyBraces = WESettings.GetBoolean(WESettings.Keys.AutoCloseCurlyBraces); + EnableCssMinification = WESettings.GetBoolean(WESettings.Keys.EnableCssMinification); + ValidateStarSelector = WESettings.GetBoolean(WESettings.Keys.ValidateStarSelector); + ValidateOverQualifiedSelector = WESettings.GetBoolean(WESettings.Keys.ValidateOverQualifiedSelector); + CssErrorLocation = (WESettings.Keys.ErrorLocation)WESettings.GetInt(WESettings.Keys.CssErrorLocation); + OnlyW3cAllowed = WESettings.GetBoolean(WESettings.Keys.OnlyW3cAllowed); + SyncVendorValues = WESettings.GetBoolean(WESettings.Keys.SyncVendorValues); + ShowInitialInherit = WESettings.GetBoolean(WESettings.Keys.ShowInitialInherit); + ShowUnsupported = WESettings.GetBoolean(WESettings.Keys.ShowUnsupported); + ValidateEmbedImages = WESettings.GetBoolean(WESettings.Keys.ValidateEmbedImages); + ShowBrowserTooltip = WESettings.GetBoolean(WESettings.Keys.ShowBrowserTooltip); + ValidateZeroUnit = WESettings.GetBoolean(WESettings.Keys.ValidateZeroUnit); + ValidateVendorSpecifics = WESettings.GetBoolean(WESettings.Keys.ValidateVendorSpecifics); + EnableSpeedTyping = WESettings.GetBoolean(WESettings.Keys.EnableSpeedTyping); + } + + protected void OnChanged() + { + CssSchemaManager.SchemaManager.ReloadSchemas(); + } + + [LocDisplayName("Enable selector highlighting")] + [Description("Highlight matching simple selectors when cursor position changes")] + [Category("Misc")] + public bool EnableCssSelectorHighligting { get; set; } + + [LocDisplayName("Auto-close curly braces")] + [Description("when a open curly brace is typed, the closing curly is inserted automatically and type-through is enabled.")] + [Category("Misc")] + public bool AutoCloseCurlyBraces { get; set; } + + [LocDisplayName("Minify CSS files on save")] + [Description("When a .css file (foo.css) is saved and a minified version (foo.min.css) exist, the minified file will be updated. Right-click any .css file to generate .min.css file")] + [Category("Misc")] + public bool EnableCssMinification { get; set; } + + [LocDisplayName("Enable Speed Typing")] + [Description("Speed Typing makes it easier to write CSS by eliminating the need for typing curlies, colons and semi-colons.")] + [Category("Misc")] + public bool EnableSpeedTyping { get; set; } + + [LocDisplayName("Disallow universal selector")] + [Description("Disallow the universal, also known as the star selector")] + [Category("Performance")] + public bool ValidateStarSelector { get; set; } + + [LocDisplayName("Disallow over qualified ID selector")] + [Description("Disallow the use of over qualifed ID selectors.")] + [Category("Performance")] + public bool ValidateOverQualifiedSelector { get; set; } + + [LocDisplayName("Small images should be inlined")] + [Description("Small images should be base64 encoded and embedded directly into the stylesheet as dataURIs.")] + [Category("Performance")] + public bool ValidateEmbedImages { get; set; } + + [LocDisplayName("Validation location")] + [Description("Controls where errors are located. To use the 'Errors' output window, select 'Warnings' and change the Visual Studio CSS settings to use 'Errors'")] + [Category("Validation")] + public WESettings.Keys.ErrorLocation CssErrorLocation { get; set; } + + [LocDisplayName("Only allow W3C values")] + [Description("Ensures that the stylesheet only uses properties, @-directives, pseudos and values defined by the W3C.")] + [Category("Validation")] + public bool OnlyW3cAllowed { get; set; } + + [LocDisplayName("Validate vendor specifics")] + [Description("Validates vendor specific properties, psuedos and @-directives.")] + [Category("Validation")] + public bool ValidateVendorSpecifics { get; set; } + + [LocDisplayName("Sync vendor specific values")] + [Description("Syncronizes vendor specific property values when the standard property is being modified")] + [Category("Intellisense")] + public bool SyncVendorValues { get; set; } + + [LocDisplayName("Show initial/inherit")] + [Description("Shows or hides the global property values 'initial' and 'inherit'. They are still valid to use.")] + [Category("Intellisense")] + public bool ShowInitialInherit { get; set; } + + [LocDisplayName("Show unsupported")] + [Description("Shows the property names, values and pseudos that aren't supported by any browser yet.")] + [Category("Intellisense")] + public bool ShowUnsupported { get; set; } + + [LocDisplayName("Show browser support")] + [Description("Shows the browser support when the mouse is hovering over any CSS property.")] + [Category("Intellisense")] + public bool ShowBrowserTooltip { get; set; } + + [LocDisplayName("Disallow units for 0 values")] + [Description("The value of 0 works without specifying units in all situations where numbers with units or percentages are allowed")] + [Category("Performance")] + public bool ValidateZeroUnit { get; set; } + } +} \ No newline at end of file diff --git a/EditorExtensions/Options/General.cs b/EditorExtensions/Options/General.cs new file mode 100644 index 000000000..738588d4d --- /dev/null +++ b/EditorExtensions/Options/General.cs @@ -0,0 +1,45 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class GeneralOptions : DialogPage + { + public GeneralOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.EnableMustache, EnableMustache); + Settings.SetValue(WESettings.Keys.EnableHtmlZenCoding, EnableHtmlZenCoding); + Settings.SetValue(WESettings.Keys.KeepImportantComments, KeepImportantComments); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + EnableMustache = WESettings.GetBoolean(WESettings.Keys.EnableMustache); + EnableHtmlZenCoding = WESettings.GetBoolean(WESettings.Keys.EnableHtmlZenCoding); + KeepImportantComments = WESettings.GetBoolean(WESettings.Keys.KeepImportantComments); + } + + // MISC + [LocDisplayName("Enable Mustache/Handlebars")] + [Description("Enable colorization Mustache/Handlebars syntax in the HTML editor")] + [Category("Misc")] + public bool EnableMustache { get; set; } + + [LocDisplayName("Enable HTML ZenCoding")] + [Description("Enables ZenCoding in the HTML editor")] + [Category("Misc")] + public bool EnableHtmlZenCoding { get; set; } + + [LocDisplayName("Keep important comments")] + [Description("Don't strip important comments when minifying JS and CSS. Important comments follows this pattern: /*! text */")] + [Category("Minification")] + public bool KeepImportantComments { get; set; } + } +} diff --git a/EditorExtensions/Options/JavaScript.cs b/EditorExtensions/Options/JavaScript.cs new file mode 100644 index 000000000..f2c61f47b --- /dev/null +++ b/EditorExtensions/Options/JavaScript.cs @@ -0,0 +1,59 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class JavaScriptOptions : DialogPage + { + public JavaScriptOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.EnableJavascriptRegions, EnableJavascriptRegions); + Settings.SetValue(WESettings.Keys.EnableJsMinification, EnableJsMinification); + Settings.SetValue(WESettings.Keys.GenerateJavaScriptSourceMaps, GenerateJavaScriptSourceMaps); + Settings.SetValue(WESettings.Keys.JavaScriptAutoCloseBraces, JavaScriptAutoCloseBraces); + Settings.SetValue(WESettings.Keys.JavaScriptOutlining, JavaScriptOutlining); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + EnableJavascriptRegions = WESettings.GetBoolean(WESettings.Keys.EnableJavascriptRegions); + EnableJsMinification = WESettings.GetBoolean(WESettings.Keys.EnableJsMinification); + GenerateJavaScriptSourceMaps = WESettings.GetBoolean(WESettings.Keys.GenerateJavaScriptSourceMaps); + JavaScriptAutoCloseBraces = WESettings.GetBoolean(WESettings.Keys.JavaScriptAutoCloseBraces); + JavaScriptOutlining = WESettings.GetBoolean(WESettings.Keys.JavaScriptOutlining); + } + + + [LocDisplayName("Enable JavaScript regions")] + [Description("Enable regions using this syntax: '//#region Name' followed by '//#endregion'")] + [Category("JavaScript")] + public bool EnableJavascriptRegions { get; set; } + + [LocDisplayName("Minify JavaScript files on save")] + [Description("When a .js file (foo.js) is saved and a minified version (foo.min.js) exist, the minified file will be updated. Right-click any .js file to generate .min.js file")] + [Category("JavaScript")] + public bool EnableJsMinification { get; set; } + + [LocDisplayName("Generate source maps (.map)")] + [Description("When minification is enabled, a source map file (*.min.js.map) is generated.")] + [Category("JavaScript")] + public bool GenerateJavaScriptSourceMaps { get; set; } + + [LocDisplayName("Auto-close braces")] + [Description("Automatically inserts closing braces as provisional text. Braces are: ], ) and }")] + [Category("JavaScript")] + public bool JavaScriptAutoCloseBraces { get; set; } + + [LocDisplayName("Enable outlining/folding")] + [Description("Enables outlining for any non-function structures. Enabling can collide with other extensions.")] + [Category("JavaScript")] + public bool JavaScriptOutlining { get; set; } + } +} diff --git a/EditorExtensions/Options/JsHint.cs b/EditorExtensions/Options/JsHint.cs new file mode 100644 index 000000000..edad031f2 --- /dev/null +++ b/EditorExtensions/Options/JsHint.cs @@ -0,0 +1,466 @@ +using Microsoft.VisualStudio.Shell; +using System; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class JsHintOptions : DialogPage + { + public JsHintOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.JsHint_maxerr, JsHint_maxerr); + Settings.SetValue(WESettings.Keys.RunJsHintOnBuild, RunJsHintOnBuild); + Settings.SetValue(WESettings.Keys.EnableJsHint, EnableJsHint); + Settings.SetValue(WESettings.Keys.JsHintErrorLocation, (int)ErrorLocation); + + Settings.SetValue(WESettings.Keys.JsHint_bitwise, JsHint_bitwise); + Settings.SetValue(WESettings.Keys.JsHint_camelcase, JsHint_camelcase); + Settings.SetValue(WESettings.Keys.JsHint_curly, JsHint_curly); + Settings.SetValue(WESettings.Keys.JsHint_eqeqeq, JsHint_eqeqeq); + Settings.SetValue(WESettings.Keys.JsHint_forin, JsHint_forin); + Settings.SetValue(WESettings.Keys.JsHint_immed, JsHint_immed); + Settings.SetValue(WESettings.Keys.JsHint_indent, JsHint_indent); + Settings.SetValue(WESettings.Keys.JsHint_latedef, JsHint_latedef); + Settings.SetValue(WESettings.Keys.JsHint_newcap, JsHint_newcap); + Settings.SetValue(WESettings.Keys.JsHint_noarg, JsHint_noarg); + Settings.SetValue(WESettings.Keys.JsHint_noempty, JsHint_noempty); + Settings.SetValue(WESettings.Keys.JsHint_nonew, JsHint_nonew); + Settings.SetValue(WESettings.Keys.JsHint_plusplus, JsHint_plusplus); + Settings.SetValue(WESettings.Keys.JsHint_quotmark, JsHint_quotmark); + Settings.SetValue(WESettings.Keys.JsHint_regexp, JsHint_regexp); + Settings.SetValue(WESettings.Keys.JsHint_undef, JsHint_undef); + Settings.SetValue(WESettings.Keys.JsHint_unused, JsHint_unused); + Settings.SetValue(WESettings.Keys.JsHint_strict, JsHint_strict); + Settings.SetValue(WESettings.Keys.JsHint_trailing, JsHint_trailing); + + Settings.SetValue(WESettings.Keys.JsHint_asi, JsHint_asi); + Settings.SetValue(WESettings.Keys.JsHint_boss, JsHint_boss); + Settings.SetValue(WESettings.Keys.JsHint_debug, JsHint_debug); + Settings.SetValue(WESettings.Keys.JsHint_eqnull, JsHint_eqnull); + Settings.SetValue(WESettings.Keys.JsHint_es5, JsHint_es5); + Settings.SetValue(WESettings.Keys.JsHint_esnext, JsHint_esnext); + Settings.SetValue(WESettings.Keys.JsHint_evil, JsHint_evil); + Settings.SetValue(WESettings.Keys.JsHint_expr, JsHint_expr); + Settings.SetValue(WESettings.Keys.JsHint_funcscope, JsHint_funcscope); + Settings.SetValue(WESettings.Keys.JsHint_globalstrict, JsHint_globalstrict); + Settings.SetValue(WESettings.Keys.JsHint_iterator, JsHint_iterator); + Settings.SetValue(WESettings.Keys.JsHint_lastsemic, JsHint_lastsemic); + Settings.SetValue(WESettings.Keys.JsHint_laxbreak, JsHint_laxbreak); + Settings.SetValue(WESettings.Keys.JsHint_laxcomma, JsHint_laxcomma); + Settings.SetValue(WESettings.Keys.JsHint_loopfunc, JsHint_loopfunc); + Settings.SetValue(WESettings.Keys.JsHint_multistr, JsHint_multistr); + Settings.SetValue(WESettings.Keys.JsHint_onecase, JsHint_onecase); + Settings.SetValue(WESettings.Keys.JsHint_proto, JsHint_proto); + Settings.SetValue(WESettings.Keys.JsHint_regexdash, JsHint_regexdash); + Settings.SetValue(WESettings.Keys.JsHint_scripturl, JsHint_scripturl); + Settings.SetValue(WESettings.Keys.JsHint_smarttabs, JsHint_smarttabs); + Settings.SetValue(WESettings.Keys.JsHint_shadow, JsHint_shadow); + Settings.SetValue(WESettings.Keys.JsHint_sub, JsHint_sub); + Settings.SetValue(WESettings.Keys.JsHint_supernew, JsHint_supernew); + Settings.SetValue(WESettings.Keys.JsHint_validthis, JsHint_validthis); + + Settings.SetValue(WESettings.Keys.JsHint_browser, JsHint_browser); + Settings.SetValue(WESettings.Keys.JsHint_couch, JsHint_couch); + Settings.SetValue(WESettings.Keys.JsHint_devel, JsHint_devel); + Settings.SetValue(WESettings.Keys.JsHint_dojo, JsHint_dojo); + Settings.SetValue(WESettings.Keys.JsHint_mootools, JsHint_mootools); + Settings.SetValue(WESettings.Keys.JsHint_node, JsHint_node); + Settings.SetValue(WESettings.Keys.JsHint_nonstandard, JsHint_nonstandard); + Settings.SetValue(WESettings.Keys.JsHint_prototypejs, JsHint_prototypejs); + Settings.SetValue(WESettings.Keys.JsHint_rhino, JsHint_rhino); + Settings.SetValue(WESettings.Keys.JsHint_worker, JsHint_worker); + Settings.SetValue(WESettings.Keys.JsHint_wsh, JsHint_wsh); + + OnChanged(); + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + EnableJsHint = WESettings.GetBoolean(WESettings.Keys.EnableJsHint); + RunJsHintOnBuild = WESettings.GetBoolean(WESettings.Keys.RunJsHintOnBuild); + ErrorLocation = (WESettings.Keys.FullErrorLocation)WESettings.GetInt(WESettings.Keys.JsHintErrorLocation); + JsHint_maxerr = WESettings.GetInt(WESettings.Keys.JsHint_maxerr); + + JsHint_bitwise = WESettings.GetBoolean(WESettings.Keys.JsHint_bitwise); + JsHint_camelcase = WESettings.GetBoolean(WESettings.Keys.JsHint_camelcase); + JsHint_curly = WESettings.GetBoolean(WESettings.Keys.JsHint_curly); + JsHint_eqeqeq = WESettings.GetBoolean(WESettings.Keys.JsHint_eqeqeq); + JsHint_forin = WESettings.GetBoolean(WESettings.Keys.JsHint_forin); + JsHint_immed = WESettings.GetBoolean(WESettings.Keys.JsHint_immed); + JsHint_indent = WESettings.GetInt(WESettings.Keys.JsHint_indent); + JsHint_latedef = WESettings.GetBoolean(WESettings.Keys.JsHint_latedef); + JsHint_newcap = WESettings.GetBoolean(WESettings.Keys.JsHint_newcap); + JsHint_noarg = WESettings.GetBoolean(WESettings.Keys.JsHint_noarg); + JsHint_noempty = WESettings.GetBoolean(WESettings.Keys.JsHint_noempty); + JsHint_nonew = WESettings.GetBoolean(WESettings.Keys.JsHint_nonew); + JsHint_plusplus = WESettings.GetBoolean(WESettings.Keys.JsHint_plusplus); + JsHint_quotmark = WESettings.GetBoolean(WESettings.Keys.JsHint_quotmark); + JsHint_regexp = WESettings.GetBoolean(WESettings.Keys.JsHint_regexp); + JsHint_undef = WESettings.GetBoolean(WESettings.Keys.JsHint_undef); + JsHint_unused = WESettings.GetBoolean(WESettings.Keys.JsHint_unused); + JsHint_strict = WESettings.GetBoolean(WESettings.Keys.JsHint_strict); + JsHint_trailing = WESettings.GetBoolean(WESettings.Keys.JsHint_trailing); + + JsHint_asi = WESettings.GetBoolean(WESettings.Keys.JsHint_asi); + JsHint_boss = WESettings.GetBoolean(WESettings.Keys.JsHint_boss); + JsHint_debug = WESettings.GetBoolean(WESettings.Keys.JsHint_debug); + JsHint_eqnull = WESettings.GetBoolean(WESettings.Keys.JsHint_eqnull); + JsHint_es5 = WESettings.GetBoolean(WESettings.Keys.JsHint_es5); + JsHint_esnext = WESettings.GetBoolean(WESettings.Keys.JsHint_esnext); + JsHint_evil = WESettings.GetBoolean(WESettings.Keys.JsHint_evil); + JsHint_expr = WESettings.GetBoolean(WESettings.Keys.JsHint_expr); + JsHint_funcscope = WESettings.GetBoolean(WESettings.Keys.JsHint_funcscope); + JsHint_globalstrict = WESettings.GetBoolean(WESettings.Keys.JsHint_globalstrict); + JsHint_iterator = WESettings.GetBoolean(WESettings.Keys.JsHint_iterator); + JsHint_lastsemic = WESettings.GetBoolean(WESettings.Keys.JsHint_lastsemic); + JsHint_laxbreak = WESettings.GetBoolean(WESettings.Keys.JsHint_laxbreak); + JsHint_laxcomma = WESettings.GetBoolean(WESettings.Keys.JsHint_laxcomma); + JsHint_loopfunc = WESettings.GetBoolean(WESettings.Keys.JsHint_loopfunc); + JsHint_multistr = WESettings.GetBoolean(WESettings.Keys.JsHint_multistr); + JsHint_onecase = WESettings.GetBoolean(WESettings.Keys.JsHint_onecase); + JsHint_proto = WESettings.GetBoolean(WESettings.Keys.JsHint_proto); + JsHint_regexdash = WESettings.GetBoolean(WESettings.Keys.JsHint_regexdash); + JsHint_scripturl = WESettings.GetBoolean(WESettings.Keys.JsHint_scripturl); + JsHint_smarttabs = WESettings.GetBoolean(WESettings.Keys.JsHint_smarttabs); + JsHint_shadow = WESettings.GetBoolean(WESettings.Keys.JsHint_shadow); + JsHint_sub = WESettings.GetBoolean(WESettings.Keys.JsHint_sub); + JsHint_supernew = WESettings.GetBoolean(WESettings.Keys.JsHint_supernew); + JsHint_validthis = WESettings.GetBoolean(WESettings.Keys.JsHint_validthis); + + JsHint_browser = WESettings.GetBoolean(WESettings.Keys.JsHint_browser); + JsHint_couch = WESettings.GetBoolean(WESettings.Keys.JsHint_couch); + JsHint_devel = WESettings.GetBoolean(WESettings.Keys.JsHint_devel); + JsHint_dojo = WESettings.GetBoolean(WESettings.Keys.JsHint_dojo); + JsHint_jquery = WESettings.GetBoolean(WESettings.Keys.JsHint_jquery); + JsHint_mootools = WESettings.GetBoolean(WESettings.Keys.JsHint_mootools); + JsHint_node = WESettings.GetBoolean(WESettings.Keys.JsHint_node); + JsHint_nonstandard = WESettings.GetBoolean(WESettings.Keys.JsHint_nonstandard); + JsHint_prototypejs = WESettings.GetBoolean(WESettings.Keys.JsHint_prototypejs); + JsHint_rhino = WESettings.GetBoolean(WESettings.Keys.JsHint_rhino); + JsHint_worker = WESettings.GetBoolean(WESettings.Keys.JsHint_worker); + JsHint_wsh = WESettings.GetBoolean(WESettings.Keys.JsHint_wsh); + } + + public static event EventHandler Changed; + + protected void OnChanged() + { + if (Changed != null) + { + Changed(this, EventArgs.Empty); + } + } + + [LocDisplayName("Maximum number of errors")] + [Description("This option suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only.")] + [Category("Common")] + public int JsHint_maxerr { get; set; } + + [LocDisplayName("Enable JSHint")] + [Description("Runs JSHint in any open .js file when saved.")] + [Category("Common")] + public bool EnableJsHint { get; set; } + + [LocDisplayName("Run on build")] + [Description("Runs JSHint on all .js files in the active project on build")] + [Category("Common")] + public bool RunJsHintOnBuild { get; set; } + + [LocDisplayName("Error location")] + [Description("Determins where to output the JSHint errors")] + [Category("Common")] + public WESettings.Keys.FullErrorLocation ErrorLocation { get; set; } + + // Enforcing Options + + [LocDisplayName("Disallow bitwise operators")] + [Description("[bitwise] This option prohibits the use of bitwise operators such as ^ (XOR), | (OR) and others. Bitwise operators are very rare in JavaScript programs and very often & is simply a mistyped &&&&.")] + [Category("Enforcing Options")] + public bool JsHint_bitwise { get; set; } + + [LocDisplayName("Require camelcasing")] + [Description("[camelcase] This option allows you to force all variable names to use either camelCase style or UPPER_CASE with underscores.")] + [Category("Enforcing Options")] + public bool JsHint_camelcase { get; set; } + + [LocDisplayName("Enforce curly braces")] + [Description("[curly] This option requires you to always put curly braces around blocks in loops and conditionals. JavaScript allows you to omit curly braces when the block consists of only one statement.")] + [Category("Enforcing Options")] + public bool JsHint_curly { get; set; } + + [LocDisplayName("Disallow == and !=")] + [Description("[eqeqeq] This options prohibits the use of == and != in favor of === and !==.")] + [Category("Enforcing Options")] + public bool JsHint_eqeqeq { get; set; } + + [LocDisplayName("Filter for-in loops")] + [Description("[forin] This option requires all for in loops to filter object's items.")] + [Category("Enforcing Options")] + public bool JsHint_forin { get; set; } + + [LocDisplayName("Enforce invocation parentheses")] + [Description("[immed] This option prohibits the use of immediate function invocations without wrapping them in parentheses.")] + [Category("Enforcing Options")] + public bool JsHint_immed { get; set; } + + [LocDisplayName("Enforce indent size (-1 to disable)")] + [Description("[indent] This option enforces specific tab width for your code.")] + [Category("Enforcing Options")] + public int JsHint_indent { get; set; } + + [LocDisplayName("Declare param before use")] + [Description("[latedef] This option prohibits the use of a variable before it was defined.")] + [Category("Enforcing Options")] + public bool JsHint_latedef { get; set; } + + [LocDisplayName("Capitalize constructor functions")] + [Description("[newcap] This option requires you to capitalize names of constructor functions.")] + [Category("Enforcing Options")] + public bool JsHint_newcap { get; set; } + + [LocDisplayName("Disallow arguments.caller/callee")] + [Description("[noarg] This option prohibits the use of arguments.caller and arguments.callee.")] + [Category("Enforcing Options")] + public bool JsHint_noarg { get; set; } + + [LocDisplayName("No empty code blocks")] + [Description("[noempty] This option warns when you have an empty block in your code.")] + [Category("Enforcing Options")] + public bool JsHint_noempty { get; set; } + + [LocDisplayName("Disallow constructor functions")] + [Description("[nonew] This option prohibits the use of constructor functions for side-effects.")] + [Category("Enforcing Options")] + public bool JsHint_nonew { get; set; } + + [LocDisplayName("Disallow ++ and -- operators")] + [Description("[plusplus] This option prohibits the use of unary increment and decrement operators.")] + [Category("Enforcing Options")] + public bool JsHint_plusplus { get; set; } + + [LocDisplayName("Use consistant quotation")] + [Description("[quotmark] This option enforces the consistency of quotation marks used throughout your code.")] + [Category("Enforcing Options")] + public bool JsHint_quotmark { get; set; } + + [LocDisplayName("Disallow . in regex")] + [Description("[regexp] This option prohibits the use of unsafe . in regular expressions.")] + [Category("Enforcing Options")] + public bool JsHint_regexp { get; set; } + + [LocDisplayName("Disallow use of undeclared var")] + [Description("[undef] This option prohibits the use of explicitly undeclared variables. This option is very useful for spotting leaking and mistyped variables.")] + [Category("Enforcing Options")] + public bool JsHint_undef { get; set; } + + [LocDisplayName("Disallow unused variables")] + [Description("[unused] This option warns when you define and never use your variables. It is very useful for general code cleanup, especially when used in addition to undef.")] + [Category("Enforcing Options")] + public bool JsHint_unused { get; set; } + + [LocDisplayName("Require 'strict mode'")] + [Description("[strict] This option requires all functions to run in EcmaScript 5's strict mode.")] + [Category("Enforcing Options")] + public bool JsHint_strict { get; set; } + + [LocDisplayName("Disallow trailing whitespace")] + [Description("[trailing] This option makes it an error to leave a trailing whitespace in your code. Trailing whitespaces can be source of nasty bugs with multi-line strings.")] + [Category("Enforcing Options")] + public bool JsHint_trailing { get; set; } + + // Relaxing Options + + [LocDisplayName("Allow missing semicolons")] + [Description("[asi] This option suppresses warnings about missing semicolons.")] + [Category("Relaxing Options")] + public bool JsHint_asi { get; set; } + + [LocDisplayName("Allow assignments")] + [Description("[boss] This option suppresses warnings about the use of assignments in cases where comparisons are expected.")] + [Category("Relaxing Options")] + public bool JsHint_boss { get; set; } + + [LocDisplayName("Allow debugger statements")] + [Description("[debug] This option suppresses warnings about the debugger statements in your code.")] + [Category("Relaxing Options")] + public bool JsHint_debug { get; set; } + + [LocDisplayName("Allow == null")] + [Description("[eqnull] This option suppresses warnings about == null comparisons.")] + [Category("Relaxing Options")] + public bool JsHint_eqnull { get; set; } + + [LocDisplayName("Use EcmaScript 5")] + [Description("[es5] This option tells JSHint that your code uses ECMAScript 5 specific features such as getters and setters.")] + [Category("Relaxing Options")] + public bool JsHint_es5 { get; set; } + + [LocDisplayName("Allow ES.next features")] + [Description("[esnext] This option tells JSHint that your code uses ES.next specific features such as const.")] + [Category("Relaxing Options")] + public bool JsHint_esnext { get; set; } + + [LocDisplayName("Allow 'eval'")] + [Description("[evil] This option suppresses warnings about the use of eval.")] + [Category("Relaxing Options")] + public bool JsHint_evil { get; set; } + + [LocDisplayName("Allow expressions")] + [Description("[expr] This option suppresses warnings about the use of expressions where normally you would expect to see assignments or function calls.")] + [Category("Relaxing Options")] + public bool JsHint_expr { get; set; } + + [LocDisplayName("Allow variable scoping mismatch")] + [Description("[funcscope] This option suppresses warnings about declaring variables inside of control structures while accessing them later from the outside.")] + [Category("Relaxing Options")] + public bool JsHint_funcscope { get; set; } + + [LocDisplayName("Allow global strict mode")] + [Description("[globalstrict] This option suppresses warnings about the use of global strict mode.")] + [Category("Relaxing Options")] + public bool JsHint_globalstrict { get; set; } + + [LocDisplayName("Allow '__iterator__'")] + [Description("[iterator] This option suppresses warnings about the __iterator__ property.")] + [Category("Relaxing Options")] + public bool JsHint_iterator { get; set; } + + [LocDisplayName("Allow omitting last semicolon")] + [Description("[lastsemic] This option suppresses warnings about missing semicolons, but only when the semicolon is omitted for the last statement in a one-line block.")] + [Category("Relaxing Options")] + public bool JsHint_lastsemic { get; set; } + + [LocDisplayName("Allow unsafe line breaks")] + [Description("[laxbreak] This option suppresses most of the warnings about possibly unsafe line breakings in your code. It doesn't suppress warnings about comma-first coding style.")] + [Category("Relaxing Options")] + public bool JsHint_laxbreak { get; set; } + + [LocDisplayName("Allow comma first")] + [Description("[laxcomma] This option suppresses warnings about comma-first coding style.")] + [Category("Relaxing Options")] + public bool JsHint_laxcomma { get; set; } + + [LocDisplayName("Allow functions inside loops")] + [Description("[loopfunc] This option suppresses warnings about functions inside of loops.")] + [Category("Relaxing Options")] + public bool JsHint_loopfunc { get; set; } + + [LocDisplayName("Allow multiline strings")] + [Description("[multistr] This option suppresses warnings about multi-line strings. Multi-line strings can be dangerous in JavaScript because all hell breaks loose if you accidentally put a whitespace in between the escape character (\\) and a new line.")] + [Category("Relaxing Options")] + public bool JsHint_multistr { get; set; } + + [LocDisplayName("Allow on-case switches")] + [Description("[onecase] This option suppresses warnings about switches with just one case.")] + [Category("Relaxing Options")] + public bool JsHint_onecase { get; set; } + + [LocDisplayName("Allow '__proto__'")] + [Description("[proto] This option suppresses warnings about the __proto__ property. This property is deprecated and not supported by all browsers.")] + [Category("Relaxing Options")] + public bool JsHint_proto { get; set; } + + [LocDisplayName("Allow unescaped '-' in regex")] + [Description("[regexdash] This option suppresses warnings about unescaped - in the end of regular expressions.")] + [Category("Relaxing Options")] + public bool JsHint_regexdash { get; set; } + + [LocDisplayName("Allow 'javascript:' URLs")] + [Description("[scripturl] This option suppresses warnings about the use of script-targeted URLs—such as javascript:")] + [Category("Relaxing Options")] + public bool JsHint_scripturl { get; set; } + + [LocDisplayName("Allow mixed tabs/spaces")] + [Description("[smarttabs] This option suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only.")] + [Category("Relaxing Options")] + public bool JsHint_smarttabs { get; set; } + + [LocDisplayName("Allow variable shadowing")] + [Description("[shadow] This option suppresses warnings about variable shadowing i.e. declaring a variable that had been already declared somewhere in the outer scope.")] + [Category("Relaxing Options")] + public bool JsHint_shadow { get; set; } + + [LocDisplayName("Allow object['member']")] + [Description("[sub] This option suppresses warnings about using [] notation when it can be expressed in dot notation: person['name'] vs. person.name.")] + [Category("Relaxing Options")] + public bool JsHint_sub { get; set; } + + [LocDisplayName("Allow weird constructions")] + [Description("[supernew] This option suppresses warnings about 'weird' constructions like new function () { ... } and new Object;.")] + [Category("Relaxing Options")] + public bool JsHint_supernew { get; set; } + + [LocDisplayName("Allow strict mode violations")] + [Description("[validthis] This option suppresses warnings about possible strict violations when the code is running in strict mode and you use this in a non-constructor function.")] + [Category("Relaxing Options")] + public bool JsHint_validthis { get; set; } + + // Environment + + [LocDisplayName("Assume browser")] + [Description("[browser] This option defines globals exposed by modern browsers: all the way from good ol' document and navigator to the HTML5 FileReader and other new developments in the browser world.")] + [Category("Environment")] + public bool JsHint_browser { get; set; } + + [LocDisplayName("Assume CouchDB")] + [Description("[couch] This option defines globals exposed by CouchDB. CouchDB is a document-oriented database that can be queried and indexed in a MapReduce fashion using JavaScript.")] + [Category("Environment")] + public bool JsHint_couch { get; set; } + + [LocDisplayName("Allow console, alert etc.")] + [Description("[devel] This option defines globals that are usually used for logging poor-man's debugging: console, alert, etc.")] + [Category("Environment")] + public bool JsHint_devel { get; set; } + + [LocDisplayName("Assume Dojo")] + [Description("[dojo] This option defines globals exposed by the Dojo Toolkit.")] + [Category("Environment")] + public bool JsHint_dojo { get; set; } + + [LocDisplayName("Assume jQuery")] + [Description("[jquery] This option defines globals exposed by the jQuery JavaScript library.")] + [Category("Environment")] + public bool JsHint_jquery { get; set; } + + [LocDisplayName("Assume MooTools")] + [Description("[mootools] This option defines globals exposed by the MooTools JavaScript framework.")] + [Category("Environment")] + public bool JsHint_mootools { get; set; } + + [LocDisplayName("Assume NodeJS")] + [Description("[node] This option defines globals available when your code is running inside of the Node runtime environment.")] + [Category("Environment")] + public bool JsHint_node { get; set; } + + [LocDisplayName("Allow non-standards")] + [Description("[nonstandard] This option defines non-standard but widely adopted globals such as escape and unescape.")] + [Category("Environment")] + public bool JsHint_nonstandard { get; set; } + + [LocDisplayName("Assume Prototype.js")] + [Description("[prototypejs] This option defines globals exposed by the Prototype JavaScript framework.")] + [Category("Environment")] + public bool JsHint_prototypejs { get; set; } + + [LocDisplayName("Assume Rhino")] + [Description("[rhino] This option defines globals available when your code is running inside of the Rhino runtime environment.")] + [Category("Environment")] + public bool JsHint_rhino { get; set; } + + [LocDisplayName("Allow Web Workers")] + [Description("[worker] This option defines globals available when your code is running inside of a Web Worker.")] + [Category("Environment")] + public bool JsHint_worker { get; set; } + + [LocDisplayName("Assume Windows Script Host")] + [Description("[wsh] This option defines globals available when your code is running as a script for the Windows Script Host.")] + [Category("Environment")] + public bool JsHint_wsh { get; set; } + } +} diff --git a/EditorExtensions/Options/Less.cs b/EditorExtensions/Options/Less.cs new file mode 100644 index 000000000..e0537ed34 --- /dev/null +++ b/EditorExtensions/Options/Less.cs @@ -0,0 +1,58 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class LessOptions : DialogPage + { + public LessOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.GenerateCssFileFromLess, GenerateCssFileFromLess); + Settings.SetValue(WESettings.Keys.ShowLessPreviewWindow, ShowLessPreviewWindow); + Settings.SetValue(WESettings.Keys.LessMinify, LessMinify); + Settings.SetValue(WESettings.Keys.LessCompileOnBuild, LessCompileOnBuild); + Settings.SetValue(WESettings.Keys.LessCompileToFolder, LessCompileToFolder); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + GenerateCssFileFromLess = WESettings.GetBoolean(WESettings.Keys.GenerateCssFileFromLess); + ShowLessPreviewWindow = WESettings.GetBoolean(WESettings.Keys.ShowLessPreviewWindow); + LessMinify = WESettings.GetBoolean(WESettings.Keys.LessMinify); + LessCompileOnBuild = WESettings.GetBoolean(WESettings.Keys.LessCompileOnBuild); + LessCompileToFolder = WESettings.GetBoolean(WESettings.Keys.LessCompileToFolder); + } + + [LocDisplayName("Generate CSS file on save")] + [Description("Generate CSS file when LESS file is saved")] + [Category("LESS")] + public bool GenerateCssFileFromLess { get; set; } + + [LocDisplayName("Generate min file on save")] + [Description("Creates a minified version of the compiled CSS file (file.min.css)")] + [Category("LESS")] + public bool LessMinify { get; set; } + + [LocDisplayName("Show preview window")] + [Description("Show the preview window when editing a LESS file.")] + [Category("LESS")] + public bool ShowLessPreviewWindow { get; set; } + + [LocDisplayName("Compile on build")] + [Description("Compiles all LESS files in the project that has a corresponding .css file.")] + [Category("LESS")] + public bool LessCompileOnBuild { get; set; } + + [LocDisplayName("Compile to 'css' folder")] + [Description("Compiles all LESS files into a folder called 'css' in the same directory as the .less file")] + [Category("LESS")] + public bool LessCompileToFolder { get; set; } + } +} diff --git a/EditorExtensions/Options/ProjectSettingsStore.cs b/EditorExtensions/Options/ProjectSettingsStore.cs new file mode 100644 index 000000000..07cfaad2a --- /dev/null +++ b/EditorExtensions/Options/ProjectSettingsStore.cs @@ -0,0 +1,349 @@ +using EnvDTE; +using EnvDTE80; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using Keys = MadsKristensen.EditorExtensions.WESettings.Keys; + +namespace MadsKristensen.EditorExtensions +{ + internal class Settings + { + public const string _fileName = "WE-settings.xml"; + public const string _solutionFolder = "Solution Items"; + + private static SortedDictionary _cache = DefaultSettings(); + private static bool _inProgress; + private static object _syncFileRoot = new object(); + private static object _syncCacheRoot = new object(); + + public Settings() + { + UpdateCache(); + } + + public static bool SolutionSettingsExist + { + get { return File.Exists(GetSolutionFilePath()); } + } + + public static float Version { get; private set; } + + public static object GetValue(string propertyName) + { + lock (_syncCacheRoot) + { + if (_cache.ContainsKey(propertyName)) + return _cache[propertyName]; + } + + return null; + } + + public static void SetValue(string propertyName, object value) + { + lock (_syncCacheRoot) + { + string v = value.ToString().ToLowerInvariant(); + _cache[propertyName] = v; + } + } + + public static void Save(string file = null) + { + //_dispatcher.BeginInvoke(new Action(() => + //{ + Task.Run(() => + { + SaveToDisk(file); + UpdateStatusBar("updated"); + }); + + //}), DispatcherPriority.ApplicationIdle, null); + } + + internal static void CreateSolutionSettings() + { + string path = GetSolutionFilePath(); + + if (!File.Exists(path)) + { + lock (_syncFileRoot) + { + File.WriteAllText(path, string.Empty); + } + + Save(path); + + Solution2 solution = EditorExtensionsPackage.DTE.Solution as Solution2; + Project project = solution.Projects + .OfType() + .FirstOrDefault(p => p.Name.Equals(_solutionFolder, StringComparison.OrdinalIgnoreCase)); + + if (project == null) + { + project = solution.AddSolutionFolder(_solutionFolder); + } + + project.ProjectItems.AddFromFile(path); + //EditorExtensionsPackage.DTE.ItemOperations.OpenFile(path); + UpdateStatusBar("applied"); + } + } + + public static void UpdateCache() + { + try + { + string path = GetFilePath(); + + if (File.Exists(path)) + { + XmlDocument doc = LoadXmlDocument(path); + + if (doc != null) + { + + XmlNode settingsNode = doc.SelectSingleNode("webessentials/settings"); + + if (settingsNode != null) + { + XmlAttribute versionAttr = settingsNode.Attributes["version"]; + if (versionAttr != null) + { + float version; + + if (float.TryParse(versionAttr.InnerText, out version)) + { + Version = version; + } + } + + lock (_syncCacheRoot) + { + _cache.Clear(); + + foreach (XmlNode node in settingsNode.ChildNodes) + { + _cache[node.Name] = node.InnerText; + } + } + + OnUpdated(); + } + } + } + } + catch + { } + } + + private static void SaveToDisk(string file) + { + if (!_inProgress) + { + _inProgress = true; + string path = file ?? GetFilePath(); + + lock (_syncFileRoot) + { + string xml = GenerateXml(); + + ProjectHelpers.CheckOutFileFromSourceControl(path); + File.WriteAllText(path, xml); + } + + _inProgress = false; + } + } + + private static string GenerateXml() + { + StringBuilder sb = new StringBuilder(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + + using (XmlWriter writer = XmlWriter.Create(sb, settings)) + { + writer.WriteStartElement("webessentials"); + writer.WriteAttributeString("version", "1.9"); + + writer.WriteStartElement("settings"); + + lock (_syncCacheRoot) + { + foreach (string property in _cache.Keys) + { + string value = _cache[property].ToString(); + writer.WriteElementString(property, value); + } + } + + writer.WriteEndElement();// settings + writer.WriteEndElement();// webessentials + } + + sb.Replace(Encoding.Unicode.WebName, Encoding.UTF8.WebName); + + return sb.ToString(); + } + + private static XmlDocument LoadXmlDocument(string path) + { + try + { + lock (_syncFileRoot) + { + XmlDocument doc = new XmlDocument(); + doc.Load(path); + return doc; + } + } + catch + { + return null; + } + } + + private static string GetFilePath() + { + string path = GetSolutionFilePath(); + + if (!File.Exists(path)) + { + path = GetUserFilePath(); + } + + return path; + } + + public static string GetSolutionFilePath() + { + EnvDTE.Solution solution = EditorExtensionsPackage.DTE.Solution; + + if (solution == null || string.IsNullOrEmpty(solution.FullName)) + return null; + + return Path.Combine(Path.GetDirectoryName(solution.FullName), _fileName); + } + + private static string GetUserFilePath() + { + string user = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + string folder = Path.Combine(user, "Web Essentials"); + + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + + return Path.Combine(folder, _fileName); + } + + private static SortedDictionary DefaultSettings() + { + var dic = new SortedDictionary(); + + // MISC + dic.Add(Keys.EnableMustache, true); + dic.Add(Keys.EnableJavascriptRegions, true); + + // LESS + dic.Add(Keys.GenerateCssFileFromLess, true); + dic.Add(Keys.ShowLessPreviewWindow, true); + dic.Add(Keys.LessMinify, true); + + // SCSS + dic.Add(Keys.GenerateCssFileFromScss, true); + dic.Add(Keys.ShowScssPreviewWindow, true); + dic.Add(Keys.ScssMinify, true); + + // CoffeeScript + dic.Add(Keys.GenerateJsFileFromCoffeeScript, true); + dic.Add(Keys.ShowCoffeeScriptPreviewWindow, true); + + // CSS + dic.Add(Keys.CssErrorLocation, (int)Keys.ErrorLocation.Messages); + dic.Add(Keys.SyncVendorValues, true); + dic.Add(Keys.EnableCssSelectorHighligting, true); + dic.Add(Keys.ShowUnsupported, true); + dic.Add(Keys.AutoCloseCurlyBraces, true); + + //JSHint + dic.Add(Keys.EnableJsHint, true); + dic.Add(Keys.JsHintErrorLocation, (int)Keys.FullErrorLocation.Messages); + dic.Add(Keys.JsHint_bitwise, true); + dic.Add(Keys.JsHint_browser, true); + dic.Add(Keys.JsHint_devel, true); + dic.Add(Keys.JsHint_eqeqeq, true); + dic.Add(Keys.JsHint_es5, true); + dic.Add(Keys.JsHint_expr, true); + dic.Add(Keys.JsHint_debug, true); + dic.Add(Keys.JsHint_jquery, true); + dic.Add(Keys.JsHint_laxbreak, true); + dic.Add(Keys.JsHint_laxcomma, true); + dic.Add(Keys.JsHint_maxerr, 50); + dic.Add(Keys.JsHint_regexdash, true); + dic.Add(Keys.JsHint_smarttabs, true); + + // MISC + dic.Add(Keys.ShowBrowserTooltip, true); + dic.Add(Keys.WrapCoffeeScriptClosure, true); + + // TypeScript + //dic.Add(Keys.ShowTypeScriptPreviewWindow, true); + //dic.Add(Keys.GenerateJsFileFromTypeScript, true); + //dic.Add(Keys.TypeScriptAddGeneratedFilesToProject, true); + + // Minification + dic.Add(Keys.EnableCssMinification, true); + dic.Add(Keys.EnableJsMinification, true); + + // Minification + dic.Add(Keys.CoffeeScriptMinify, true); + //dic.Add(Keys.TypeScriptMinify, true); + + dic.Add(Keys.GenerateJavaScriptSourceMaps, true); + dic.Add(Keys.EnableHtmlZenCoding, true); + + dic.Add(Keys.JavaScriptAutoCloseBraces, true); + dic.Add(Keys.JavaScriptOutlining, true); + + return dic; + } + + public static event EventHandler Updated; + + private static void OnUpdated() + { + if (Updated != null) + { + Updated(null, EventArgs.Empty); + } + } + + public static void UpdateStatusBar(string action) + { + try + { + if (SolutionSettingsExist) + { + EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Solution settings " + action; + } + else + { + EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Global settings " + action; + } + } + catch + { + Logger.Log("Error updating status bar"); + } + } + } +} diff --git a/EditorExtensions/Options/ProjectSettingsTextViewListener.cs b/EditorExtensions/Options/ProjectSettingsTextViewListener.cs new file mode 100644 index 000000000..8b5861154 --- /dev/null +++ b/EditorExtensions/Options/ProjectSettingsTextViewListener.cs @@ -0,0 +1,36 @@ +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; +using System.Threading.Tasks; + +namespace MadsKristensen.EditorExtensions.Options +{ + [Export(typeof(IWpfTextViewCreationListener))] + [ContentType("XML")] + [TextViewRole(PredefinedTextViewRoles.Document)] + internal class ProjectSettingsTextViewListener : IWpfTextViewCreationListener + { + public void TextViewCreated(IWpfTextView textView) + { + ITextDocument document; + textView.TextDataModel.DocumentBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document); + + if (document != null) + { + document.FileActionOccurred += document_FileActionOccurred; + } + } + + private void document_FileActionOccurred(object sender, TextDocumentFileActionEventArgs e) + { + if (e.FileActionType == FileActionTypes.ContentSavedToDisk && e.FilePath.EndsWith(Settings._fileName)) + { + Task.Run(() => + { + Settings.UpdateCache(); + }); + } + } + } +} diff --git a/EditorExtensions/Options/Scss.cs b/EditorExtensions/Options/Scss.cs new file mode 100644 index 000000000..c92b300c5 --- /dev/null +++ b/EditorExtensions/Options/Scss.cs @@ -0,0 +1,58 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class ScssOptions : DialogPage + { + public ScssOptions() + { + Settings.Updated += delegate { LoadSettingsFromStorage(); }; + } + + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.GenerateCssFileFromScss, GenerateCssFileFromScss); + Settings.SetValue(WESettings.Keys.ShowScssPreviewWindow, ShowScssPreviewWindow); + Settings.SetValue(WESettings.Keys.ScssMinify, ScssMinify); + Settings.SetValue(WESettings.Keys.ScssCompileOnBuild, ScssCompileOnBuild); + Settings.SetValue(WESettings.Keys.ScssCompileToFolder, ScssCompileToFolder); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + GenerateCssFileFromScss = WESettings.GetBoolean(WESettings.Keys.GenerateCssFileFromScss); + ShowScssPreviewWindow = WESettings.GetBoolean(WESettings.Keys.ShowScssPreviewWindow); + ScssMinify = WESettings.GetBoolean(WESettings.Keys.ScssMinify); + ScssCompileOnBuild = WESettings.GetBoolean(WESettings.Keys.ScssCompileOnBuild); + ScssCompileToFolder = WESettings.GetBoolean(WESettings.Keys.ScssCompileToFolder); + } + + [LocDisplayName("Generate CSS file on save")] + [Description("Generate CSS file when Scss file is saved")] + [Category("Scss")] + public bool GenerateCssFileFromScss { get; set; } + + [LocDisplayName("Generate min file on save")] + [Description("Creates a minified version of the compiled CSS file (file.min.css)")] + [Category("Scss")] + public bool ScssMinify { get; set; } + + [LocDisplayName("Show preview window")] + [Description("Show the preview window when editing a Scss file.")] + [Category("Scss")] + public bool ShowScssPreviewWindow { get; set; } + + [LocDisplayName("Compile on build")] + [Description("Compiles all Scss files in the project that has a corresponding .css file.")] + [Category("Scss")] + public bool ScssCompileOnBuild { get; set; } + + [LocDisplayName("Compile to 'css' folder")] + [Description("Compiles all SCSS files into a folder called 'css' in the same directory as the .scss file")] + [Category("Scss")] + public bool ScssCompileToFolder { get; set; } + } +} diff --git a/EditorExtensions/Options/TypeScript.cs b/EditorExtensions/Options/TypeScript.cs new file mode 100644 index 000000000..b04e4206a --- /dev/null +++ b/EditorExtensions/Options/TypeScript.cs @@ -0,0 +1,88 @@ +using Microsoft.VisualStudio.Shell; +using System.ComponentModel; + +namespace MadsKristensen.EditorExtensions +{ + class TypeScriptOptions : DialogPage + { + public override void SaveSettingsToStorage() + { + Settings.SetValue(WESettings.Keys.GenerateJsFileFromTypeScript, GenerateJsFileFromTypeScript); + Settings.SetValue(WESettings.Keys.ShowTypeScriptPreviewWindow, ShowTypeScriptPreviewWindow); + Settings.SetValue(WESettings.Keys.CompileTypeScriptOnBuild, CompileTypeScriptOnBuild); + Settings.SetValue(WESettings.Keys.TypeScriptKeepComments, TypeScriptKeepComments); + Settings.SetValue(WESettings.Keys.TypeScriptUseAmdModule, TypeScriptUseAmdModule); + Settings.SetValue(WESettings.Keys.TypeScriptCompileES3, TypeScriptCompileES3); + Settings.SetValue(WESettings.Keys.TypeScriptProduceSourceMap, TypeScriptProduceSourceMap); + Settings.SetValue(WESettings.Keys.TypeScriptMinify, TypeScriptMinify); + Settings.SetValue(WESettings.Keys.TypeScriptAddGeneratedFilesToProject, TypeScriptAddGeneratedFilesToProject); + Settings.SetValue(WESettings.Keys.TypeScriptResaveWithUtf8BOM, TypeScriptResaveWithUtf8BOM); + + Settings.Save(); + } + + public override void LoadSettingsFromStorage() + { + GenerateJsFileFromTypeScript = WESettings.GetBoolean(WESettings.Keys.GenerateJsFileFromTypeScript); + ShowTypeScriptPreviewWindow = WESettings.GetBoolean(WESettings.Keys.ShowTypeScriptPreviewWindow); + CompileTypeScriptOnBuild = WESettings.GetBoolean(WESettings.Keys.CompileTypeScriptOnBuild); + TypeScriptKeepComments = WESettings.GetBoolean(WESettings.Keys.TypeScriptKeepComments); + TypeScriptUseAmdModule = WESettings.GetBoolean(WESettings.Keys.TypeScriptUseAmdModule); + TypeScriptCompileES3 = WESettings.GetBoolean(WESettings.Keys.TypeScriptCompileES3); + TypeScriptProduceSourceMap = WESettings.GetBoolean(WESettings.Keys.TypeScriptProduceSourceMap); + TypeScriptMinify = WESettings.GetBoolean(WESettings.Keys.TypeScriptMinify); + TypeScriptAddGeneratedFilesToProject = WESettings.GetBoolean(WESettings.Keys.TypeScriptAddGeneratedFilesToProject); + TypeScriptResaveWithUtf8BOM = WESettings.GetBoolean(WESettings.Keys.TypeScriptResaveWithUtf8BOM); + } + + [LocDisplayName("Compile TypeScript on save")] + [Description("Generate JavaScript file when TypeScript file is saved")] + [Category("TypeScript")] + public bool GenerateJsFileFromTypeScript { get; set; } + + [LocDisplayName("Show preview window")] + [Description("Show the preview window when editing a TypeScript file.")] + [Category("TypeScript")] + public bool ShowTypeScriptPreviewWindow { get; set; } + + [LocDisplayName("Add generated files to project")] + [Description("Includes the generated .js, .min.js and .map files to the current project, nested under the .ts file.")] + [Category("TypeScript")] + public bool TypeScriptAddGeneratedFilesToProject { get; set; } + + [LocDisplayName("Compile all TypeScript files on build")] + [Description("Runs the compiler on all TypeScript files in your project on build")] + [Category("TypeScript")] + public bool CompileTypeScriptOnBuild { get; set; } + + [LocDisplayName("Minify generated JavaScript")] + [Description("Creates a minified version of the compiled JavaScript file (file.min.js)")] + [Category("TypeScript")] + public bool TypeScriptMinify { get; set; } + + [LocDisplayName("Re-save JS with UTF8 BOM")] + [Description("Re-saves the compiled output with a UTF-8 BOM")] + [Category("TypeScript")] + public bool TypeScriptResaveWithUtf8BOM { get; set; } + + [LocDisplayName("Use the AMD module")] + [Description("Sets the '--module AMD' flag on the compiler")] + [Category("Compiler flags")] + public bool TypeScriptUseAmdModule { get; set; } + + [LocDisplayName("Compile to EcmaScript 3")] + [Description("Sets the '--target ES3' flag on the compiler. Default is EcmaScript 5")] + [Category("Compiler flags")] + public bool TypeScriptCompileES3 { get; set; } + + [LocDisplayName("Generate Source Map")] + [Description("Sets the '-sourcemap' flag on the compiler.")] + [Category("Compiler flags")] + public bool TypeScriptProduceSourceMap { get; set; } + + [LocDisplayName("Keep comments")] + [Description("Keeps the comments in the generated JavaScript files by setting the '-c' flag on the compiler.")] + [Category("Compiler flags")] + public bool TypeScriptKeepComments { get; set; } + } +} diff --git a/EditorExtensions/Options/WebEssentialsSettings.cs b/EditorExtensions/Options/WebEssentialsSettings.cs new file mode 100644 index 000000000..97380dc83 --- /dev/null +++ b/EditorExtensions/Options/WebEssentialsSettings.cs @@ -0,0 +1,185 @@ + +namespace MadsKristensen.EditorExtensions +{ + static class WESettings + { + public class Keys + { + // General + public const string EnableHtmlZenCoding = "HtmlEnableZenCoding"; + public const string EnableMustache = "HtmlEnableMustache"; + public const string KeepImportantComments = "KeepImportantComments"; + + // LESS + public const string GenerateCssFileFromLess = "LessGenerateCssFile"; + public const string ShowLessPreviewWindow = "LessShowPreviewWindow"; + public const string LessMinify = "LessMinify"; + public const string LessCompileOnBuild = "LessCompileOnBuild"; + public const string LessCompileToFolder = "LessCompileToFolder"; + + // SCSS + public const string GenerateCssFileFromScss = "ScssGenerateCssFile"; + public const string ShowScssPreviewWindow = "ScssShowPreviewWindow"; + public const string ScssMinify = "ScssMinify"; + public const string ScssCompileOnBuild = "ScssCompileOnBuild"; + public const string ScssCompileToFolder = "ScssCompileToFolder"; + + // CoffeeScript + public const string GenerateJsFileFromCoffeeScript = "CoffeeScriptGenerateJsFile"; + public const string ShowCoffeeScriptPreviewWindow = "CoffeeScriptShowPreviewWindow"; + public const string CoffeeScriptMinify = "CoffeeScriptMinify"; + public const string WrapCoffeeScriptClosure = "CoffeeScriptWrapClosure"; + public const string EnableIcedCoffeeScript = "CoffeeScriptEnableIced"; + public const string CoffeeScriptCompileToFolder = "CoffeeScriptCompileToFolder"; + public const string CoffeeScriptCompileOnBuild = "CoffeeScriptCompileOnBuild"; + + // CSS + public const string ValidateStarSelector = "CssValidateStarSelector"; + public const string ValidateOverQualifiedSelector = "CSSValidateOverQualifiedSelector"; + public const string CssErrorLocation = "CssErrorLocation"; + public const string EnableCssSelectorHighligting = "CssEnableSelectorHighligting"; + public const string ValidateEmbedImages = "CssValidateEmbedImages"; + public const string AutoCloseCurlyBraces = "CssAutoCloseCurlyBraces"; + public const string ShowBrowserTooltip = "CssShowBrowserTooltip"; + public const string SyncVendorValues = "CssSyncVendorValues"; + public const string ShowInitialInherit = "CssShowInitialInherit"; + public const string ShowUnsupported = "CssShowUnsupported"; + public const string EnableCssMinification = "CssEnableMinification"; + public const string ValidateZeroUnit = "CssValidateZeroUnit"; + public const string OnlyW3cAllowed = "CssOnlyW3cAllowed"; + public const string ValidateVendorSpecifics = "ValidateVendorSpecifics"; + public const string EnableSpeedTyping = "EnableSpeedTyping"; + + // JavaScript + public const string EnableJavascriptRegions = "JavascriptEnableRegions"; + public const string EnableJsMinification = "JavaScriptEnableMinification"; + public const string JavaScriptAutoCloseBraces = "JavaScriptAutoCloseBraces"; + public const string JavaScriptOutlining = "JavaScriptOutlining"; + public const string GenerateJavaScriptSourceMaps = "JavaScriptGenerateSourceMaps"; + + // TypeScript + //public const string GenerateJsFileFromTypeScript = "TypeScriptGenerateJsFile"; + //public const string ShowTypeScriptPreviewWindow = "TypeScriptShowPreviewWindow"; + //public const string CompileTypeScriptOnBuild = "TypeScriptCompileOnBuild"; + //public const string TypeScriptKeepComments = "TypeScriptKeepComments"; + //public const string TypeScriptUseAmdModule = "TypeScriptUseAmdModule"; + //public const string TypeScriptCompileES3 = "TypeScriptCompileES3"; + //public const string TypeScriptProduceSourceMap = "TypeScriptProduceSourceMap"; + //public const string TypeScriptMinify = "TypeScriptMinify"; + //public const string TypeScriptAddGeneratedFilesToProject = "TypeScriptAddGeneratedFilesToProject"; + //public const string TypeScriptResaveWithUtf8BOM = "TypeScriptResaveWithUtf8BOM"; + + // JSHint + public const string EnableJsHint = "JsHintEnable"; + public const string RunJsHintOnBuild = "JsHintRunOnBuild"; + public const string JsHintErrorLocation = "JsHintErrorLocation"; + public const string JsHint_eqeqeq = "JsHint_eqeqeq"; + public const string JsHint_bitwise = "JsHint_bitwise"; + public const string JsHint_maxerr = "JsHint_maxerr"; // int + public const string JsHint_camelcase = "JsHint_camelcase"; + public const string JsHint_curly = "JsHint_curly"; + public const string JsHint_forin = "JsHint_forin"; + public const string JsHint_immed = "JsHint_immed"; + public const string JsHint_indent = "JsHint_indent"; // int + public const string JsHint_latedef = "JsHint_latedef"; + public const string JsHint_newcap = "JsHint_newcap"; + public const string JsHint_noarg = "JsHint_noarg"; + public const string JsHint_noempty = "JsHint_noempty"; + public const string JsHint_nonew = "JsHint_nonew"; + public const string JsHint_plusplus = "JsHint_plusplus"; + public const string JsHint_quotmark = "JsHint_quotmark"; + public const string JsHint_regexp = "JsHint_regexp"; + public const string JsHint_undef = "JsHint_undef"; + public const string JsHint_unused = "JsHint_unused"; + public const string JsHint_strict = "JsHint_strict"; + public const string JsHint_trailing = "JsHint_trailing"; + + // Relaxing + public const string JsHint_asi = "JsHint_asi"; + public const string JsHint_boss = "JsHint_boss"; + public const string JsHint_debug = "JsHint_debug"; + public const string JsHint_eqnull = "JsHint_eqnull"; + public const string JsHint_es5 = "JsHint_es5"; + public const string JsHint_esnext = "JsHint_esnext"; + public const string JsHint_evil = "JsHint_evil"; + public const string JsHint_expr = "JsHint_expr"; + public const string JsHint_funcscope = "JsHint_funcscope"; + public const string JsHint_globalstrict = "JsHint_globalstrict"; + public const string JsHint_iterator = "JsHint_iterator"; + public const string JsHint_lastsemic = "JsHint_lastsemic"; + public const string JsHint_laxbreak = "JsHint_laxbreak"; + public const string JsHint_laxcomma = "JsHint_laxcomma"; + public const string JsHint_loopfunc = "JsHint_loopfunc"; + public const string JsHint_multistr = "JsHint_multistr"; + public const string JsHint_onecase = "JsHint_onecase"; + public const string JsHint_proto = "JsHint_proto"; + public const string JsHint_regexdash = "JsHint_regexdash"; + public const string JsHint_scripturl = "JsHint_scripturl"; + public const string JsHint_smarttabs = "JsHint_smarttabs"; + public const string JsHint_shadow = "JsHint_shadow"; + public const string JsHint_sub = "JsHint_sub"; + public const string JsHint_supernew = "JsHint_supernew"; + public const string JsHint_validthis = "JsHint_validthis"; + + // Environment + public const string JsHint_browser = "JsHint_browser"; + public const string JsHint_devel = "JsHint_devel"; + public const string JsHint_jquery = "JsHint_jquery"; + public const string JsHint_couch = "JsHint_couch"; + public const string JsHint_dojo = "JsHint_dojo"; + public const string JsHint_mootools = "JsHint_mootools"; + public const string JsHint_node = "JsHint_node"; + public const string JsHint_nonstandard = "JsHint_nonstandard"; + public const string JsHint_prototypejs = "JsHint_prototypejs"; + public const string JsHint_rhino = "JsHint_rhino"; + public const string JsHint_worker = "JsHint_worker"; + public const string JsHint_wsh = "JsHint_wsh"; + + public enum ErrorLocation + { + Warnings = 0, + Messages = 1, + } + + public enum FullErrorLocation + { + Errors = 0, + Warnings = 1, + Messages = 2, + } + } + + private static Settings _projectStore; + + static WESettings() + { + _projectStore = new Settings(); + } + + public static bool GetBoolean(string propertyName) + { + bool result; + object value = Settings.GetValue(propertyName); + + if (value != null && bool.TryParse(value.ToString(), out result)) + { + return result; + } + + return false; + } + + public static int GetInt(string propertyName) + { + int result; + object value = Settings.GetValue(propertyName); + + if (value != null && int.TryParse(value.ToString(), out result)) + { + return result; + } + + return -1; + } + } +} diff --git a/EditorExtensions/PkgCmdID.cs b/EditorExtensions/PkgCmdID.cs new file mode 100644 index 000000000..6347b3362 --- /dev/null +++ b/EditorExtensions/PkgCmdID.cs @@ -0,0 +1,58 @@ + +namespace MadsKristensen.EditorExtensions +{ + static class PkgCmdIDList + { + public const uint myCommand = 0x100; + public const uint htmlEncode = 0x102; + public const uint htmlDecode = 0x103; + public const uint urlEncode = 0x106; + public const uint urlDecode = 0x107; + public const uint jsEncode = 0x108; + public const uint attrEncode = 0x109; + public const uint urlPathEncode = 0x110; + public const uint upperCaseTransform = 0x111; + public const uint lowerCaseTransform = 0x114; + public const uint titleCaseTransform = 0x115; + public const uint reverseTransform = 0x116; + public const uint normalizeTransform = 0x118; + public const uint md5Transform = 0x120; + public const uint sha1Transform = 0x121; + public const uint sha256Transform = 0x122; + public const uint sha384Transform = 0x123; + public const uint sha512Transform = 0x124; + public const uint sortCssProperties = 0x125; + public const uint addMissingVendor = 0x127; + public const uint addMissingStandard = 0x128; + public const uint cssRemoveDuplicates = 0x129; + public const uint cssHideUnsupported = 0x1033; + public const uint cssHideInheritInitial = 0x1035; + public const uint addNewFeature = 0x334; + public const uint SurroundWith = 0x334; + public const uint ExpandSelection = 0x335; + public const uint ContractSelection = 0x336; + public const uint cmdDiff = 0x1041; + public const uint cmdJsHint = 0x1042; + public const uint cmdProjectSettings = 0x1043; + public const uint cmdSolutionSettings = 0x1044; + public const uint cmdSolutionColors = 0x1045; + public const uint cmdMarkdownStylesheet = 0x1046; + public const uint CssIntellisenseSubMenu = 0x1031; + public const uint MinifyCss = 0x1051; + public const uint MinifyJs = 0x1052; + public const uint MinifySelection = 0x1053; + public const uint ExtractSelection = 0x1054; + public const uint SelectBrowsers = 0x1055; + public const uint ExtractVariable = 0x1056; + public const uint ExtractMixin = 0x1057; + public const uint BundleCss = 0x1071; + public const uint BundleJs = 0x1072; + + // Build + public const uint cmdBuildBundles = 0x1083; + public const uint cmdBuildLess = 0x1084; + //public const uint cmdBuildTypeScript = 0x1085; + public const uint cmdBuildMinify = 0x1086; + public const uint cmdBuildCoffeeScript = 0x1087; + }; +} diff --git a/EditorExtensions/Properties/AssemblyInfo.cs b/EditorExtensions/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..570631b1f --- /dev/null +++ b/EditorExtensions/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Web Essentials 2013")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Mads Kristensen")] +[assembly: AssemblyProduct("Web Essentials 2013")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.5.0.0")] +[assembly: AssemblyFileVersion("1.5.0.0")] + + + diff --git a/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfo.cs b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfo.cs new file mode 100644 index 000000000..9453c4d44 --- /dev/null +++ b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfo.cs @@ -0,0 +1,293 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.CSS.Editor.Intellisense; +using Microsoft.CSS.Editor.Schemas; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace MadsKristensen.EditorExtensions +{ + internal class DeclarationQuickInfo : IQuickInfoSource + { + private DeclarationQuickInfoSourceProvider _provider; + private ITextBuffer _buffer; + private CssTree _tree; + private static readonly string[] browserAbbr = new[] { "C", "FF", "IE", "O", "S" }; + private ICssSchemaInstance _rootSchema; + + public DeclarationQuickInfo(DeclarationQuickInfoSourceProvider provider, ITextBuffer buffer) + { + _provider = provider; + _buffer = buffer; + _rootSchema = CssSchemaManager.SchemaManager.GetSchemaRootForBuffer(buffer); + } + + public void AugmentQuickInfoSession(IQuickInfoSession session, IList qiContent, out ITrackingSpan applicableToSpan) + { + applicableToSpan = null; + + if (!EnsureTreeInitialized() || session == null || qiContent == null || qiContent.Count > 0 || !WESettings.GetBoolean(WESettings.Keys.ShowBrowserTooltip)) + return; + + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position); + if (item == null || !item.IsValid) + return; + + ParseItem theOne = null; + ICssCompletionListEntry entry = null; + ICssSchemaInstance schema = CssSchemaManager.SchemaManager.GetSchemaForItem(_rootSchema, item); + + // Declaration + Declaration dec = item.FindType(); + if (dec != null && dec.PropertyName != null && dec.PropertyName.ContainsRange(point.Value.Position, 1)) + { + entry = schema.GetProperty(dec.PropertyName.Text); + theOne = dec.PropertyName; + } + else if (dec != null && dec.IsValid && dec.Values.TextStart <= point.Value.Position && dec.Values.TextAfterEnd >= point.Value.Position) + { + entry = schema.GetProperty(dec.PropertyName.Text); + if (entry != null) + { + var list = schema.GetPropertyValues(entry.DisplayText); + theOne = dec.StyleSheet.ItemFromRange(point.Value.Position, 0); + entry = list.SingleOrDefault(r => r.DisplayText.Equals(theOne.Text, StringComparison.OrdinalIgnoreCase)); + } + } + + // Pseudo class + if (entry == null) + { + PseudoClassSelector pseudoClass = item.FindType(); + if (pseudoClass != null) + { + entry = schema.GetPseudo(pseudoClass.Text); + theOne = pseudoClass; + } + } + + // Pseudo class function + if (entry == null) + { + PseudoClassFunctionSelector pseudoClassFunction = item.FindType(); + if (pseudoClassFunction != null) + { + entry = schema.GetPseudo(pseudoClassFunction.Text); + theOne = pseudoClassFunction; + } + } + + // Pseudo element + if (entry == null) + { + PseudoElementSelector pseudoElement = item.FindType(); + if (pseudoElement != null) + { + entry = schema.GetPseudo(pseudoElement.Text); + theOne = pseudoElement; + } + } + + // Pseudo element function + if (entry == null) + { + PseudoElementFunctionSelector pseudoElementFunction = item.FindType(); + if (pseudoElementFunction != null) + { + entry = schema.GetPseudo(pseudoElementFunction.Text); + theOne = pseudoElementFunction; + } + } + + // @-directive + if (entry == null) + { + AtDirective atDirective = item.Parent as AtDirective; + if (atDirective != null && atDirective.Keyword != null) + { + entry = schema.GetAtDirective("@" + atDirective.Keyword.Text); + theOne = atDirective.Keyword; + } + } + + if (entry != null) + { + applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(theOne.Start, theOne.Length, SpanTrackingMode.EdgeNegative); + + string syntax = entry.GetSyntax(schema.Version); + string b = entry.GetAttribute("browsers"); + + if (string.IsNullOrEmpty(b) && theOne.Parent != null && theOne.Parent is Declaration) + { + b = schema.GetProperty(((Declaration)theOne.Parent).PropertyName.Text).GetAttribute("browsers"); + if (string.IsNullOrEmpty(syntax)) + syntax = theOne.Text; + } + + if (!string.IsNullOrEmpty(syntax)) + { + //var example = CreateExample(syntax); + qiContent.Add("Example: " + syntax); + } + + Dictionary browsers = GetBrowsers(b); + qiContent.Add(CreateBrowserList(browsers)); + } + } + + public static Dictionary GetBrowsers(string browsersRaw) + { + Dictionary dic = new Dictionary(); + if (!string.IsNullOrEmpty(browsersRaw)) + { + string[] array = browsersRaw.Split(','); + + foreach (string browserString in array) + { + var browser = GetBrowserVersion(browserString); + if (!dic.ContainsKey(browser.Key)) + dic.Add(browser.Key, browser.Value); + } + } + else + { + foreach (string name in browserAbbr) + { + dic.Add(name, "all"); + } + } + + return dic; + } + + private static KeyValuePair GetBrowserVersion(string browserString) + { + var nameChars = browserString.Where(b => char.IsLetter(b)).ToArray(); + + string name = string.Join(string.Empty, nameChars); + string value = "all"; + + if (nameChars.Length < browserString.Length) + value = browserString.Substring(nameChars.Length); + + int index = value.IndexOf('-'); + if (index > -1) + value = value.Substring(0, index); + + //if (value.StartsWith("1") || value.StartsWith("2") || value.StartsWith("3")) + // value = "all"; + + return new KeyValuePair(name, value); + } + + //private static UIElement CreateExample(string example) + //{ + // StackPanel panel = new StackPanel(); + // panel.Orientation = Orientation.Horizontal; + // panel.Margin = new Thickness(0, 0, 0, 5); + + // TextBlock label = new TextBlock(); + // label.Text = "Example: "; + // label.FontWeight = FontWeights.Bold; + // label.FontSize = 11; + // label.FontFamily = new FontFamily("Consolas"); + // panel.Children.Add(label); + + // TextBlock value = new TextBlock(); + // value.Text = example; + // value.FontSize = 11; + // value.FontFamily = new FontFamily("Consolas"); + // panel.Children.Add(value); + + // return panel; + //} + + private static UIElement CreateBrowserList(Dictionary browsers) + { + StackPanel panel = new System.Windows.Controls.StackPanel(); + panel.Orientation = Orientation.Horizontal; + + foreach (string name in browserAbbr) + { + StackPanel p = new StackPanel(); + p.Orientation = Orientation.Vertical; + p.Margin = new Thickness(5, 0, 5, 0); + p.HorizontalAlignment = HorizontalAlignment.Right; + + Image image = new Image(); + image.Height = 24; + image.Width = 24; + p.Children.Add(image); + + TextBlock block = new TextBlock(); + block.TextAlignment = TextAlignment.Center; + block.Background = new SolidColorBrush(Brushes.WhiteSmoke.Color); + block.Background.Opacity = 0.6; + block.Margin = new Thickness(0, -7, 0, 0); + block.HorizontalAlignment = HorizontalAlignment.Right; + block.FontSize = 11; + block.FontFamily = new FontFamily("Consolas"); + + if (!browsers.ContainsKey(name) && !browsers.ContainsKey("all")) + { + image.Opacity = 0.4; + image.Source = BitmapFrame.Create(new Uri("pack://application:,,,/WebEssentials2013;component/Resources/Browsers/" + name + "_gray.png", UriKind.RelativeOrAbsolute)); + } + else + { + block.Text = browsers.ContainsKey("all") ? string.Empty : browsers[name]; + image.Source = BitmapFrame.Create(new Uri("pack://application:,,,/WebEssentials2013;component/Resources/Browsers/" + name + ".png", UriKind.RelativeOrAbsolute)); + } + + if (block.Text != "all") + p.Children.Add(block); + + panel.Children.Add(p); + } + + return panel; + } + + /// + /// This must be delayed so that the TextViewConnectionListener + /// has a chance to initialize the WebEditor host. + /// + public bool EnsureTreeInitialized() + { + if (_tree == null)// && WebEditor.GetHost(CssContentTypeDefinition.CssContentType) != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (Exception) + { + } + } + + return _tree != null; + } + + private bool m_isDisposed; + public void Dispose() + { + if (!m_isDisposed) + { + GC.SuppressFinalize(this); + m_isDisposed = true; + } + } + } +} diff --git a/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoController.cs b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoController.cs new file mode 100644 index 000000000..9639c3ede --- /dev/null +++ b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoController.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace MadsKristensen.EditorExtensions +{ + internal class DeclarationQuickInfoController : IIntellisenseController + { + private ITextView m_textView; + private IList m_subjectBuffers; + private DeclarationQuickInfoControllerProvider m_provider; + private IQuickInfoSession m_session; + + internal DeclarationQuickInfoController(ITextView textView, IList subjectBuffers, DeclarationQuickInfoControllerProvider provider) + { + m_textView = textView; + m_subjectBuffers = subjectBuffers; + m_provider = provider; + + m_textView.MouseHover += this.OnTextViewMouseHover; + } + + private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e) + { + //find the mouse position by mapping down to the subject buffer + SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch + (new SnapshotPoint(m_textView.TextSnapshot, e.Position), + PointTrackingMode.Positive, + snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer), + PositionAffinity.Predecessor); + + if (point != null) + { + ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, PointTrackingMode.Positive); + + if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView)) + { + m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true); + } + } + } + + public void Detach(ITextView textView) + { + if (m_textView == textView) + { + m_textView.MouseHover -= this.OnTextViewMouseHover; + m_textView = null; + } + } + + public void ConnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + + public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + } +} diff --git a/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoControllerProvider.cs b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoControllerProvider.cs new file mode 100644 index 000000000..7273d8759 --- /dev/null +++ b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoControllerProvider.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [Name("Declaration QuickInfo Controller")] + [ContentType("CSS")] + internal class DeclarationQuickInfoControllerProvider : IIntellisenseControllerProvider + { + [Import] + internal IQuickInfoBroker QuickInfoBroker { get; set; } + + public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList subjectBuffers) + { + return new DeclarationQuickInfoController(textView, subjectBuffers, this); + } + } +} diff --git a/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoSourceProvider.cs b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoSourceProvider.cs new file mode 100644 index 000000000..aff37b206 --- /dev/null +++ b/EditorExtensions/QuickInfo/Declaration/DeclarationQuickInfoSourceProvider.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Utilities; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IQuickInfoSourceProvider))] + [Name("Declaration QuickInfo Source")] + [Order(Before = "Selector QuickInfo Source")] + [ContentType("CSS")] + internal class DeclarationQuickInfoSourceProvider : IQuickInfoSourceProvider + { + [Import] + internal ITextStructureNavigatorSelectorService NavigatorService { get; set; } + + [Import] + internal ITextBufferFactoryService TextBufferFactoryService { get; set; } + + public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) + { + return new DeclarationQuickInfo(this, textBuffer); + } + } +} diff --git a/EditorExtensions/QuickInfo/Font/FontQuickInfo.cs b/EditorExtensions/QuickInfo/Font/FontQuickInfo.cs new file mode 100644 index 000000000..cc9e8aed9 --- /dev/null +++ b/EditorExtensions/QuickInfo/Font/FontQuickInfo.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Drawing.Text; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class FontQuickInfo : IQuickInfoSource + { + private FontQuickInfoSourceProvider _provider; + private ITextBuffer _buffer; + private static InstalledFontCollection fonts = new InstalledFontCollection(); + private CssTree _tree; + private List _allowed = new List() { "FONT", "FONT-FAMILY" }; + + public FontQuickInfo(FontQuickInfoSourceProvider provider, ITextBuffer subjectBuffer) + { + _provider = provider; + _buffer = subjectBuffer; + } + + public void AugmentQuickInfoSession(IQuickInfoSession session, IList qiContent, out ITrackingSpan applicableToSpan) + { + applicableToSpan = null; + + if (!EnsureTreeInitialized() || session == null || qiContent == null) + return; + + // Map the trigger point down to our buffer. + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position); + if (item == null || !item.IsValid) + return; + + Declaration dec = item.FindType(); + if (dec == null || !dec.IsValid || !_allowed.Contains(dec.PropertyName.Text.ToUpperInvariant())) + return; + + string fontName = item.Text.Trim('\'', '"'); + + if (fonts.Families.SingleOrDefault(f => f.Name.Equals(fontName, StringComparison.OrdinalIgnoreCase)) != null) + { + FontFamily font = new FontFamily(fontName); + + applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(item.Start, item.Length, SpanTrackingMode.EdgeNegative); + qiContent.Add(CreateFontPreview(font, 10)); + qiContent.Add(CreateFontPreview(font, 11)); + qiContent.Add(CreateFontPreview(font, 12)); + qiContent.Add(CreateFontPreview(font, 14)); + qiContent.Add(CreateFontPreview(font, 25)); + qiContent.Add(CreateFontPreview(font, 40)); + } + } + + /// + /// This must be delayed so that the TextViewConnectionListener + /// has a chance to initialize the WebEditor host. + /// + public bool EnsureTreeInitialized() + { + if (_tree == null)// && WebEditor.GetHost(CssContentTypeDefinition.CssContentType) != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (Exception) + { + } + } + + return _tree != null; + } + + private static UIElement CreateFontPreview(FontFamily font, double size) + { + return new TextBlock() + { + Text = font.Source + " (" + size + "px)", + FontFamily = font, + FontSize = size, + }; + } + + private bool m_isDisposed; + public void Dispose() + { + if (!m_isDisposed) + { + GC.SuppressFinalize(this); + m_isDisposed = true; + } + } + } +} diff --git a/EditorExtensions/QuickInfo/Font/FontQuickInfoController.cs b/EditorExtensions/QuickInfo/Font/FontQuickInfoController.cs new file mode 100644 index 000000000..67a913537 --- /dev/null +++ b/EditorExtensions/QuickInfo/Font/FontQuickInfoController.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace MadsKristensen.EditorExtensions +{ + internal class FontQuickInfoController : IIntellisenseController + { + private ITextView m_textView; + private IList m_subjectBuffers; + private FontQuickInfoControllerProvider m_provider; + private IQuickInfoSession m_session; + + internal FontQuickInfoController(ITextView textView, IList subjectBuffers, FontQuickInfoControllerProvider provider) + { + m_textView = textView; + m_subjectBuffers = subjectBuffers; + m_provider = provider; + + m_textView.MouseHover += this.OnTextViewMouseHover; + } + + private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e) + { + //find the mouse position by mapping down to the subject buffer + SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch + (new SnapshotPoint(m_textView.TextSnapshot, e.Position), + PointTrackingMode.Positive, + snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer), + PositionAffinity.Predecessor); + + if (point != null) + { + ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, + PointTrackingMode.Positive); + + if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView)) + { + m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true); + } + } + } + + public void Detach(ITextView textView) + { + if (m_textView == textView) + { + m_textView.MouseHover -= this.OnTextViewMouseHover; + m_textView = null; + } + } + + public void ConnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + + public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + } +} diff --git a/EditorExtensions/QuickInfo/Font/FontQuickInfoControllerProvider.cs b/EditorExtensions/QuickInfo/Font/FontQuickInfoControllerProvider.cs new file mode 100644 index 000000000..d322b049c --- /dev/null +++ b/EditorExtensions/QuickInfo/Font/FontQuickInfoControllerProvider.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [Name("Font QuickInfo Controller")] + [ContentType("css")] + internal class FontQuickInfoControllerProvider : IIntellisenseControllerProvider + { + [Import] + internal IQuickInfoBroker QuickInfoBroker { get; set; } + + public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList subjectBuffers) + { + return new FontQuickInfoController(textView, subjectBuffers, this); + } + } +} diff --git a/EditorExtensions/QuickInfo/Font/FontQuickInfoSourceProvider.cs b/EditorExtensions/QuickInfo/Font/FontQuickInfoSourceProvider.cs new file mode 100644 index 000000000..890c865ed --- /dev/null +++ b/EditorExtensions/QuickInfo/Font/FontQuickInfoSourceProvider.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IQuickInfoSourceProvider))] + [Name("Font QuickInfo Source")] + [Order(Before = "Default Quick Info Presenter")] + [ContentType("CSS")] + internal class FontQuickInfoSourceProvider : IQuickInfoSourceProvider + { + [Import] + internal ITextStructureNavigatorSelectorService NavigatorService { get; set; } + + [Import] + internal ITextBufferFactoryService TextBufferFactoryService { get; set; } + + public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) + { + return new FontQuickInfo(this, textBuffer); + } + } +} diff --git a/EditorExtensions/QuickInfo/Image/ImageQuickInfo.cs b/EditorExtensions/QuickInfo/Image/ImageQuickInfo.cs new file mode 100644 index 000000000..6997bacb9 --- /dev/null +++ b/EditorExtensions/QuickInfo/Image/ImageQuickInfo.cs @@ -0,0 +1,159 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Controls; +using System.Windows.Media.Imaging; + +namespace MadsKristensen.EditorExtensions +{ + internal class ImageQuickInfo : IQuickInfoSource + { + private ITextBuffer _buffer; + private CssTree _tree; + private static List _imageExtensions = new List() { ".png", ".jpg", "gif", ".jpeg", ".bmp", ".tif", ".tiff" }; + + public ImageQuickInfo(ITextBuffer subjectBuffer) + { + _buffer = subjectBuffer; + } + + public void AugmentQuickInfoSession(IQuickInfoSession session, IList qiContent, out ITrackingSpan applicableToSpan) + { + applicableToSpan = null; + + if (!EnsureTreeInitialized() || session == null || qiContent == null) + return; + + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position); + if (item == null || !item.IsValid) + return; + + UrlItem urlItem = item.FindType(); + + if (urlItem != null && urlItem.UrlString != null && urlItem.UrlString.IsValid) + { + string url = GetFileName(urlItem.UrlString.Text.Trim('\'', '"')); + if (!string.IsNullOrEmpty(url)) + { + applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(point.Value.Position, 1, SpanTrackingMode.EdgeNegative); + var image = CreateImage(url); + if (image != null && image.Source != null) + { + qiContent.Add(image); + qiContent.Add(Math.Round(image.Source.Width) + "x" + Math.Round(image.Source.Height)); + } + } + } + } + + /// + /// This must be delayed so that the TextViewConnectionListener + /// has a chance to initialize the WebEditor host. + /// + public bool EnsureTreeInitialized() + { + if (_tree == null)// && WebEditor.GetHost(CssContentTypeDefinition.CssContentType) != null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (Exception) + { + } + } + + return _tree != null; + } + + public static string GetFileName(string text) + { + if (!string.IsNullOrEmpty(text)) + { + if (text.StartsWith("data:", StringComparison.Ordinal)) + return text; + + string imageUrl = text.Trim(new[] { '\'', '"' }); + //if (!_imageExtensions.Contains(Path.GetExtension(imageUrl))) + // return null; + + string filePath = string.Empty; + + if (text.StartsWith("//", StringComparison.Ordinal)) + text = "http:" + text; + + if (text.StartsWith("http://", StringComparison.Ordinal) || text.Contains(";base64,")) + { + return text; + } + else if (imageUrl.StartsWith("/", StringComparison.Ordinal)) + { + string root = ProjectHelpers.GetProjectFolder(EditorExtensionsPackage.DTE.ActiveDocument.FullName); + if (root.Contains("://")) + return root + imageUrl; + else if (!string.IsNullOrEmpty(root)) + filePath = root + imageUrl;// new FileInfo(root).Directory + imageUrl; + } + else if (EditorExtensionsPackage.DTE.ActiveDocument != null) + { + FileInfo fi = new FileInfo(EditorExtensionsPackage.DTE.ActiveDocument.FullName); + DirectoryInfo dir = fi.Directory; + while (imageUrl.Contains("../")) + { + imageUrl = imageUrl.Remove(imageUrl.IndexOf("../", StringComparison.Ordinal), 3); + dir = dir.Parent; + } + + filePath = Path.Combine(dir.FullName, imageUrl.Replace("/", "\\")); + } + + return File.Exists(filePath) ? filePath : "pack://application:,,,/WebEssentials2013;component/Resources/nopreview.png"; + } + + return null; + } + + public static Image CreateImage(string file) + { + try + { + var image = new Image(); + + if (file.StartsWith("data:", StringComparison.Ordinal)) + { + int index = file.IndexOf("base64,", StringComparison.Ordinal) + 7; + byte[] imageBytes = Convert.FromBase64String(file.Substring(index)); + + using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length)) + { + image.Source = BitmapFrame.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + } + } + else if (File.Exists(file)) + { + image.Source = BitmapFrame.Create(new Uri(file), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + } + + return image; + } + catch (Exception) + { + return null; + } + } + + public void Dispose() + { + // Nothing to dispose + } + } +} diff --git a/EditorExtensions/QuickInfo/Image/ImageQuickInfoController.cs b/EditorExtensions/QuickInfo/Image/ImageQuickInfoController.cs new file mode 100644 index 000000000..779ffe691 --- /dev/null +++ b/EditorExtensions/QuickInfo/Image/ImageQuickInfoController.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Windows.Controls; +using System.Windows.Media.Imaging; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions.QuickInfo +{ + internal class ImageQuickInfoController : IIntellisenseController + { + private ITextView m_textView; + private IList m_subjectBuffers; + private ImageQuickInfoControllerProvider m_provider; + + internal ImageQuickInfoController(ITextView textView, IList subjectBuffers, ImageQuickInfoControllerProvider provider) + { + m_textView = textView; + m_subjectBuffers = subjectBuffers; + m_provider = provider; + + m_textView.MouseHover += this.OnTextViewMouseHover; + } + + private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e) + { + //find the mouse position by mapping down to the subject buffer + SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch + (new SnapshotPoint(m_textView.TextSnapshot, e.Position), + PointTrackingMode.Positive, + snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer), + PositionAffinity.Predecessor); + + if (point != null) + { + ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, + PointTrackingMode.Positive); + + if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView)) + { + m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true); + } + } + } + + public void Detach(ITextView textView) + { + if (m_textView == textView) + { + m_textView.MouseHover -= this.OnTextViewMouseHover; + m_textView = null; + } + } + + + public void ConnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + + public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + } +} diff --git a/EditorExtensions/QuickInfo/Image/ImageQuickInfoControllerProvider.cs b/EditorExtensions/QuickInfo/Image/ImageQuickInfoControllerProvider.cs new file mode 100644 index 000000000..6ea93cd0b --- /dev/null +++ b/EditorExtensions/QuickInfo/Image/ImageQuickInfoControllerProvider.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions.QuickInfo +{ + [Export(typeof(IIntellisenseControllerProvider))] + [Name("Image QuickInfo Controller")] + [ContentType("CSS")] + internal class ImageQuickInfoControllerProvider : IIntellisenseControllerProvider + { + [Import, System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal IQuickInfoBroker QuickInfoBroker { get; set; } + + public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList subjectBuffers) + { + return new ImageQuickInfoController(textView, subjectBuffers, this); + } + } +} diff --git a/EditorExtensions/QuickInfo/Image/ImageQuickInfoSourceProvider.cs b/EditorExtensions/QuickInfo/Image/ImageQuickInfoSourceProvider.cs new file mode 100644 index 000000000..6d75be576 --- /dev/null +++ b/EditorExtensions/QuickInfo/Image/ImageQuickInfoSourceProvider.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions.QuickInfo +{ + [Export(typeof(IQuickInfoSourceProvider))] + [Name("Image QuickInfo Source")] + [Order(Before = "Default Quick Info Presenter")] + [ContentType("CSS")] + internal class ImageQuickInfoSourceProvider : IQuickInfoSourceProvider + { + public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) + { + return new ImageQuickInfo(textBuffer); + } + } +} diff --git a/EditorExtensions/QuickInfo/Selector/SelectorQuickInfo.cs b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfo.cs new file mode 100644 index 000000000..08e21c6e1 --- /dev/null +++ b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfo.cs @@ -0,0 +1,94 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MadsKristensen.EditorExtensions +{ + internal class SelectorQuickInfo : IQuickInfoSource + { + private SelectorQuickInfoSourceProvider _provider; + private ITextBuffer _buffer; + private CssTree _tree; + + public SelectorQuickInfo(SelectorQuickInfoSourceProvider provider, ITextBuffer subjectBuffer) + { + _provider = provider; + _buffer = subjectBuffer; + } + + public void AugmentQuickInfoSession(IQuickInfoSession session, IList qiContent, out ITrackingSpan applicableToSpan) + { + applicableToSpan = null; + + if (!EnsureTreeInitialized() || session == null || qiContent == null) + return; + + // Map the trigger point down to our buffer. + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + ParseItem item = _tree.StyleSheet.ItemBeforePosition(point.Value.Position); + if (item == null || !item.IsValid) + return; + + Selector sel = item.FindType(); + if (sel == null) + return; + + applicableToSpan = _buffer.CurrentSnapshot.CreateTrackingSpan(item.Start, item.Length, SpanTrackingMode.EdgeNegative); + + string content = GenerateContent(sel); + qiContent.Add(content); + } + + private static string GenerateContent(Selector sel) + { + SelectorSpecificity specificity = new SelectorSpecificity(sel); + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Selector specificity:\t\t" + specificity.ToString()); + //sb.AppendLine(" - IDs:\t\t\t\t" + specificity.IDs); + //sb.AppendLine(" - Classes:\t\t\t" + (specificity.Classes + specificity.PseudoClasses)); + //sb.AppendLine(" - Attributes:\t\t" + specificity.Attributes); + //sb.AppendLine(" - Elements:\t\t" + (specificity.Elements + specificity.PseudoElements)); + + return sb.ToString().Trim(); + } + + /// + /// This must be delayed so that the TextViewConnectionListener + /// has a chance to initialize the WebEditor host. + /// + public bool EnsureTreeInitialized() + { + if (_tree == null) + { + try + { + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + _tree = document.Tree; + } + catch (Exception) + { + } + } + + return _tree != null; + } + + private bool m_isDisposed; + public void Dispose() + { + if (!m_isDisposed) + { + GC.SuppressFinalize(this); + m_isDisposed = true; + } + } + } +} diff --git a/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoController.cs b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoController.cs new file mode 100644 index 000000000..41c26cfb3 --- /dev/null +++ b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoController.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace MadsKristensen.EditorExtensions +{ + internal class SelectorQuickInfoController : IIntellisenseController + { + private ITextView m_textView; + private IList m_subjectBuffers; + private SelectorQuickInfoControllerProvider m_provider; + private IQuickInfoSession m_session; + + internal SelectorQuickInfoController(ITextView textView, IList subjectBuffers, SelectorQuickInfoControllerProvider provider) + { + m_textView = textView; + m_subjectBuffers = subjectBuffers; + m_provider = provider; + + m_textView.MouseHover += this.OnTextViewMouseHover; + } + + private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e) + { + //find the mouse position by mapping down to the subject buffer + SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch + (new SnapshotPoint(m_textView.TextSnapshot, e.Position), + PointTrackingMode.Positive, + snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer), + PositionAffinity.Predecessor); + + if (point != null) + { + ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, + PointTrackingMode.Positive); + + if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView)) + { + m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true); + } + } + } + + public void Detach(ITextView textView) + { + if (m_textView == textView) + { + m_textView.MouseHover -= this.OnTextViewMouseHover; + m_textView = null; + } + } + + public void ConnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + + public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer) + { + } + } +} diff --git a/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoControllerProvider.cs b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoControllerProvider.cs new file mode 100644 index 000000000..aec2896d2 --- /dev/null +++ b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoControllerProvider.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IIntellisenseControllerProvider))] + [Name("Selector QuickInfo Controller")] + [ContentType("CSS")] + internal class SelectorQuickInfoControllerProvider : IIntellisenseControllerProvider + { + [Import] + internal IQuickInfoBroker QuickInfoBroker { get; set; } + + public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList subjectBuffers) + { + return new SelectorQuickInfoController(textView, subjectBuffers, this); + } + } +} diff --git a/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoSourceProvider.cs b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoSourceProvider.cs new file mode 100644 index 000000000..7deff2334 --- /dev/null +++ b/EditorExtensions/QuickInfo/Selector/SelectorQuickInfoSourceProvider.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Operations; +using Microsoft.VisualStudio.Utilities; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(IQuickInfoSourceProvider))] + [Name("Selector QuickInfo Source")] + [Order(Before = "Default Quick Info Presenter")] + [ContentType("CSS")] + internal class SelectorQuickInfoSourceProvider : IQuickInfoSourceProvider + { + [Import] + internal ITextStructureNavigatorSelectorService NavigatorService { get; set; } + + [Import] + internal ITextBufferFactoryService TextBufferFactoryService { get; set; } + + public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) + { + return new SelectorQuickInfo(this, textBuffer); + } + } +} diff --git a/EditorExtensions/QuickInfo/Selector/SelectorSpecificity.cs b/EditorExtensions/QuickInfo/Selector/SelectorSpecificity.cs new file mode 100644 index 000000000..43b6846fb --- /dev/null +++ b/EditorExtensions/QuickInfo/Selector/SelectorSpecificity.cs @@ -0,0 +1,84 @@ +using Microsoft.CSS.Core; +using System.Linq; + +namespace MadsKristensen.EditorExtensions +{ + internal class SelectorSpecificity + { + private Selector _selector; + + public SelectorSpecificity(Selector selector) + { + _selector = selector; + Calculate(); + } + + public int IDs { get; set; } + public int Classes { get; set; } + public int Elements { get; set; } + public int PseudoClasses { get; set; } + public int PseudoElements { get; set; } + public int Attributes { get; set; } + //public int Total { get; set; } + + public override string ToString() + { + return IDs + ", " + (Classes + PseudoClasses + Attributes) + ", " + (Elements + PseudoElements); + } + + private void Calculate() + { + // IDs + var visitorIDs = new CssItemCollector(); + _selector.Accept(visitorIDs); + + if (visitorIDs.Items.Count > 0) + IDs = visitorIDs.Items.Count;// *100; + + // Classes + var visitorClasses = new CssItemCollector(); + _selector.Accept(visitorClasses); + + if (visitorClasses.Items.Count > 0) + Classes = visitorClasses.Items.Count;// *10; + + // Attributes + var visitorAttribute = new CssItemCollector(); + _selector.Accept(visitorAttribute); + + if (visitorAttribute.Items.Count > 0) + Attributes = visitorAttribute.Items.Count;// *10; + + // Elements + var visitorElements = new CssItemCollector(); + _selector.Accept(visitorElements); + Elements = visitorElements.Items.Where(i => i.Text != "*" && i.FindType() == null).Count(); + + // Pseudo Elements + var visitorPseudoElementSelector = new CssItemCollector(); + _selector.Accept(visitorPseudoElementSelector); + + var visitorPseudoElementFunctionSelector = new CssItemCollector(); + _selector.Accept(visitorPseudoElementFunctionSelector); + + PseudoElements = visitorPseudoElementSelector.Items.Count + visitorPseudoElementFunctionSelector.Items.Count; + + // Pseudo Classes + var visitorPseudoClassSelector = new CssItemCollector(); + _selector.Accept(visitorPseudoClassSelector); + + var visitorPseudoClassFunctionSelector = new CssItemCollector(true); + _selector.Accept(visitorPseudoClassFunctionSelector); + + int pseudoClases = visitorPseudoClassSelector.Items.Count(p => !p.IsPseudoElement()); + pseudoClases += visitorPseudoClassFunctionSelector.Items.Where(p => !p.Text.StartsWith(":not(") && !p.Text.StartsWith(":matches(")).Count(); + Elements += visitorPseudoClassSelector.Items.Count(p => p.IsPseudoElement()); + + if (pseudoClases > 0) + PseudoClasses = pseudoClases;// *10; + + // Total + //Total = IDs + Classes + Attributes + Elements + PseudoElements + PseudoClasses; + } + } +} diff --git a/EditorExtensions/QuickInfo/ValueOrder/RemoveCssSignatureHelpSource.cs b/EditorExtensions/QuickInfo/ValueOrder/RemoveCssSignatureHelpSource.cs new file mode 100644 index 000000000..56b2a1c7a --- /dev/null +++ b/EditorExtensions/QuickInfo/ValueOrder/RemoveCssSignatureHelpSource.cs @@ -0,0 +1,63 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal class RemoveCssSignatureHelpSource : ISignatureHelpSource + { + private ITextBuffer _buffer; + + public RemoveCssSignatureHelpSource(ITextBuffer buffer) + { + _buffer = buffer; + } + + public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList signatures) + { + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + ParseItem item = document.StyleSheet.ItemBeforePosition(point.Value.Position); + + if (item == null) + return; + + Declaration dec = item.FindType(); + if (dec == null || dec.PropertyName == null || dec.Colon == null) + return; + + foreach (ISignature signature in signatures) + { + if (signature is ValueOrderSignature) + { + signatures.RemoveAt(signatures.Count - 1); + break; + } + } + } + + public ISignature GetBestMatch(ISignatureHelpSession session) + { + return (session.Signatures != null && session.Signatures.Count > 0) + ? session.Signatures[0] + : null; + } + + private bool m_isDisposed; + public void Dispose() + { + if (!m_isDisposed) + { + GC.SuppressFinalize(this); + m_isDisposed = true; + } + } + } +} diff --git a/EditorExtensions/QuickInfo/ValueOrder/ValueOrderFactory.cs b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderFactory.cs new file mode 100644 index 000000000..fb2d206d0 --- /dev/null +++ b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderFactory.cs @@ -0,0 +1,204 @@ +using Microsoft.CSS.Core; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System.Collections.Generic; + +namespace MadsKristensen.EditorExtensions +{ + internal static class ValueOrderFactory + { + public delegate void AddSignatures(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span); + + public static AddSignatures GetMethod(Declaration dec) + { + switch (dec.PropertyName.Text.ToLowerInvariant()) + { + case "margin": + case "padding": + case "border-width": + case "outline-width": + return Margins; + + case "border-radius": + return Corners; + + case "border": + return Borders; + + case "font": + return Fonts; + + case "columns": + return Columns; + } + + return null; + } + + private static void Margins(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span) + { + string value1 = "3px"; + string value2 = "4px"; + string value3 = "5px"; + string value4 = "6px"; + + if (dec.Values.Count > 0) + { + value1 = dec.Values[0].Text; + value2 = dec.Values.Count > 1 ? dec.Values[1].Text : value2; + value3 = dec.Values.Count > 2 ? dec.Values[2].Text : value3; + value4 = dec.Values.Count > 3 ? dec.Values[3].Text : value4; + } + + ValueOrderSignature signature1 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2} {3} {4}; }} ", dec.PropertyName.Text, value1, value2, value3, value4), + string.Format("[top={0}] [right={1}] [bottom={2}] [left={3}]", value1, value2, value3, value4), + span, session); + + ValueOrderSignature signature2 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2} {3}; }} ", dec.PropertyName.Text, value1, value2, value3), + string.Format("[top={0}] [right and left={1}] [bottom={2}]", value1, value2, value3), + span, session); + + ValueOrderSignature signature3 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2}; }} ", dec.PropertyName.Text, value1, value2), + string.Format("[top and bottom={0}] [right and left={1}]", value1, value2), + span, session); + + ValueOrderSignature signature4 = new ValueOrderSignature( + string.Format("div {{ {0}: {1}; }} ", dec.PropertyName.Text, value1), + string.Format("[top and right and bottom and left={0}]", value1), + span, session); + + signatures.Add(signature1); + signatures.Add(signature2); + signatures.Add(signature3); + signatures.Add(signature4); + } + + private static void Corners(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span) + { + string value1 = "3px"; + string value2 = "4px"; + string value3 = "5px"; + string value4 = "6px"; + + if (dec.Values.Count > 0) + { + value1 = dec.Values[0].Text; + value2 = dec.Values.Count > 1 ? dec.Values[1].Text : value2; + value3 = dec.Values.Count > 2 ? dec.Values[2].Text : value3; + value4 = dec.Values.Count > 3 ? dec.Values[3].Text : value4; + + } + ValueOrderSignature signature1 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2} {3} {4}; }} ", dec.PropertyName.Text, value1, value2, value3, value4), + string.Format("[top-left={0}] [top-right={1}] [bottom-right={2}] [bottom-left={3}]", value1, value2, value3, value4), + span, session); + + ValueOrderSignature signature2 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2} {3}; }} ", dec.PropertyName.Text, value1, value2, value3), + string.Format("[top-left={0}] [top-right and bottom-left={1}] [bottom-right={2}]", value1, value2, value3), + span, session); + + ValueOrderSignature signature3 = new ValueOrderSignature( + string.Format("div {{ {0}: {1} {2}; }} ", dec.PropertyName.Text, value1, value2), + string.Format("[top-left and bottom-right={0}] [top-right and bottom-left={1}]", value1, value2), + span, session); + + ValueOrderSignature signature4 = new ValueOrderSignature( + string.Format("div {{ {0}: {1}; }} ", dec.PropertyName.Text, value1), + string.Format("[top-left and top-right and bottom-right and bottom-left={0}]", value1), + span, session); + + signatures.Add(signature1); + signatures.Add(signature2); + signatures.Add(signature3); + signatures.Add(signature4); + } + + private static void Borders(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span) + { + ValueOrderSignature signature1 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 1px solid red; } ", + "[border-width=1px] [border-style=solid] [border-color=red]", + span, session); + + ValueOrderSignature signature2 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 1px solid; } ", + "[border-width=1px] [border-style=solid] [border-color='color']", + span, session); + + ValueOrderSignature signature3 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": solid; } ", + "[border-width=3px] [border-style=solid] [border-color='color']", + span, session); + + signatures.Add(signature1); + signatures.Add(signature2); + signatures.Add(signature3); + } + + private static void Fonts(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span) + { + ValueOrderSignature signature1 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": italic small-caps bold 13px/150% Arial; } ", + "[font-style=italic] [font-variant=small-caps] [font-weight=bold] [font-size=12px]/[line-height=150%] [font-family=Arial]", + span, session); + + ValueOrderSignature signature2 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": small-caps bold 13px/150% Arial; } ", + "[font-variant=small-caps] [font-weight=bold] [font-size=12px]/[line-height=150%] [font-family=Arial]", + span, session); + + ValueOrderSignature signature3 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": bold 13px/150% Arial; } ", + "[font-weight=bold] [font-size=12px]/[line-height=150%] [font-family=Arial]", + span, session); + + ValueOrderSignature signature4 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 13px/150% Arial; } ", + "[font-size=12px]/[line-height=150%] [font-family=Arial]", + span, session); + + ValueOrderSignature signature5 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 13px Arial; } ", + "[font-size=13px] [font-family=Arial]", + span, session); + + signatures.Add(signature5); + signatures.Add(signature4); + signatures.Add(signature3); + signatures.Add(signature2); + signatures.Add(signature1); + } + + private static void Columns(ISignatureHelpSession session, IList signatures, Declaration dec, ITrackingSpan span) + { + ValueOrderSignature signature1 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 12em; } ", + "[column-width=12em] [column-count=auto]", + span, session); + + ValueOrderSignature signature2 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": auto 12em; } ", + "[column-width=12em] [column-count=auto]", + span, session); + + ValueOrderSignature signature3 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": auto; } ", + "[column-width=auto] [column-count=auto]", + span, session); + + ValueOrderSignature signature4 = new ValueOrderSignature( + "div { " + dec.PropertyName.Text + ": 2; } ", + "[column-width=auto] [column-count=2]", + span, session); + + signatures.Add(signature1); + signatures.Add(signature2); + signatures.Add(signature3); + signatures.Add(signature4); + } + } +} diff --git a/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignature.cs b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignature.cs new file mode 100644 index 000000000..853f52478 --- /dev/null +++ b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignature.cs @@ -0,0 +1,199 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; + +namespace MadsKristensen.EditorExtensions +{ + public class ValueOrderSignature : ISignature + { + private string _propertyName; + private string _syntax; + private string _description; + private string _content; + private CssPropertyNameParameter _nameParam; + private IParameter _currentParam; + private ITrackingSpan _trackingSpan; + private ISignatureHelpSession _session; + + public event EventHandler CurrentParameterChanged; + + public ValueOrderSignature( + string syntax, + string description, + ITrackingSpan trackingSpan, + ISignatureHelpSession session) + { + + _propertyName = "Syntax"; + _syntax = syntax ?? string.Empty; + _description = description; + _trackingSpan = trackingSpan; + + _content = string.Format(CultureInfo.InvariantCulture, "{0}: {1}", _propertyName, _syntax); + _nameParam = new CssPropertyNameParameter(this); + _currentParam = _nameParam; + + _session = session; + + // In order to dismiss this tip at the appropriate time, I need to listen + // to changes in the text buffer + if (_trackingSpan != null && _session != null) + { + _session.Dismissed += OnSessionDismissed; + _trackingSpan.TextBuffer.Changed += OnTextBufferChanged; + } + } + + public ITrackingSpan ApplicableToSpan + { + get { return _trackingSpan; } + } + + public string PropertyName + { + get { return _propertyName; } + } + + public string Content + { + get { return _content; } + } + + public IParameter CurrentParameter + { + get { return _nameParam; } + + set + { + if (value != _currentParam) + { + IParameter oldParam = _currentParam; + _currentParam = value; + + if (CurrentParameterChanged != null) + { + CurrentParameterChanged(this, new CurrentParameterChangedEventArgs(oldParam, _currentParam)); + } + } + } + } + + public string Documentation + { + get { return _description; } + } + + public ReadOnlyCollection Parameters + { + get + { + IList parameters = new List(); + parameters.Add(_nameParam); + + return new ReadOnlyCollection(parameters); + } + } + + /// + /// This is called when there isn't enough room on the screen to show the normal content + /// + public string PrettyPrintedContent + { + get { return Content; } + } + + /// + /// I'm about to be destroyed, so stop listening to events + /// + private void OnSessionDismissed(object sender, System.EventArgs eventArgs) + { + if (_trackingSpan != null) + { + _trackingSpan.TextBuffer.Changed -= OnTextBufferChanged; + } + + if (_session != null) + { + _session.Dismissed -= OnSessionDismissed; + _session = null; + } + } + + /// + /// Check if the property name in the text buffer has changed. + /// If so, then dismiss the syntax help tip. + /// + private void OnTextBufferChanged(object sender, TextContentChangedEventArgs eventArgs) + { + if (_trackingSpan != null && _session != null) + { + ITextSnapshot snapshot = _trackingSpan.TextBuffer.CurrentSnapshot; + SnapshotPoint startPoint = _trackingSpan.GetStartPoint(snapshot); + bool propertyNameStillValid = false; + + if (startPoint.Position + _propertyName.Length <= snapshot.Length) + { + // Get the current text at the beginning of the tracking span. + + string text = snapshot.GetText(startPoint.Position, _propertyName.Length); + + char afterText = (startPoint.Position + _propertyName.Length < snapshot.Length) + ? snapshot.GetText(startPoint.Position + _propertyName.Length, 1)[0] + : '\0'; + + if (string.Equals(text, _propertyName, StringComparison.OrdinalIgnoreCase) && + !char.IsLetterOrDigit(afterText) && + afterText != '-') + { + // The correct property name is still in the code + propertyNameStillValid = true; + } + } + + if (!propertyNameStillValid) + { + _session.Dismiss(); + } + } + } + } + + internal class CssPropertyNameParameter : IParameter + { + private ValueOrderSignature _signature; + + public CssPropertyNameParameter(ValueOrderSignature signature) + { + _signature = signature; + } + + public string Documentation + { + get { return null; } + } + + public Span Locus + { + get { return new Span(0, _signature.PropertyName.Length); } + } + + public string Name + { + get { return _signature.PropertyName; } + } + + public Span PrettyPrintedLocus + { + get { return Locus; } + } + + public ISignature Signature + { + get { return _signature; } + } + } + +} diff --git a/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSource.cs b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSource.cs new file mode 100644 index 000000000..422a018bc --- /dev/null +++ b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSource.cs @@ -0,0 +1,83 @@ +using Microsoft.CSS.Core; +using Microsoft.CSS.Editor; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using System; +using System.Collections.Generic; +using System.Windows.Threading; + +namespace MadsKristensen.EditorExtensions +{ + internal class ValueOrderSignatureHelpSource : ISignatureHelpSource + { + private ITextBuffer _buffer; + + public ValueOrderSignatureHelpSource(ITextBuffer buffer) + { + _buffer = buffer; + } + + public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList signatures) + { + SnapshotPoint? point = session.GetTriggerPoint(_buffer.CurrentSnapshot); + if (!point.HasValue) + return; + + CssEditorDocument document = CssEditorDocument.FromTextBuffer(_buffer); + ParseItem item = document.StyleSheet.ItemBeforePosition(point.Value.Position); + + if (item == null) + return; + + Declaration dec = item.FindType(); + if (dec == null || dec.PropertyName == null || dec.Colon == null) + return; + + var span = _buffer.CurrentSnapshot.CreateTrackingSpan(dec.Colon.Start, dec.Length - dec.PropertyName.Length, SpanTrackingMode.EdgeNegative); + + ValueOrderFactory.AddSignatures method = ValueOrderFactory.GetMethod(dec); + + if (method != null) + { + signatures.Clear(); + method(session, signatures, dec, span); + + Dispatcher.CurrentDispatcher.BeginInvoke( + new Action(() => { + session.Properties.AddProperty("dec", dec); + session.Match(); + }), + DispatcherPriority.Normal, null); + } + } + + public ISignature GetBestMatch(ISignatureHelpSession session) + { + int number = 0; + + if (session.Properties.ContainsProperty("dec")) + { + Declaration dec = session.Properties["dec"] as Declaration; + string methodName = ValueOrderFactory.GetMethod(dec).Method.Name; + if (dec.Values.Count > 0 && (methodName == "Margins" || methodName == "Corners")) + { + number = 4 - dec.Values.Count; + } + } + + return (session.Signatures != null && session.Signatures.Count > number && number > -1) + ? session.Signatures[number] + : null; + } + + private bool m_isDisposed; + public void Dispose() + { + if (!m_isDisposed) + { + GC.SuppressFinalize(this); + m_isDisposed = true; + } + } + } +} diff --git a/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSourceProvider.cs b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSourceProvider.cs new file mode 100644 index 000000000..bdd32630b --- /dev/null +++ b/EditorExtensions/QuickInfo/ValueOrder/ValueOrderSignatureHelpSourceProvider.cs @@ -0,0 +1,32 @@ +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Utilities; +using Microsoft.Web.Editor; +using System.ComponentModel.Composition; + +namespace MadsKristensen.EditorExtensions +{ + [Export(typeof(ISignatureHelpSourceProvider))] + [Name("Value Order Signature Help Source")] + [Order(Before = "CSS Signature Help Source")] + [ContentType(CssContentTypeDefinition.CssContentType)] + internal class ValueOrderSignatureHelpSourceProvider : ISignatureHelpSourceProvider + { + public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer) + { + return new ValueOrderSignatureHelpSource(textBuffer); + } + } + + [Export(typeof(ISignatureHelpSourceProvider))] + [Name("Value Order Signature Help Source2")] + [Order(After = "Default")] + [ContentType(CssContentTypeDefinition.CssContentType)] + internal class RemoveCssSignatureHelpSourceProvider : ISignatureHelpSourceProvider + { + public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer) + { + return new RemoveCssSignatureHelpSource(textBuffer); + } + } +} diff --git a/EditorExtensions/QuickLaunch/Nuget/NugetSearchProvider.cs b/EditorExtensions/QuickLaunch/Nuget/NugetSearchProvider.cs new file mode 100644 index 000000000..fc4565d59 --- /dev/null +++ b/EditorExtensions/QuickLaunch/Nuget/NugetSearchProvider.cs @@ -0,0 +1,86 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows.Media.Imaging; +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.MSDNSearch +{ + /// + /// Search Provider for MSDN Library + /// GUID uniquely identifies and differentiates MSDN search from other QuickLaunch searches + /// + [Guid("042C2B4B-C7F7-49DB-B7A2-402EB8DC7891")] + public class NugetSearchProvider : IVsSearchProvider + { + // Defines all string variables like Description(Hover over Search Heading), Search Heading text, Category Shortcut + private const string _description = "search through Nuget gallery"; + private const string _displayText = "Nuget Gallery"; + private const string _categoryShortcut = "nuget"; + + public Guid Category + { + get { return GetType().GUID; } + } + + public IVsSearchTask CreateSearch(uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchProviderCallback pSearchCallback) + { + if (dwCookie == VSConstants.VSCOOKIE_NIL) + { + return null; + } + + return new NugetSearchTask(this, dwCookie, pSearchQuery, pSearchCallback); + } + + public IVsSearchItemResult CreateItemResult(string lpszPersistenceData) + { + char[] delim = { '|' }; + string[] strArr = lpszPersistenceData.Split(delim); + string displayText = strArr[0]; + string url = strArr[1]; + + return new NugetSearchResult(displayText, url, this); + } + + public string DisplayText + { + get { return _displayText; } + } + + public string Description + { + get + { + return _description; + } + } + + public void ProvideSearchSettings(IVsUIDataSource pSearchOptions) + { + } + + public string Shortcut + { + get + { + return _categoryShortcut; + } + } + + public string Tooltip + { + get { return null; } //no additional tooltip + } + + public IVsUIObject Icon + { + get + { + var image = BitmapFrame.Create(new Uri("pack://application:,,,/EditorExtensions;component/Resources/nuget.png", UriKind.RelativeOrAbsolute)); + return WpfPropertyValue.CreateIconObject(image); + } + } + } +} diff --git a/EditorExtensions/QuickLaunch/Nuget/NugetSearchResult.cs b/EditorExtensions/QuickLaunch/Nuget/NugetSearchResult.cs new file mode 100644 index 000000000..f4adab104 --- /dev/null +++ b/EditorExtensions/QuickLaunch/Nuget/NugetSearchResult.cs @@ -0,0 +1,68 @@ +using System; +using System.Diagnostics; +using System.Windows.Media.Imaging; +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.MSDNSearch +{ + public class NugetSearchResult : IVsSearchItemResult + { + private string url; + + public NugetSearchResult(string displaytext, string url, NugetSearchProvider provider) + { + this.DisplayText = displaytext; + this.SearchProvider = provider; + this.url = url; + this.PersistenceData = displaytext + "|" + url; + this.Icon = provider.Icon; + } + + public VisualStudio.OLE.Interop.IDataObject DataObject + { + get { return null; } + } + + public string Description + { + get; + private set; + } + + public string DisplayText + { + get; + private set; + } + + public IVsUIObject Icon + { + get; + private set; + } + + public void InvokeAction() + { + Process.Start(this.url); + } + + public string PersistenceData + { + get; + private set; + } + + public IVsSearchProvider SearchProvider + { + get; + private set; + } + + public string Tooltip + { + get; + private set; + } + } +} diff --git a/EditorExtensions/QuickLaunch/Nuget/NugetSearchTask.cs b/EditorExtensions/QuickLaunch/Nuget/NugetSearchTask.cs new file mode 100644 index 000000000..0ef816247 --- /dev/null +++ b/EditorExtensions/QuickLaunch/Nuget/NugetSearchTask.cs @@ -0,0 +1,99 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Web; +using System.Xml; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.MSDNSearch +{ + public class NugetSearchTask : VsSearchTask + { + private NugetSearchProvider provider; + + public NugetSearchTask(NugetSearchProvider provider, uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchProviderCallback pSearchCallback) + : base(dwCookie, pSearchQuery, pSearchCallback) + { + this.provider = provider; + } + + // Startes the search by sending Query to MSDN + protected override void OnStartSearch() + { + var webQuery = this.GetWebQuery(this.SearchQuery); + + try + { + //parser code to parse through RSS results + var xmlDocument = new XmlDocument(); + xmlDocument.Load(webQuery); + var root = xmlDocument.DocumentElement; + + //each item/entry is a unique result + var entries = root.GetElementsByTagName("item"); + if (entries.Count == 0) + entries = root.GetElementsByTagName("entry"); + + foreach (var node in entries) + { + var entry = node as XmlElement; + if (entry != null) + { + string title = null; + string url = null; + + //title tag provides result title + var titleNodes = entry.GetElementsByTagName("title"); + if (titleNodes.Count > 0) + { + title = (titleNodes[0] as XmlElement).InnerText; + } + + //link / url / id tag provides the URL linking the result string to its page + var linkNodes = entry.GetElementsByTagName("link"); + if (linkNodes.Count == 0) + linkNodes = entry.GetElementsByTagName("url"); + if (linkNodes.Count == 0) + linkNodes = entry.GetElementsByTagName("id"); + + if (linkNodes.Count > 0) + { + url = (linkNodes[0] as XmlElement).Attributes["href"].InnerText; + } + + if (title != null && url != null) + { + var result = new NugetSearchResult(title, url, this.provider); + + this.SearchCallback.ReportResult(this, result); + } + } + } + + this.SearchCallback.ReportComplete(this, (uint)entries.Count); + } + catch (Exception) + { + } + + //base.OnStartSearch(); + } + + protected new IVsSearchProviderCallback SearchCallback + { + get + { + return (IVsSearchProviderCallback)base.SearchCallback; + } + } + + public string GetWebQuery(IVsSearchQuery pSearchQuery) + { + //"http://nuget.org/api/v2/Packages()?$orderby=DownloadCount%20desc,Id,LastUpdated%20desc&$filter=((((Id%20ne%20null)%20and%20substringof('{0}',tolower(Id)))%20or%20((Description%20ne%20null)%20and%20substringof('{0}',tolower(Description))))%20or%20((Tags%20ne%20null)%20and%20substringof('%20{0}%20',tolower(Tags))))%20and%20IsAbsoluteLatestVersion&$select=Id,Version,Authors,DownloadCount,VersionDownloadCount,PackageHash,PackageSize&$top=15", + return string.Format( + "http://nuget.org/api/v2/Packages()?$orderby=DownloadCount%20desc,Id,LastUpdated%20desc&$filter=((((Id%20ne%20null)%20and%20substringof('{0}',tolower(Id)))%20or%20((Description%20ne%20null)%20and%20substringof('{0}',tolower(Description))))%20or%20((Tags%20ne%20null)%20and%20substringof('%20{0}%20',tolower(Tags))))%20and%20IsAbsoluteLatestVersion&$select=Id&$top=10", + HttpUtility.UrlEncode(pSearchQuery.SearchString)); + } + } +} diff --git a/EditorExtensions/QuickLaunch/VSGallery/VSSearchProvider.cs b/EditorExtensions/QuickLaunch/VSGallery/VSSearchProvider.cs new file mode 100644 index 000000000..5897dd283 --- /dev/null +++ b/EditorExtensions/QuickLaunch/VSGallery/VSSearchProvider.cs @@ -0,0 +1,93 @@ +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using System; +using System.Runtime.InteropServices; +using System.Windows.Media.Imaging; + +namespace Microsoft.MSDNSearch +{ + /// + /// Search Provider for MSDN Library + /// GUID uniquely identifies and differentiates MSDN search from other QuickLaunch searches + /// + [Guid("042C2B4B-C7F7-49DB-B7A2-402EB8DC7892")] + public class VSSearchProvider : IVsSearchProvider + { + // Defines all string variables like Description(Hover over Search Heading), Search Heading text, Category Shortcut + private const string DescriptionString = "search through the Visual Studio Gallery"; + private const string DisplayTextString = "Visual Studio Gallery"; + private const string CategoryShortcutString = "vs"; + + // Get the GUID that identifies this search provider + public Guid Category + { + get { return GetType().GUID; } + } + + //Main Search method that calls MSDNSearchTask to create and execute search query + public IVsSearchTask CreateSearch(uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchProviderCallback pSearchCallback) + { + if (dwCookie == VSConstants.VSCOOKIE_NIL) + { + return null; + } + + return new VSSearchTask(this, dwCookie, pSearchQuery, pSearchCallback); + } + + //Verifies persistent data to populate MRU list with previously selected result + public IVsSearchItemResult CreateItemResult(string lpszPersistenceData) + { + char[] delim = { '|' }; + string[] strArr = lpszPersistenceData.Split(delim); + string displayText = strArr[0]; + string url = strArr[1]; + + return new VSSearchResult(displayText, url, this); + } + + //MSDN Search Category Heading + public string DisplayText + { + get { return DisplayTextString; } + } + + //MSDN Search Description - shows as tooltip on hover over Search Category Heading + public string Description + { + get + { + return DescriptionString; + } + } + + // + public void ProvideSearchSettings(IVsUIDataSource pSearchOptions) + { + } + + //MSDN Category shortcut to scope results to to show only from MSDN Library + public string Shortcut + { + get + { + return CategoryShortcutString; + } + } + + public string Tooltip + { + get { return null; } //no additional tooltip + } + + public IVsUIObject Icon + { + get + { + var image = BitmapFrame.Create(new Uri("pack://application:,,,/WebEssentials2013;component/Resources/vsgallery.png", UriKind.RelativeOrAbsolute)); + return WpfPropertyValue.CreateIconObject(image); + } + } + } +} diff --git a/EditorExtensions/QuickLaunch/VSGallery/VSSearchResult.cs b/EditorExtensions/QuickLaunch/VSGallery/VSSearchResult.cs new file mode 100644 index 000000000..1119d9810 --- /dev/null +++ b/EditorExtensions/QuickLaunch/VSGallery/VSSearchResult.cs @@ -0,0 +1,68 @@ +using System.Diagnostics; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.MSDNSearch +{ + public class VSSearchResult : IVsSearchItemResult + { + private string url; + + public VSSearchResult(string displaytext, string url, VSSearchProvider provider) + { + this.DisplayText = displaytext; + this.SearchProvider = provider; + this.url = url; + this.PersistenceData = displaytext + "|" + url; + this.Icon = provider.Icon; + } + + public VisualStudio.OLE.Interop.IDataObject DataObject + { + get { return null; } + } + + public string Description + { + get; + private set; + } + + public string DisplayText + { + get; + private set; + } + + public IVsUIObject Icon + { + get; + private set; + } + + //action to be performed on selection of result from result list + public void InvokeAction() + { + Process.Start(this.url); + + } + + //retrieves persistence data for this result + public string PersistenceData + { + get; + private set; + } + + public IVsSearchProvider SearchProvider + { + get; + private set; + } + + public string Tooltip + { + get; + private set; + } + } +} diff --git a/EditorExtensions/QuickLaunch/VSGallery/VSSearchTask.cs b/EditorExtensions/QuickLaunch/VSGallery/VSSearchTask.cs new file mode 100644 index 000000000..e109a84ef --- /dev/null +++ b/EditorExtensions/QuickLaunch/VSGallery/VSSearchTask.cs @@ -0,0 +1,96 @@ +using System; +using System.Text; +using System.Web; +using System.Xml; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace Microsoft.MSDNSearch +{ + public class VSSearchTask : VsSearchTask + { + private VSSearchProvider provider; + + public VSSearchTask(VSSearchProvider provider, uint dwCookie, IVsSearchQuery pSearchQuery, IVsSearchProviderCallback pSearchCallback) + : base(dwCookie, pSearchQuery, pSearchCallback) + { + this.provider = provider; + } + + protected override void OnStartSearch() + { + string webQuery = this.GetWebQuery(this.SearchQuery); + + try + { + //parser code to parse through RSS results + var xmlDocument = new XmlDocument(); + xmlDocument.Load(webQuery); + var root = xmlDocument.DocumentElement; + + //each item/entry is a unique result + var entries = root.GetElementsByTagName("item"); + if (entries.Count == 0) + entries = root.GetElementsByTagName("entry"); + + for (int i = 0; i < Math.Min(10, entries.Count); i++) + { + var entry = entries[i] as XmlElement; + + if (entry != null) + { + string title = null; + string url = null; + + //title tag provides result title + var titleNodes = entry.GetElementsByTagName("title"); + if (titleNodes.Count > 0) + { + title = (titleNodes[0] as XmlElement).InnerText; + } + + //link / url / id tag provides the URL linking the result string to its page + var linkNodes = entry.GetElementsByTagName("link"); + if (linkNodes.Count == 0) + linkNodes = entry.GetElementsByTagName("url"); + if (linkNodes.Count == 0) + linkNodes = entry.GetElementsByTagName("id"); + + if (linkNodes.Count > 0) + { + url = (linkNodes[0] as XmlElement).InnerText; + } + + if (title != null && url != null) + { + var result = new VSSearchResult(title, url, this.provider); + + this.SearchCallback.ReportResult(this, result); + } + } + } + + this.SearchCallback.ReportComplete(this, (uint)entries.Count); + } + catch (Exception) + { + this.SearchCallback.ReportComplete(this, 0); + } + } + + protected new IVsSearchProviderCallback SearchCallback + { + get + { + return (IVsSearchProviderCallback)base.SearchCallback; + } + } + + public string GetWebQuery(IVsSearchQuery pSearchQuery) + { + return string.Format( + "http://visualstudiogallery.msdn.microsoft.com/site/feeds/searchRss?f%5B0%5D.Type=SearchText&f%5B0%5D.Value={0}&f%5B1%5D.Type=RootCategory&f%5B1%5D.Value=tools&f%5B1%5D.Text=Tools&sortBy=Relevance", + HttpUtility.UrlEncode(pSearchQuery.SearchString)); + } + } +} diff --git a/EditorExtensions/Resources.Designer.cs b/EditorExtensions/Resources.Designer.cs new file mode 100644 index 000000000..6a4b975b4 --- /dev/null +++ b/EditorExtensions/Resources.Designer.cs @@ -0,0 +1,378 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18210 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MadsKristensen.EditorExtensions { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MadsKristensen.EditorExtensions.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Browser compatibility: Add missing standard directive ({0}). + /// + internal static string BestPracticeAddMissingStandardDirective { + get { + return ResourceManager.GetString("BestPracticeAddMissingStandardDirective", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Browser compatibility: Add missing standard property ({0}). + /// + internal static string BestPracticeAddMissingStandardProperty { + get { + return ResourceManager.GetString("BestPracticeAddMissingStandardProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Browser compatibility: Add missing vendor specific properties to '{0}' ({1}). + /// + internal static string BestPracticeAddMissingVendorSpecific { + get { + return ResourceManager.GetString("BestPracticeAddMissingVendorSpecific", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Browser compatibility: Add missing vendor specific directives to '{0}' ({1}). + /// + internal static string BestPracticeAddMissingVendorSpecificDirective { + get { + return ResourceManager.GetString("BestPracticeAddMissingVendorSpecificDirective", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best practice: The property '{0}' is already specified in the rule. Remove any unneeded duplicates. + /// + internal static string BestPracticeDuplicatePropertyInRule { + get { + return ResourceManager.GetString("BestPracticeDuplicatePropertyInRule", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best practice: The property '{0}' with the same value is already specified in the rule and should be removed. + /// + internal static string BestPracticeDuplicatePropertyWithSameValueInRule { + get { + return ResourceManager.GetString("BestPracticeDuplicatePropertyWithSameValueInRule", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best practice: The exact same selector is already defined on line {0}. Consider consolidating the duplicate style rules. + /// + internal static string BestPracticeDuplicateSelectors { + get { + return ResourceManager.GetString("BestPracticeDuplicateSelectors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best practice: The '{0}' property has no effect with 'display: inline' and should be removed. + /// + internal static string BestPracticeInlineIncompat { + get { + return ResourceManager.GetString("BestPracticeInlineIncompat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best practice: "{0}" should be placed before any pseudo classes/elements. + /// + internal static string BestPracticePseudosAfterOtherSelectors { + get { + return ResourceManager.GetString("BestPracticePseudosAfterOtherSelectors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Browser compatibility: Place the standard property below its vendor specific implementations. + /// + internal static string BestPracticeStandardPropertyOrder { + get { + return ResourceManager.GetString("BestPracticeStandardPropertyOrder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Best Practice: Don't specify the unit type ({0}) when the value is zero. (Disable this check in Tools -> Options). + /// + internal static string BestPracticeZeroUnit { + get { + return ResourceManager.GetString("BestPracticeZeroUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE6 only. + /// + internal static string IE6OnlyPropertyHackName { + get { + return ResourceManager.GetString("IE6OnlyPropertyHackName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE6 only. + /// + internal static string IE6OnlySelectorHackSmartTagActionName { + get { + return ResourceManager.GetString("IE6OnlySelectorHackSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE7 and above. + /// + internal static string IE7AboveSelectorHackSmartTagActionName { + get { + return ResourceManager.GetString("IE7AboveSelectorHackSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE7 and below. + /// + internal static string IE7BelowPropertyHackName { + get { + return ResourceManager.GetString("IE7BelowPropertyHackName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE7 only. + /// + internal static string IE7OnlySelectorHackSmartTagActionName { + get { + return ResourceManager.GetString("IE7OnlySelectorHackSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make visible to IE8 and above. + /// + internal static string IE8AboveSelectorHackSmartTagActionName { + get { + return ResourceManager.GetString("IE8AboveSelectorHackSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trim over qualified selectors. + /// + internal static string OverQualifiedSmartTagActionName { + get { + return ResourceManager.GetString("OverQualifiedSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance: Don't over qualify selectors. Remove all selectors before "{0}" ({1}). ID's must only occur once per web page and doesn't need further qualification.. + /// + internal static string PerformanceDontOverQualifySelectors { + get { + return ResourceManager.GetString("PerformanceDontOverQualifySelectors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance: Never use the universal selector. It has a big negative performance impact on browser rendering.. + /// + internal static string PerformanceDontUseStarSelector { + get { + return ResourceManager.GetString("PerformanceDontUseStarSelector", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance: The image is only {0} bytes and should be embedded as a base64 dataURI to reduce the number of HTTP requests.. + /// + internal static string PerformanceEmbedImageAsDataUri { + get { + return ResourceManager.GetString("PerformanceEmbedImageAsDataUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance: Use shorthand notation. The properties {0} can be replaced by {1}. + /// + internal static string PerformanceUseShorthand { + get { + return ResourceManager.GetString("PerformanceUseShorthand", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove IE selector hack. + /// + internal static string RemoveSelectorHackSmartTagActionName { + get { + return ResourceManager.GetString("RemoveSelectorHackSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save to file. + /// + internal static string ReverseEmbedSmartTagActionName { + get { + return ResourceManager.GetString("ReverseEmbedSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add missing standard property ({0}). + /// + internal static string StandardSmartTagActionName { + get { + return ResourceManager.GetString("StandardSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Re-embed dataURI from "{0}". + /// + internal static string UpdateEmbedSmartTagActionName { + get { + return ResourceManager.GetString("UpdateEmbedSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Embed as base64 DataURI. + /// + internal static string UrlSmartTagActionName { + get { + return ResourceManager.GetString("UrlSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): Values must be between 0 and 255. + /// + internal static string ValidationColorValuesInRange { + get { + return ResourceManager.GetString("ValidationColorValuesInRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): "{0}" has been deprecated and is safe to remove. Use the un-prefixed standard property instead.. + /// + internal static string ValidationDeprecatedVendorDeclaration { + get { + return ResourceManager.GetString("ValidationDeprecatedVendorDeclaration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): Pseudo elements ("{0}") must be specified after pseudo classes ("{1}").. + /// + internal static string ValidationPseudoOrder { + get { + return ResourceManager.GetString("ValidationPseudoOrder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): "{0}" is not a valid vendor specific property or it may have been deprecated.. + /// + internal static string ValidationVendorDeclarations { + get { + return ResourceManager.GetString("ValidationVendorDeclarations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): "{0}" is not a valid vendor specific @-directive or it may have been deprecated.. + /// + internal static string ValidationVendorDirective { + get { + return ResourceManager.GetString("ValidationVendorDirective", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Validation (WE): "{0}" is not a valid vendor specific pseudo class/element or it may have been deprecated.. + /// + internal static string ValidationVendorPseudo { + get { + return ResourceManager.GetString("ValidationVendorPseudo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Move property below last vendor specific. + /// + internal static string VendorOrderSmartTagActionName { + get { + return ResourceManager.GetString("VendorOrderSmartTagActionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add missing vendor specifics. + /// + internal static string VendorSmartTagActionName { + get { + return ResourceManager.GetString("VendorSmartTagActionName", resourceCulture); + } + } + } +} diff --git a/EditorExtensions/Resources.resx b/EditorExtensions/Resources.resx new file mode 100644 index 000000000..1e7d2c105 --- /dev/null +++ b/EditorExtensions/Resources.resx @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Browser compatibility: Add missing standard directive ({0}) + + + Browser compatibility: Add missing standard property ({0}) + + + Browser compatibility: Add missing vendor specific properties to '{0}' ({1}) + + + Browser compatibility: Add missing vendor specific directives to '{0}' ({1}) + + + Best practice: The property '{0}' is already specified in the rule. Remove any unneeded duplicates + + + Best practice: The property '{0}' with the same value is already specified in the rule and should be removed + + + Best practice: The exact same selector is already defined on line {0}. Consider consolidating the duplicate style rules + + + Best practice: The '{0}' property has no effect with 'display: inline' and should be removed + + + Best practice: "{0}" should be placed before any pseudo classes/elements + + + Browser compatibility: Place the standard property below its vendor specific implementations + + + Best Practice: Don't specify the unit type ({0}) when the value is zero. (Disable this check in Tools -> Options) + + + Make visible to IE6 only + + + Make visible to IE6 only + + + Make visible to IE7 and above + + + Make visible to IE7 and below + + + Make visible to IE7 only + + + Make visible to IE8 and above + + + Trim over qualified selectors + + + Performance: Don't over qualify selectors. Remove all selectors before "{0}" ({1}). ID's must only occur once per web page and doesn't need further qualification. + + + Performance: Never use the universal selector. It has a big negative performance impact on browser rendering. + + + Performance: The image is only {0} bytes and should be embedded as a base64 dataURI to reduce the number of HTTP requests. + + + Performance: Use shorthand notation. The properties {0} can be replaced by {1} + + + Remove IE selector hack + + + Save to file + + + Add missing standard property ({0}) + + + Re-embed dataURI from "{0}" + + + Embed as base64 DataURI + + + Validation (WE): Values must be between 0 and 255 + + + Validation (WE): "{0}" has been deprecated and is safe to remove. Use the un-prefixed standard property instead. + + + Validation (WE): Pseudo elements ("{0}") must be specified after pseudo classes ("{1}"). + + + Validation (WE): "{0}" is not a valid vendor specific property or it may have been deprecated. + + + Validation (WE): "{0}" is not a valid vendor specific @-directive or it may have been deprecated. + + + Validation (WE): "{0}" is not a valid vendor specific pseudo class/element or it may have been deprecated. + + + Move property below last vendor specific + + + Add missing vendor specifics + + \ No newline at end of file diff --git a/EditorExtensions/Resources/Browsers/c.png b/EditorExtensions/Resources/Browsers/c.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8f0aad4375c5c53b4ed63679a8ac5f283911b1 GIT binary patch literal 1781 zcmV&QyyVsAtE39=aDBKGa`~T1T89>mYM+qcpwqg*jTL? zkDc}6Z*J<^hUaB!aT9N+JOKl0z;_w;q`>7o>tX!oi83P z-ZH?Iuk7noVVfB97{Y@Hh1w1?0c#03jn^ZA<7FvTKA8RTEBZeH41aO=GK_o^;maa2 z4?ycazhSfbch{dH5aG2~y?@R-|7zi--uM#%T;8{16-J&y*n^Or+P3Lvra69USXEBr z^;u`+rLM!h(SHJj(>--z*Vbh|u}>kg7okO_u~epguW-E`THAjmBHt57x!heik{i0@ zrj3Hec>aewJ1QrmujgakLlR5e7-lN5AYuR0=wd>s6cx^!dMgRxW_;p&a05O}jGkak8@eSwm-}u{b6Ttr8 zK1$-MT}hDaKef~p?mQE6?>iA8GPR|uN78Aerw5kbgIll&$)yOx3#8pCOtr5b1kJh- z1WCt_1o`seOuPQ2o;$7qB%uv}Wr1hYXkK|^WeeSBi*%00gvQjYo;3@3XbZ)yJGs!& z!<8h&Dzv6N-MJ0Sli!o8{0gxjfe1!w7-DLU5|IU>>_CH)_1tj{AWBD>(3=MWAIud| z-d`N>?p-szQ)RYjydk97#*!y z-N=(u8j&r6ya1fN;Vy`SC|f1DPc0%=DTj^|Yx7)fPm`2mTvs=f+jen$Jj1DhF@`59 zl%j}A6fs_^&_6uEpU+l#ue=+ZS&uQo47qI?nB`5EQD!2W3M#2Z&MV%5RF!iDcw=)1 zCQ;nID;Q{-$LYaQCdv`zD5hAc%~BLmied&wCU|ow!eYd;;Do zk++=C_n1EydfM}hmnuwFu4$lHiJ2%xsQ0Ys&M?OvM_qaPq$Cna)$}(3sFz3`@2FEW zQPf=nQ44*S{=p^xcfN4{dLoh&n2|8&-}{?55_}6 zsi^05wOaJ9X1Th?gwgUCfB5I`X!%S(2X`%H&x#%vcjURft%WrUJ2~*+9qe3Lpf16gefzMpbHB2td3dMi{s{$gkr=tiEkE+t=OAZaW|E zg~UwqQT!HHqN8Nf#~?_i08~M};Jrb8Fp2OdaelIK@D26A`k!pfiV41jn5QKmE2fr4 z#neHJfG83O*;EVpbe=$jiKs-IDe~>E0Ul_*fT*AlsBvFcL zoT3_~HK}IKR4TcjjbCjY%&i!oxhy~Somcy<4WC!Xo8GBaR}aw%x7lPOwx_!s_$)=!~sU}?a?8cP1 zaGMtniqY+2#L&<~T^k9)+P0YQ&+jLv5s3})&eWzisD|&O`U^!4b?q6r_=&6H4Nq?t zp9=4BhQ~$pQDgjPMe6N{fs_gO(V~B`A~Q^61H23H-r#*Oj>=Jy)N_IQ6NN|4Ox{vs zvih0b9chV|2jaJ5WDCMw3Cwx8Gd52a&QVRk`>>*F`cYn2HN8skRyLJA*ZJ_^w334*DmU@0_(gwnqEAulPR52aOUi&KmmXN~hb&oiPvSQIrNG!Av1 z=XqAdDQF+sQre_Y=!8CKUH$)!M{e)nkP0pI!pGkCoPGBC_u6Z%eU62QSp1t<{AUE5 z=2uWqU{zRHcnMrBDk{1L?7(Z_RbT^N!kCNs`T3S7&2=ULxw*Nzyu7^E!EG2wfq-_j zt7yLmKZ0#Af@@_k?u>Ca@XY0N5s;agc{M95>(lJ)?1r42oF|xA2>Ryu159FkG@g4a zIXT(#nFXY#re04=ODjxIPyZn!BSQ%KqV)~0vDLu;T|C>2IX*~AN_y_h0umAu-c3wQ ztjEJUKnPazH}tP-eFOHu0_JkYT+g3cKy-BU^_ZBL`q--P) z(O&@{ySTVqI8i`KO3IbU$jJPNh=?5^=K<#14+{$$4h{}}?^pqdU>&0QGwj`y(9lo` z2?;R?CQ@(=CO$RrMk!*$W?*2zSO6l|;xN_ffkZ_`iJzaJ`1|`G!T&T2fl^abBb}X{ zg2@!!-QCjM+$>E^O=f9nY55l8Zq3ZhSeX)Vfq4#|!V@ZzeSLk!)6-MDy}cDdK|xYk zSt*!6mY0`hYHCU*CnsfoeqJ^{ig`c8~5(rQxo_0_Nt>UZGRh#GMHF|7+9QKUkD2n%PNgACKwy^3a{1I z*UQ-0nBjga!*DzA{f5>NRZ?g2FhZ$)0f)^4{C0SFP>7*7xGnSsGlXIobXvBwwY8Zv zOri7|L^s2@J?@!5jo!IUxX*_fNu2v zqzJx@Xxl;|Y#9e!DGeX4R#i+MTHrC_A`;j>(_68RkB=o%?ItLIkgxeZpb4QzD1v7M zSB%vPR;mKAwYBvZynK9x{%v6Wk3UTCCUgY?-iIgBAz}g|ex_HL0dzH23qw0Fyav92 z@lSv~ykU7RUq**1Y6YX0uyT6{_z*lm@yW)j^I;Y{{;hp VUfZjIwTu7&002ovPDHLkV1m0ik)i+q literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Browsers/ff.png b/EditorExtensions/Resources/Browsers/ff.png new file mode 100644 index 0000000000000000000000000000000000000000..5a58808347decd8a3e2671fa2819a354f5b93cfb GIT binary patch literal 2264 zcmV;}2q*W6P)+6~}*jpZodl^UZWFohdWZVmqZRO^dZnp=dD$qDCcX3~CgVpvDJ?zVSl!3GhKf zj09qgF`^9$#Dq&x!G;3m(hHQ{n0BV~&HX;}-OhKe+lRKKFl`CG@Ze5%vUAQ!)^D%# z&ws5Ylu~?}OY$i%{lY;Aam5dv8^149y2*((D--Far8Gk#wexQiM66=v2Q?A+6}9)l z@Z$ns$h`RAa0LMS^LJ%q)7_ZO3y$W$nr?3b_o0 zY=%e}#Bqe7B7(*YR(z1kY(H)8sn>7WKJY|(Ry+9eFRiz4-E%y=9Dx3j=R%(y`v4E^mRBY1kwm735-1+nPiQzRH|JJqpNa>0i0Jwcs%J9$juN7%?*WQx!9d~8N=dbJAynan5 z<@qtT7bAun4o4?6=4rujY=|S~Dw65N3PU3mswY6T7P(2UV6J4d&{>sfXT`|x*8RoW z=$&cVc4p?X0AE<1a-+q$)+o^Qtxe6hJhRR*dU`!w*ZXPI`$<>QJUO$5Oi$cYFKZ6~PXo!N0K}Stxy%-F zW0XLvsyOWn?;wvJ2TeoFjB!Nvaw@%rR7W?aYhfB1iBjls0u7I7ae?`{DN2hrL$jS6 z|Fh)pUph+rYLy3(mu3BHM<2iXjrDi;k6h9RYAUgXNybPCG%X-roFb%fv41y@d0EE3`v_VpN8)=V zl`_H11X=>wW!;D{LX;QzY^BUlNw6j@kPR*4Ps`#R*EVZF^dW%GPQBH&2nxLk zRv|=-HKGLxevCqq&RcX}yOEY1H?d=`ji)Ac!dive&}o$K(U=}bgaNr_J?KcZIAY!M zguXRZV(EZ%X;#**JFad17cloBfMc)5`9eXik0&9sB|&Hj;k1wP6E1j^<4DMxJUWo$ z$>}VKs3Vh*+SyYO`Vhy6C?G7)qPYe9NYO9z&@$s@)bgW-s=-i1#$^MXRBrwTVzkDK%7;? zv*)bxM8AL}p(adTNY+pan$eVo2WvqEFgN7W^=5L1=mz+5%dGPsB9($*XASMYTjGRG}s37t>!jdGOKr<3% z2Gya_!KAtbz>kz)uB!2cMY_{%AObLSXf8k_6eK7P^$S{Z6?SHhqiayE!8?Qf9DFOL zG$#;^I&l(_vmMsC9-H!WP;rp13z1J!)|eTM51$?k%S!+TV}Eg4Mf(;PwQactFntgb zTALN~Wk?htB!|u<=$0fgVJNYAb_Nbr#}O!mQaGl?-Ms-@ipROS=#$htkX_BF>Io_n zqI9|x9)7lezP1G5uwSp-SWmw(J7SJE^@w&0a20403Rwt3SlK1fGmnHxTnWQk0P{OJ91SYcrnot7@CZpd+x2usS7UnA%I$v1h350j&@=G zqjkW%r)eVy1*Qu@KR6cH7F?5pA2%he9CvuRn&!CIMAZw}k*{$3iZZ*dQl!HeV^bdU z`W4_xl9MIM)8fqg1L3~E9+{cETs2HyZ&W9@)KmZNIHm6pq3n}=it4ODufnpNLIDy* zZ;Q?k^B&)>9wSzQBnwtfVAsGMoY_9CC(n!DYr?o`3N&@kZZTFmkZoX45^4XkW}B+iBkgE z5uz12C%XAr`~yKWI^(@~|360_KQvaGzWDZ+>Ins40j&?WcK)PSw|qI11X z94aa^F{Ud>6(yFd(3FAz%qB34U^GeeqQuNd!m~y+UJBmWb8POR`(G^W11c8)uGAF^ zzyaDGZteV0mto$P*5pdVme?7IX-jlNVA=vlhR7sA>H<9{F^Uqis9|I^WJ6B|N5bcy zJU09LU%WiBADF*bd>_}AUw~-6x4HG^wYL40&a}D1b!6IfB!(?99f@fw%pd>(dRoJ5 z*0Bo)wUEK#g<$`E&z=44fl~Dhuy{VW`XqC~h2N3eo=&g+Vm^CAYs&b{RXOXrVp{KY z9L+Xtfn_9UrUXmW$}%}Q?neht&U$bE=GBSU2Id+gK<(n2f6~E302<&LLgf0=PRque z+f#J(Hr)`GrVBJnpc_J=;Y~Hd(N{~A!FMO?(?A*UKPtNaX)-zwA^{Vy&u@8AZ>P?c mFB*UcgqI6^S%ClB>G;1%7#CS$sIM~s0000B`Yg)?jg5S3R zkeHb0Zfk2B@8RK*>h10QE^tIUIy$=9+1ZI9I9D%Uz8u2;o3QhfgM-6wQ&UrI#l^*@ zWdkTHD|1`9a%C{)`}geGGY}IKvk?wIShHr$(Xg;EpLOfjDNj#N1u(K65zD)9sK9_4 z92`_wUz3!SR5~*=V=O5tsXKS>oat==7%pGFyxZN~{S;olkdu=$>FVnG3FuGTuwjEZ z#xvE^)1$h&y2J{!4lrRHA0IC@8jWQqPoC^q5=W|)va5%0#i~_5~HG`?1qPj71)qS>+0&%^z^iHad8m_hK7a~7$C^?>({Hzn>Q;z zKR>P;ZEtTc#<06Np{ z?d_RMMdx%dHa4avCnwdjXU}Bb+1Xh^mR08#@Sbjs1)-7Tr% zyIgnh;6Ygnd*e@^K7IfA@#8n=EshreoYvi$M_3&kr6vhzSS? zP)LPP+TY(V4t2@-`uZw}QbAZUI7ep476H;RD}aoVjmXGIHZi%kti1#lKRt8i%#am; z6DLl@g4%|GfdRF3>sDdl(W6HKf)Q~Y=Ln7!LFZb{jg5_BoJ=dza&=6UnGddtB z(oe9XqoV?lY;X<%DdCP2#nrLyb=gtb4iN8{uTRz2 z*UKEiVdqr4cI{GIwrmkSakC;@_wL>M^2(Jf7aAHGtjiGPw$js3?ork+g~o_T;cG`PVT6%$o~1`7NH04idkBFsaylpVT#FXmjxPIEVPRnv z%uN1eFW_bbs$7tUG?Yy)3`B7kV>xLDy5tCojBsAxQ>X;T{8MmD0jq?}U<;ptM!v@p zEe}BYV8*=IiO3eiJ2^S|BM9wdDBK4T86X(h-*q{nRK*FSqaO6;M8-Hzuw2XBx3;#< zg8J&x($XBX>{i&Heig?eM>6UN!*AQRZP_qFAYO1_U{9wbmLMIo&UxjJVr8^+s;^`M z6-4K?XuWyJ{V!NL&MYoNM@4KMhYmlVYnZ7N_=6^EvJC49e`AqA>*%+s!mciknj#M z!=zX!7U9x~!CPgi>3YiLO9{d(+B}NjP7Ldj1n#0f zov!SKh)x76@Ob;b0*h0B1XK2fZ5xUhJOAbrzWhZ>NzZl-$wP}~= zuP64!3tl{Hty%t^Pe?<>tnRRs{ANdM^ZAF*nA)@8!0GnX z33<`szReu{ER;sLZ_8YM{%n*~gXm2u)BBC*|H(XaXK63+gS}vJF&5K5AAG|q#HKYu z)JIOpx$e@lkM5m)`AJ7wliOQ}lM1bJ4Y_xh^Wj*`itr5HYjp7b&fRR z8oEA;s*e$tc8x|#o~&2h^V&xYdoSR*w<9L*)8rU^&*UlHJ)LdMLe=_N((yD0Og|L* zSMpAcEsu@NIOETinNJ6IT~tcftfPP1A%5w-`$pwa}Pm9OJq zwwim|ayC4#0j#~GzViYE<@vU-k8-?>=uj_mVfS-P+viBEfmLj*+xps_C*5}Q;M{f5 zT^H}=DwkhfZXG}22hFM$8?C_4BXR|-ToGlv!p-F8Sz{lZ`H}rzVAC~6h&VVc=Lzqe z>3y6(YXj|F^YAwRol?EbrRB@2FR6o{F?U_~nKh|$tsCd|d}#m~Q4i}_**tbr3wS}+5pa8q295)W!)%0{=W57 zvzB6FvqKieNIgYKW1?7kv!=RH|GElMEU2d%8y72EM5ZaO=g+pQLp=ek{}`OU)yvtx zuH@!SN~X@=SAbV!QgH_6jfZ(mFXUOVkV1>!n)3@!O>DOHq$b1UyhGLkr3^|5j5MUN zY|oAN$n35X$OL5s!p&ivEXIlRt!{eoUSKS^`-1Z6Z*2D3BIR=6zQxoqK_Fqck+Q1}TSn`6`66Cu5vEmCTn7x;E|%?D`K-0y z$2m?n^n%3#FT?S%vKZg7FXKiwlSUPmRZn4uX+t;)znI6(K*qQ5T|>dMX!Qhn4}9MN zTNx{xF{zU=QeZ6GGLD-uj+ZeAVT{oASrynv=1}xULCj&pNPP7+RM%B;2;Gmr%!Kj6w>KwqueoS^D}=_=xXWbYzUk zT7tnq5hmJ%fu>Q5MB0c%5~oHhX|OFrHfIFmj1riEN+sB%STGBVZVZW+Eo3`%uE^+S zUKwrSr9mHiLV%J9QcJ4R6H-{SH$3z5PIKGopK7Nme|RS|zpLqYZ*12`M%9|uaox}; zYwBZ0SB7*psj8l~+_nAiR|mmi2vQ7^?EZ7vG~jDtxP5IqVYNo4P$jKbXw~3v3w+dJ9*g0l}e1rTHoIh+sP0*BJW6f#N(Gq&wyGLz979VMtnj2tVYOI2tD*xI0z$Ot8wTJW~oMx6KI1J_qR zc{T)N2ui}_CK6Y`VvXaQe?0li?>&+)7B4vVfXSm-6B$z;K@M&q-nxZ&+YZv93Tn85 z7z?n=0rJBk%$isfy#pMe3<$Ieu`$4|k4N1D-!*@MmuFu4;K^OB`LDM$n@dI-$(%}JoG^-zO5r%J z5JHfqsnJ@YZLew&&lw@^8pV5l*R4y`XH7B(s9^xad$=q{a7g;M-iO?y`#v@rIO>j4 z%PZI2yS)2}=bPKqPwy*#dFbu1V`7lVNr|?cM9M(f?)%zuUe}iMGC~X{*=)kH(?0(P zn{MlE*>gSa7=~VZjHnTScRkX1lpu&O!bLNS)SO0&hv63Y+`b+E@8%)WZM``FA|#FG zdx>k`Kw2)+-c6#$P{b$(Q2IAyc-1|z?+aOZM7pil*)z9L43ouh9EzimC?xBVti`a^ gJ-$zUkqh2G0TEh{tf{(2*8l(j07*qoM6N<$g1AGSYXATM literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Browsers/ie_gray.png b/EditorExtensions/Resources/Browsers/ie_gray.png new file mode 100644 index 0000000000000000000000000000000000000000..5770d8b55309a161c4e5cdf0276b902d597bf76c GIT binary patch literal 2023 zcmV5K3H`X+!Zs|W;?UuQj zmSi>!t>SbT?;44=I-N~X!7G|YB6z_I2#A+g0pIu8=X=6S?4Zk*`6MUjdEV!o-}m?Z z{l357d0xjn$Lsw0^XBQ(r%rHi@L<<FMdg^XAPPb?@H2q+7RcooR1xUs_gHR(asSfo^v8?Ac=gUdhP*kHE8M z&o^oSdA|^XJbGij9r6VU}2~ zUAtzQnwo6rTU%RAeSN*Te*L;>XlU>~c<`VSXWzro&q01o*c-0xw*+ z(A3n_7`$E)6&3Z{<;#~x5mLwN^_u(l@0&h-`k1=9Itz5_)F}f?1Bk&%LyoOe%r4=$B_(a#wQHBl2qsNG1^f%Ar|`l^AS(&&pO-CL7Cda&Fw@xBXbob-y>jJ>xq9`g z1k(yLm-UfhT#=EHj-2WQwvG@9FZb{C>ecJZ)vH(IpBp@9&KzHlj3-Q(kQp8xzB4~R zKYIA^;ijdf#VEuhM~-waU%qS*QO)7Qhd%-E8^YFs@i8#_B@vp!I)~JB0V_%{ZzAt` zMCZEz#`l18b8}5|b8`g7_6!|5^tG{L$66z)si`J8IoSZ}lFuuoVcxlO=g#lgv7>A6 z%$YNz5!rUspQQ>AYXK`Yq{1aK6+~p}kt0Vsx&g~LD$R|Eh}aENPfALP89#o!88Kpn zLaTD}oj!ef6~Ld7uWpf=J9qBOR&G(Sp`irAt@~DBCLcR?thx*M#EBDT-MV!#iHV74sl7omiV<_^(k085 znwAqjSTyj?kLR|z$brrSz|I(tsjRH@Xpg`HBI^Y9p_#?y<>jSaz;qdPprzz*J>v3A zoH)@o2sH*B0Afz=4IRr+W|pml$66aku|h!BLCtC^N|69HlyBC#l-oyiu-{l<5-yLY z^73aKZTZxyN9CgiA;vP=uU|h~QkoHuZ6cJM4YgRQZNkz;fVTWJ%K-t3x$dyWUnNUD~0)84r9>$!H1Mv#ep+kpks99_h5)yPm`2i}z z=wDSXIA9M7t&vgX66Wgf>U>>b3bAHAW7~W5=+Q^c*|TR~0{Be;LlH_}R9!%xdn;G_ z_U*F*3ILN^mo+6Ed2essy0u$5ty#0iLwo(4(`+K4_KPu2_{A89{D{v-o zL?c!}5|Y5hT7uG0O|$Pdqm6wrD7Fs(jzAMBAdS=-ytd+0gJuv)e0ppjX-x2fJ#PXB_Lg5NmL}lS{{FdE~>ju zr|RnJnPSY#RkX!i7M2sXylK;>`HG5)3SqO3@b}kR0jX&ST+KudsB_7guTrD>g0SCNDkF6* zJqN}!my5$*_Lbu7uK~UN?-d~6WX&x46HOx<1B<6mpT6nYMN5_}>4&)9fWb0E^AceV z5i9j(9FPWW9Sa*)g6NjJ%u|9-QdjYNkxB@5s!ItZ+Yo|5-;1{fbqjf{>vM7UX81VA= zfj-JH{DfJZEfs**8DZT2jsw5`|NZA7;P6fbK4ts`;DvY|%4md1GeB+JUtoL&i*K{D zv!Baf9s#R)xD0&@>+i>OKqfJKjA~d`@~&1Yf1ZEv{skXUe(qtE?@a&z002ovPDHLk FV1o6=>9ha< literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Browsers/o.png b/EditorExtensions/Resources/Browsers/o.png new file mode 100644 index 0000000000000000000000000000000000000000..95e677693d4d4c2401ba942f4ea0dd547962b68d GIT binary patch literal 1881 zcmV-f2d4OmP)X(d^7*fLx!j$IYz9DE zAJ$c!voB=L=FijR?Xe-pBHYpyCUS1vXNke|ZnbzNPb>)m_v<9(mFb?eAI_t3Y0 zKe=KzsIHvWkDFTTj)*|X=C|26rYv|fApt1!Ka`C$R%C$O(~>(+1GaOlv( zyC3)>-FBk9;8A#E zJ;Z+lkf-6m@ZP;o?0Mvod-oi;Bgfn0Fk7ZNJIloBQ@lGhdFI0W{EUEX>+9RTXWRCh zcI@0mv8M+e8p69}FK1tQB|G=rb1z&RAAj;ucy%qrH36Q2J^ejBPws#0vHP}f-%;?+ zoI&e#vMl558*gy@pQm3umc+j}2a^J_2X-AO6du0&roErJY1eLi>!7;`w||PM$;ss8 zk)Qo;c6s@UZ>Wy12ME^de!u7CyM6!jH$U*;q0#PAL5?5CHX3*$EMB_ATknmZ{zsZT zb5!-O4X6XW1ruJ9H2P*p8umN*_QGI!OdHKZB{46#K z(YT2%m+@YEjnSUo;tgYCU;dHEoq%j;Lx95~IX{=%H@JQKSZQGqd*K2Kh;t-K%)-** zTFfXHjdxIdBdWH;LkSX#p+*ZUX?fpn9>EBui-&k@J0= zwWum)VSz$-H=8;-Zc`WlCRZJC6@ZGAI?{Bw5Qex~6;x5@5a-Y&#aGRMW;+0&DUfB> zlBi-^U#fF>NkS0E!$7H(2mc9RMDkvvQSg?Qu=V!{SB)>KhuS!DoJkcb<;#^i&jjz>Q9MEtMv#LM~ zz-u;fBKV!1LKtrB0ujL`DRI~!Q^h)WrF5mfPkzf5YZn&mMzwtlpC7PORN9e!f(~0iiMA+{zXJR+Yds z$((E7j#uOpmnmsvZ9YS;EZ|g0MR2(s`Jo}<{CU|(h3iH~ahER>8G~~U+bVljm4XTm zQnxOF*8*sWRzviB)!JQ(VAcR+su;lQ?QNTczO{Z_t9iy4oaf=zIza^^a;^%MweVLd zFzvLw({m?#tlj0Q5X<{}Xskt{IPCj9?EnUYpx60+cRfw7I3NS^3Y)xuCDFgX3nB<$tOm zL=k%Cn6>k36}SrEf^&`Y&YhgaoibKw7)Q;mfYh8LQ5^^xjU8=fNzZRKZ%kANnyXu; zN}y2ke5#@+CRAUqt=L%GbwhL1n70?vW0`2AR;d|7#agP?Qc040+-x2^a{cwUtXJWw z9Xm!FNpfqFWqEBy5THkVa-J7OBCj4b=Dqdpc%y-&qfg}e$2;=h+iAS}$4wGc*Cg)X z=FM#B?EFm>Mc+@;^xXiELZQE_Sp52O7=F84sk9mk42aLi{2(g_JonuseSA*!Jdj>< zAOX?^)!CPfJ(3UT-$w4PvN6H3I5J?d(IDsh4;6C3?!c2@3gSH9f3V(Y+`Sk@AVLR1 zQDMZ-o9VzE`)y`^IHy`>gDJV)Oy~opF9pG;?+pA$hmCx;jw1pR6wL)}DikQl%CpAm zXv7JAX2_|~jo=GzF5pimj6L!zV~zpUweo+EsW=Ce?(qGazYqjp>sLA0r83ge59`4u z2>>N@mK@+A_&^mmx#;QNp2^IQ$DKRZ3ZDHh?*#$SH6${6Ul1JJDza}#Z~M$nEx z1y6(&hpI%2=sRW6lNVKAf8LnmWz`uV+Gv3Jpa82*DFEF&J#X;io_Avr1_e4y>!t_l zpt-Di@h#^jr&Q;G8j!S^9X=GmYElc32Rd6o-Wn@vYk%X`z>>8K+!o;f_U-uJ`HWwy T?L4VB00000NkvXXu0mjfjAo^; literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Browsers/o_gray.png b/EditorExtensions/Resources/Browsers/o_gray.png new file mode 100644 index 0000000000000000000000000000000000000000..b96d96612eaa0e01bddc50af90afe4cbccb56e44 GIT binary patch literal 1682 zcmV;D25tF?P)ji66Lj7x25ps}_P zNl08Kjf@am0}qC1wXHU$4>V~)^uZVs7t)-5-wnSZc7DLVv`I-${>%TLd(L;hv)nr~ zL}bRlDKq{v04Dp3j*fPTi;Md-B_$7RC|E05vu4e6eCtk3Ow3%k zaG`%hM8vGgY)%(|6PyQ_&E~3Y+qV62eOj8Eo8|cN zjFCS6@!(%07~4<0-ayWK8_4HV;RwW30Gy(tqRg8%ZL(dwc=65s`}gJg z_3Lu!(j{qaZI#l}Qb|io`w=wXh>VQ1Vg1X_ojawarA5x2J13o;oiaE$NRV%=R;vvl z%=-(l|s?3I1{_Q~G8du8|T-KrMI+}5pI zhiF?%g+l;y=gu{P-ddt(E}NQ~lrSPjZ?RZL!o$OBpz7wJXx;d2!-fqbm6erJRaGT? zvR-I|U}9rqYrVa_jk*BB!oq?xGc&vC@Yu0q%4tJGgNkU^u3dtTco-TQYJsZJ0RW@P zWU`+2QjnwlEroRO?p zvEp`MU?AJd*#Q7&enbD?&dbY_f`S5pEzSfb)z#IKlauoV08~df0$>0G8QA>t(4j+$ zzKV(pDJv^e&KU^+*x@9Cx()ys_zeK;XkQ_S+}vCx{GTi!g)adhgSw6Y%mf2jP*QY} z#-gGkV|FaJU`-ep|kLc`t3yDQ19VWn~G{s_bxN13(siIRpR(teo$R zI6psM32CIz5DL_Wb_<#c!20#;W#h(;%(-w)o7vgf3IGbxstW+c z1on^OS>x>N?5;P6)Hp>Yr-Hg4m^+O^v<}g$9HJH)#}A^vjbhY56ZBt)goG%^d=doO zmo{!;P$g)4^#B-fs(FLH7DPVEjYN;)R1uL@q{WW9h<&#c@a{9Dsv8U{#~O%n`bV+1 z*=RJ*(b6~Bg~SDlAwb-P6pYciW{|>^pb)>sGX?-%5wRSYk_sZs8|y$Q1&~8k@FqDF-@!;(EcahU4sqI{!iX5-09qk zSuArrJv~!k^lKRWo%FMxH6aL!*7pQT9f17}d%kjacaMh+FGoc?-QNW~_dQ%)U88Z( zRD^BI3Ky`5c{8hMY%Y??*a!hxhtrWEj7K`OKa@I~KK(6A%zk z4XFpc^?X9=AeBBoKAD&$QPA~^8f$< literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Browsers/s.png b/EditorExtensions/Resources/Browsers/s.png new file mode 100644 index 0000000000000000000000000000000000000000..c700b35c3d74c71d8addfac375d40a292fbdb7bf GIT binary patch literal 2248 zcmV;(2sihMP)z^Z^!rBYB{L@N{!2rnTCNq`t$ z5<(IJgd`9WNJs)9B!avsD8Aj=*?L|(ao4)-w(B3e>$-mSe18XbyG^Y2pY3kBdoI6x z^Zh>0=leXL=jFEmz=Hp#Ecl-R@I0UF?CgbnKL1A|k!Y1zEDj)fmE<*&wL+nAbwx$R z((~ufFMJ+d^8r|xo143gl)XVpHwy%U*Ao*HmqbNHEh6P>s;a7j8XFtabvj*#Ua!B~ z(b4gU@V?ryZTwSj=5rA3R@RvpadF1X!pjE|3l?X_4e z)1{@QahEP#@_!)!Sy@?|rBbO;p-?;^cYZ~R9^AWk4-SWe47Nbg)C5tD9DJ!9(gqa- zwGAi}*P=`$MSY`!1Jv8wi#vDjps%m*6XJ`ku&{9L^8#43ZQHgL6!*9C^76{a6Hl0N zy}ljIYBeq^RH)PF(dF>KIxvi$!K*O4eCX^Og4)!JidrQ^we?UnH$$t{;`Z&^u-omw zFDWTW3=a=q@?0Dsd5M_3Tdh`KC*$9?w6s7&%BmYx=;(35dF2}VuTF8|8kvN9d>WpK zTj(FXfj-|g)U}#XB&vmm&XEq>y?ggt3fClgA%c+g>L%Y;~9s|I|0Y=B$TE;$qCu(bJjX60v zug`&aDuAG%phfxl`O!qW&luYo$rS1qSjf$ub~CP)RKTV+!r1FZo6Q5G^9tt$ZI2rU zdN#R+3D_71s#$;m4#D=W(w;n?lmY#{gx)zqp>TpHzKr(vb}ozR>+6T9uKa@8nh!uQOFt?m= zuI=CynmyOhOiFoj9STyi;SP_$Cs9$bCncjSB?|(T2|BwE>Run(93yCV45Pz!6?*#4 zF0SG(!%~w9)MEk=HZOp*w6u4q_|9qmBVw5Y(ZQV(%E8hQ&Jx3%Q?tSGV`!y^DMpO-8PGsZ^@J6Uq0kS+mCPX#o6E zQ&abn2fkyQtyT+C3aSu&UW)h1l@RM}7`k=`pFaEo#X>oF2M*)UGc%YWF+1F_Q+hsp z^d+v|`WUK#F(k|FI8d%fTxJOj!~v=)3;@Ujae;w>i=PVM?_eAKC2YwZZn0!z&P+-N=nMU<;#~ZdMW^_fZM4HKBDeMwY(b_g^k#iB|%7<5Svex zA?QpMb_tC*q3*{8jSaE6)i7F|)R68{Hr&V2LODWnYH(QLM3UN#m|`V)QOxxTRu8JH ztN(KR`0-uL)>AnU7Z(@E2`I_W%mhQ`p*KZ=B^Hhf_8A;&y|n8JGS>oi;`Z*6S_b=v9p`1mdJl5pqFov+f+ zQAccrMx%k<;lhzzDI)U}h{#o7N6uv&sL&zLMlse8;b1`nawM&IW$#&py%2TYU!>_QTW z2>SYEuRkn*N&-FzLlAo*~<p=6ymO%*F{N!dD(=L^_CdTW>cH+o zHKK|%*h}E{knARadkUK=WDQ8;E79k4fk@2(pgu4V85y~mY%FX6E`!tw* z&gwW32i}oUnC-aF97>lE2>*iz4}L_W*b^2CrpWCXg3@S5Y@Q5zavN}5(uGW= zgEJaiX+Ttg62Hldi{nC8-6->`|kt5+U3%%Tek+%K^vj} zBUMMpWHPQg4tTs!8hUZAN{#eN6;jKakST12yv+)Sdx$EY88tOEpm`EBL4R}N#0l4q z9Xqx%opZPUJ^*ur$+F*Ot!i@q6J{v;W(-<9`BD W$Ee-yr>AuQ0000$QIUdOwX08XYy-uUWIkd*#ZN?lWf0aB7aNrT{q2 znKP%2jC~-Z0jpQ9?h+Fd;}#hi=_2Dk>(;Fc%*e<{%+Aiv&B@8B$<57uq*2ek<_h#K zNo)FO?YomEO>%w{0M08`tO$^?qGQL7-IKwr$&)Ah%3$cOUAxjsN=oitxNyN-zkc1^ zxN*bWym`}9S67>=swz8o@#00JHTQS#-kl-vVN<3|Y28u)u1l6I8CY0Y_(Nr7rIFLS zix)5cs-U3Yn`_suStsYtoij&{95DwE9y9`Kva+)5ReQ{tGiOXiMTKGQ(W6JJmoHx) zy=c)Q-xdK#N=gdYxN&3t&Ye5&i_Rx9bpOtsJLc4>Q)d7E{eUuhZ_@X=$lBefl&`?6b6B!ED;J$*uv&ty{Oui4!Mkmo8lz6BZWc)+`NZw3d?l zXJ%$r%J~bT-nVa`Nl#C=)So|p-dwtL$qsUU<;oRv_3Bk~`SN9(9@ef}waNmJ4O3H7 z^FrzRS}cSk^4C^@)Z0;!WRuIHq9RMX#Au_$!P&ECZRBNTWp)lxa$jCvZr|~&sxT6> z-3v2lV#}5-`N_%2T^t}91rQh*=rVu){3wa;9)=JXbdrC-kaLWyLJ*k+01Le1UUXY9 z>_saZHf*pgFsC&S#lja#g=>=lMvortDf&_z4sk{l(91Ihp;u*Q4U-PU#u|aPzyJY5 zu(fR2GP^E6Ki`6oAU7l=B)roU0H?&n#19o^DZ+v}HXlEJ+(yJTEiKK=o;}-0R7MqI z#R>HQWdM?L1PqKYM}@GCptf({ep!9xV|+CQpcm!G=EH{%TjgVrh%k!6Wxyy3Gjrxl zqpoSDPMvD2gOmV(5@f&x*98j}*kHI9bM@LE+$4aB6DNMA+&yy`Bj+?63>-Lc03q4P z$BrFq;^N|LV}gN{loVT*R0homF><96rca-4Q$PhtPrpm#1AKgZoErn+JbwK60b<}K zivclf)+{4djKpKvK+O*xJg_<#HENW3{P?k{tE;ngqlensTHB(Dmd2!BVkS(OVDj?v zERzUY3`G0;`@1#@K#@f#>ffNBoCAPphYcHMbRgNG6VWPMk=QGa>+9>SFjYln$dDm+ z4bIh1j99g70zw*iId0szfgT4!Axdu+dX706?@vPa376Uu5fZd^M_p=;&yFmCjY_-%$ksAc`?###kV*f^!{G zmI0d7h!G=f&JmstGdoAh$UnNF3eb?6Q?=Oa*`x?VLqj`=zI5oMrBaU2sbkerj{0E$ zV_UawwGPljNJxkoIdY`UF?(^&VMYGw4LtKsjAVv~hj(fcfS;dV8ySj|((BoT7D$Iu zW7I~CPDTy!l#(Z!OX$?8lSfkk>~XAC*+aQ4W|Kr? zdjR<)4UQ(HO0g*b5WpC)!843eIi!N-L%Oh~HRTZz5drey_R7P^+uPeiT8Ni{hiHK2 zLo0?-n9x~aMW&Ap8!ba09Tph(FaZO!V#m>}KJlY+Kf%}6w_U@D`^t|}H-YdSI&|nf zRl!qIfgzd;)DtD$5CEGuZ?;b9cFa>1tfx6qDMYST{9M%MbnV*pJxBDf1Hf_V-n(~i ze{C!g`kzoc=K%E#5V|8JO4LM8C#36i{@DOxpD7 z)vM>=!Glv3VI2S{DRklJ6SQ9j_ssE*HLMk|I+bTpaBy&tY`x9bR&&0H{sE$M=g#k| z1176YS4eojl7I97#YD<*d?WHstUQwltD>T!W_Ih=?W4aqcWNmB2MBjhPftIkBwR*k z#m2_wNdwPRmyul9eZ{Y?NkKp>vB>fwHh>J#<+ z{(buN`BDuimJt*b6s@_4?%lh8DzG?i+px#ErT+_F^@Bp!hNy5rNqIJmb`5jx4QrfR f{MYP%`|tQqpU<66n}ZZ300000NkvXXu0mjfL6BEg literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Images.png b/EditorExtensions/Resources/Images.png new file mode 100644 index 0000000000000000000000000000000000000000..ba2b3e9f67b2b02b4f42d0f1bb047ee5befabc71 GIT binary patch literal 1217 zcmV;y1U~zTP)&E5JD6jUrrxfC5SAss^|Zg$K>Q>>&VE6Xl`y6RaI3P;2!PhSL33D6(x?3 zbX}280UW=b6k8yG88@O=u9P!`ajbUM9G99>;qvYoF7L6A@$ zU@SxejE;`>+B|?J|K#1D5{GLCeTiU4$qu36)W+MH00uk+@RV?c@D}$=m!tp&Yyxny z{#*Co2tOa6$6Jvlal%9pQDB}XRFkiPd)=qqJ_zL^=yhLALpY$9Z9UYlI zKOq3*XKT@J0o)6+p z@=eRXdGEEj(H<9`LeV5~0`;{%`|$ul<_GZr+Qq}|gJ9ilE# zC4fdn_+G*h!ZAW80p#x|yx;{2jK0H8}3E&gq0N#zxs~girvh=K{c55R}{Y&_=x9B+!X)KVSl=WCG|RloIyg zOoVru0+>B3$5w7j58xF0{mgeG-@JFI10V+&hKuK8Ap#xy(T=s9MBrupLAHTTIe^U* z5Sbw+fSrWrghj$pMf$0X0Irp%)!2}&4q#e-w54Cdmk4qdfaw9e=DU%v_VvP62{aQx zO*q^>b_m_w-BuB7MjQ`ihWbyMP5E{|JBIm8%&6l;u(h^pyw(*#-E4Nj@*; zaPraaRoOG^0L z5o8OM@O`!vg60VCas91M7J)wVch9>AD1-=f2*`$f{V#xd7uSCQXh-;fH-JcR4H4*% zh$K&wYlBV<{Z!$J(uGz;M@55mMUf$00000NkvXXu0mjfTj4TW literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Package.ico b/EditorExtensions/Resources/Package.ico new file mode 100644 index 0000000000000000000000000000000000000000..27420cc5d899138f1cd09694057230f2912b6ffa GIT binary patch literal 7278 zcmeHMJx?1!5FLLIju>($i#oW>FG%aqQqv-rv~;#;I4ayAegc$G(<0$2l%_^P5E>#H zC@G?B-rKu5pEqZ7(t+g!FU-#OyxsAhd|Hc?q#}(*0A7`!Ws$EU&;`0D$DYXNis}tH z4n)4!M7}Tv^bN#3JCK__LJ|B+7)A^;L{KQbUJnjq|HT+eApFt9$?K*DlK#^7+R5n9 z|FVvP?KY=4{K;cw`{u z;JMxDcBx@JBMx~7k%rmtKH=Z0w<7bCpq@x2#8D>JFOjAxg~t5YGsEW`4+BRvVsJHfNDUo30h*m$+jjvRWASh*y;5Gf9 z>>y4e4b@MqQ|iy?(9rse`lo&WFRicW{>SF?1TR(xA=Sm`OzZiD<_)}*JR1=Cms81= zN*u=$%ho@XT>F^RVF~+m1i`{wZ2b@fD$Xqsf)(oEOCAfCmmo2;;z0`Pwmv6@*5=Dz zP_GAGdA>$Haaw^zd>R8EER{M4LkKEHb7H-ns`r$JU03MrEm>?V;GM%vf?QnHCxJ~2 z#dEph%Gdge=W_Lr$}eiy`Yx{O>QCdm z_wzT~|NH*_Nk0okWqrQ%d2_k?i{gyR*ZMB5>gperU(~Mk70>1BcRB6`4ek$z-etzE zg|W!|MHs;>St$310kTz5^(P1jOc@zNYVA9SEGdG?HZRYP)d(|SfPh~YcfP1tS} zJMW%xZ)uL^y1%Ah#BJ7kth73^IK%c?CzRBYmed` literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/Scripts/CoffeeScript-1.4.js b/EditorExtensions/Resources/Scripts/CoffeeScript-1.4.js new file mode 100644 index 000000000..9bc5d672c --- /dev/null +++ b/EditorExtensions/Resources/Scripts/CoffeeScript-1.4.js @@ -0,0 +1,8 @@ +/** + * CoffeeScript Compiler v1.3.3 + * http://coffeescript.org + * + * Copyright 2011, Jeremy Ashkenas + * Released under the MIT License + */ +(function(root){var CoffeeScript=function(){function require(a){return require[a]}require["./helpers"]=new function(){var a=this;(function(){var b,c;a.starts=function(a,b,c){return b===a.substr(c,b.length)},a.ends=function(a,b,c){var d;d=b.length;return b===a.substr(a.length-d-(c||0),d)},a.compact=function(a){var b,c,d,e;e=[];for(c=0,d=a.length;c=0)f+=1;else if(j=g[0],t.call(d,j)>=0)f-=1;a+=1}return a-1},a.prototype.removeLeadingNewlines=function(){var a,b,c,d,e;e=this.tokens;for(a=c=0,d=e.length;c=0)))return 1;d.splice(b,1);return 0})},a.prototype.closeOpenCalls=function(){var a,b;b=function(a,b){var c;return(c=a[0])===")"||c==="CALL_END"||a[0]==="OUTDENT"&&this.tag(b-1)===")"},a=function(a,b){return this.tokens[a[0]==="OUTDENT"?b-1:b][0]="CALL_END"};return this.scanTokens(function(c,d){c[0]==="CALL_START"&&this.detectEnd(d+1,b,a);return 1})},a.prototype.closeOpenIndexes=function(){var a,b;b=function(a,b){var c;return(c=a[0])==="]"||c==="INDEX_END"},a=function(a,b){return a[0]="INDEX_END"};return this.scanTokens(function(c,d){c[0]==="INDEX_START"&&this.detectEnd(d+1,b,a);return 1})},a.prototype.addImplicitBraces=function(){var a,b,c,f,g,i,j,k;f=[],g=null,k=null,c=!0,i=0,j=0,b=function(a,b){var d,e,f,g,i,m;i=this.tokens.slice(b+1,b+3+1||9e9),d=i[0],g=i[1],f=i[2];if("HERECOMMENT"===(d!=null?d[0]:void 0))return!1;e=a[0],t.call(l,e)>=0&&(c=!1);return(e==="TERMINATOR"||e==="OUTDENT"||t.call(h,e)>=0&&c&&b-j!==1)&&(!k&&this.tag(b-1)!==","||(g!=null?g[0]:void 0)!==":"&&((d!=null?d[0]:void 0)!=="@"||(f!=null?f[0]:void 0)!==":"))||e===","&&d&&(m=d[0])!=="IDENTIFIER"&&m!=="NUMBER"&&m!=="STRING"&&m!=="@"&&m!=="TERMINATOR"&&m!=="OUTDENT"},a=function(a,b){var c;c=this.generate("}","}",a[2]);return this.tokens.splice(b,0,c)};return this.scanTokens(function(h,i,m){var n,o,p,q,r,s,u,v;if(u=q=h[0],t.call(e,u)>=0){f.push([q==="INDENT"&&this.tag(i-1)==="{"?"{":q,i]);return 1}if(t.call(d,q)>=0){g=f.pop();return 1}if(q!==":"||(n=this.tag(i-2))!==":"&&((v=f[f.length-1])!=null?v[0]:void 0)==="{")return 1;c=!0,j=i+1,f.push(["{"]),o=n==="@"?i-2:i-1;while(this.tag(o-2)==="HERECOMMENT")o-=2;p=this.tag(o-1),k=!p||t.call(l,p)>=0,s=new String("{"),s.generated=!0,r=this.generate("{",s,h[2]),m.splice(o,0,r),this.detectEnd(i+2,b,a);return 2})},a.prototype.addImplicitParentheses=function(){var a,b,c,d,e;c=e=d=!1,b=function(a,b){var c,g,i,j;g=a[0];if(!e&&a.fromThen)return!0;if(g==="IF"||g==="ELSE"||g==="CATCH"||g==="->"||g==="=>"||g==="CLASS")e=!0;if(g==="IF"||g==="ELSE"||g==="SWITCH"||g==="TRY"||g==="=")d=!0;if((g==="."||g==="?."||g==="::")&&this.tag(b-1)==="OUTDENT")return!0;return!a.generated&&this.tag(b-1)!==","&&(t.call(h,g)>=0||g==="INDENT"&&!d)&&(g!=="INDENT"||(i=this.tag(b-2))!=="CLASS"&&i!=="EXTENDS"&&(j=this.tag(b-1),t.call(f,j)<0)&&(!(c=this.tokens[b+1])||!c.generated||c[0]!=="{"))},a=function(a,b){return this.tokens.splice(b,0,this.generate("CALL_END",")",a[2]))};return this.scanTokens(function(f,h,k){var m,n,o,p,q,r,s,u;q=f[0];if(q==="CLASS"||q==="IF"||q==="FOR"||q==="WHILE")c=!0;r=k.slice(h-1,h+1+1||9e9),p=r[0],n=r[1],o=r[2],m=!c&&q==="INDENT"&&o&&o.generated&&o[0]==="{"&&p&&(s=p[0],t.call(i,s)>=0),e=!1,d=!1,t.call(l,q)>=0&&(c=!1),p&&!p.spaced&&q==="?"&&(f.call=!0);if(f.fromThen)return 1;if(!(m||(p!=null?p.spaced:void 0)&&(p.call||(u=p[0],t.call(i,u)>=0))&&(t.call(g,q)>=0||!f.spaced&&!f.newLine&&t.call(j,q)>=0)))return 1;k.splice(h,0,this.generate("CALL_START","(",f[2])),this.detectEnd(h+1,b,a),p[0]==="?"&&(p[0]="FUNC_EXIST");return 2})},a.prototype.addImplicitIndentation=function(){var a,b,c,d,e;e=c=d=null,b=function(a,b){var c;return a[1]!==";"&&(c=a[0],t.call(m,c)>=0)&&(a[0]!=="ELSE"||e==="IF"||e==="THEN")},a=function(a,b){return this.tokens.splice(this.tag(b-1)===","?b-1:b,0,d)};return this.scanTokens(function(f,g,h){var i,j,k;i=f[0];if(i==="TERMINATOR"&&this.tag(g+1)==="THEN"){h.splice(g,1);return 0}if(i==="ELSE"&&this.tag(g-1)!=="OUTDENT"){h.splice.apply(h,[g,0].concat(u.call(this.indentation(f))));return 2}if(i==="CATCH"&&((j=this.tag(g+2))==="OUTDENT"||j==="TERMINATOR"||j==="FINALLY")){h.splice.apply(h,[g+2,0].concat(u.call(this.indentation(f))));return 4}if(t.call(n,i)>=0&&this.tag(g+1)!=="INDENT"&&(i!=="ELSE"||this.tag(g+1)!=="IF")){e=i,k=this.indentation(f,!0),c=k[0],d=k[1],e==="THEN"&&(c.fromThen=!0),h.splice(g+1,0,c),this.detectEnd(g+2,b,a),i==="THEN"&&h.splice(g,1);return 1}return 1})},a.prototype.tagPostfixConditionals=function(){var a,b,c;c=null,b=function(a,b){var c;return(c=a[0])==="TERMINATOR"||c==="INDENT"},a=function(a,b){if(a[0]!=="INDENT"||a.generated&&!a.fromThen)return c[0]="POST_"+c[0]};return this.scanTokens(function(d,e){if(d[0]!=="IF")return 1;c=d,this.detectEnd(e+1,b,a);return 1})},a.prototype.indentation=function(a,b){var c,d;b==null&&(b=!1),c=["INDENT",2,a[2]],d=["OUTDENT",2,a[2]],b&&(c.generated=d.generated=!0);return[c,d]},a.prototype.generate=function(a,b,c){var d;d=[a,b,c],d.generated=!0;return d},a.prototype.tag=function(a){var b;return(b=this.tokens[a])!=null?b[0]:void 0};return a}(),b=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],a.INVERSES=k={},e=[],d=[];for(q=0,r=b.length;q","=>","[","(","{","--","++"],j=["+","-"],f=["->","=>","{","[",","],h=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],n=["ELSE","->","=>","TRY","FINALLY","THEN"],m=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],l=["TERMINATOR","INDENT","OUTDENT"]}).call(this)},require["./lexer"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X=[].indexOf||function(a){for(var b=0,c=this.length;b=0||X.call(g,c)>=0)&&(j=c.toUpperCase(),j==="WHEN"&&(l=this.tag(),X.call(v,l)>=0)?j="LEADING_WHEN":j==="FOR"?this.seenFor=!0:j==="UNLESS"?j="IF":X.call(O,j)>=0?j="UNARY":X.call(H,j)>=0&&(j!=="INSTANCEOF"&&this.seenFor?(j="FOR"+j,this.seenFor=!1):(j="RELATION",this.value()==="!"&&(this.tokens.pop(),c="!"+c)))),X.call(t,c)>=0&&(b?(j="IDENTIFIER",c=new String(c),c.reserved=!0):X.call(I,c)>=0&&this.error('reserved word "'+c+'"')),b||(X.call(e,c)>=0&&(c=f[c]),j=function(){switch(c){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":return"BOOL";case"break":case"continue":return"STATEMENT";default:return j}}()),this.token(j,c),a&&this.token(":",":");return d.length},a.prototype.numberToken=function(){var a,b,c,d,e;if(!(c=E.exec(this.chunk)))return 0;d=c[0],/^0[BOX]/.test(d)?this.error("radix prefix '"+d+"' must be lowercase"):/E/.test(d)&&!/^0x/.test(d)?this.error("exponential notation '"+d+"' must be indicated with a lowercase 'e'"):/^0\d*[89]/.test(d)?this.error("decimal literal '"+d+"' must not be prefixed with '0'"):/^0\d+/.test(d)&&this.error("octal literal '"+d+"' must be prefixed with '0o'"),b=d.length;if(e=/^0o([0-7]+)/.exec(d))d="0x"+parseInt(e[1],8).toString(16);if(a=/^0b([01]+)/.exec(d))d="0x"+parseInt(a[1],2).toString(16);this.token("NUMBER",d);return b},a.prototype.stringToken=function(){var a,b,c;switch(this.chunk.charAt(0)){case"'":if(!(a=L.exec(this.chunk)))return 0;this.token("STRING",(c=a[0]).replace(A,"\\\n"));break;case'"':if(!(c=this.balancedString(this.chunk,'"')))return 0;0=0))return 0;if(!(c=G.exec(this.chunk)))return 0;g=c,c=g[0],e=g[1],a=g[2],e.slice(0,2)==="/*"&&this.error("regular expressions cannot begin with `*`"),e==="//"&&(e="/(?:)/"),this.token("REGEX",""+e+a);return c.length},a.prototype.heregexToken=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n;d=a[0],b=a[1],c=a[2];if(0>b.indexOf("#{")){e=b.replace(o,"").replace(/\//g,"\\/"),e.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(e||"(?:)")+"/"+c);return d.length}this.token("IDENTIFIER","RegExp"),this.tokens.push(["CALL_START","("]),g=[],k=this.interpolateString(b,{regex:!0});for(i=0,j=k.length;ithis.indent){if(d){this.indebt=f-this.indent,this.suppressNewlines();return b.length}a=f-this.indent+this.outdebt,this.token("INDENT",a),this.indents.push(a),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0}else this.indebt=0,this.outdentToken(this.indent-f,d);this.indent=f;return b.length},a.prototype.outdentToken=function(a,b){var c,d;while(a>0)d=this.indents.length-1,this.indents[d]===void 0?a=0:this.indents[d]===this.outdebt?(a-=this.outdebt,this.outdebt=0):this.indents[d]=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned");if((h=b[1])==="||"||h==="&&"){b[0]="COMPOUND_ASSIGN",b[1]+="=";return f.length}}if(f===";")this.seenFor=!1,e="TERMINATOR";else if(X.call(z,f)>=0)e="MATH";else if(X.call(i,f)>=0)e="COMPARE";else if(X.call(j,f)>=0)e="COMPOUND_ASSIGN";else if(X.call(O,f)>=0)e="UNARY";else if(X.call(K,f)>=0)e="SHIFT";else if(X.call(x,f)>=0||f==="?"&&(b!=null?b.spaced:void 0))e="LOGIC";else if(b&&!b.spaced)if(f==="("&&(k=b[0],X.call(c,k)>=0))b[0]==="?"&&(b[0]="FUNC_EXIST"),e="CALL_START";else if(f==="["&&(l=b[0],X.call(q,l)>=0)){e="INDEX_START";switch(b[0]){case"?":b[0]="INDEX_SOAK"}}switch(f){case"(":case"{":case"[":this.ends.push(r[f]);break;case")":case"}":case"]":this.pair(f)}this.token(e,f);return f.length},a.prototype.sanitizeHeredoc=function(a,b){var c,d,e,f,g;e=b.indent,d=b.herecomment;if(d){l.test(a)&&this.error('block comment cannot contain "*/", starting');if(a.indexOf("\n")<=0)return a}else while(f=m.exec(a)){c=f[1];if(e===null||0<(g=c.length)&&gj;d=1<=j?++i:--i){if(c){--c;continue}switch(e=a.charAt(d)){case"\\":++c;continue;case b:h.pop();if(!h.length)return a.slice(0,d+1||9e9);b=h[h.length-1];continue}b!=="}"||e!=='"'&&e!=="'"?b==="}"&&e==="/"&&(f=n.exec(a.slice(d))||G.exec(a.slice(d)))?c+=f[0].length-1:b==="}"&&e==="{"?h.push(b="}"):b==='"'&&g==="#"&&e==="{"&&h.push(b="}"):h.push(b=e),g=e}return this.error("missing "+h.pop()+", starting")},a.prototype.interpolateString=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;c==null&&(c={}),e=c.heredoc,m=c.regex,o=[],l=0,f=-1;while(j=b.charAt(f+=1)){if(j==="\\"){f+=1;continue}if(j!=="#"||b.charAt(f+1)!=="{"||!(d=this.balancedString(b.slice(f+1),"}")))continue;l1&&(k.unshift(["(","(",this.line]),k.push([")",")",this.line])),o.push(["TOKENS",k])}f+=d.length,l=f+1}f>l&&l1)&&this.token("(","(");for(f=q=0,r=o.length;q|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/,P=/^[^\n\S]+/,h=/^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/,d=/^[-=]>/,B=/^(?:\n[^\n\S]*)+/,L=/^'[^\\']*(?:\\.[^\\']*)*'/,s=/^`[^\\`]*(?:\\.[^\\`]*)*`/,G=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,n=/^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/,o=/\s+(?:#.*)?/g,A=/\n/g,m=/\n+([^\n\S]*)/g,l=/\*\//,w=/^\s*(?:,|\??\.(?![.\d])|::)/,N=/\s+$/,j=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|="],O=["!","~","NEW","TYPEOF","DELETE","DO"],x=["&&","||","&","|","^"],K=["<<",">>",">>>"],i=["==","!=","<",">","<=",">="],z=["*","/","%"],H=["IN","OF","INSTANCEOF"],b=["TRUE","FALSE"],C=["NUMBER","REGEX","BOOL","NULL","UNDEFINED","++","--","]"],D=C.concat(")","}","THIS","IDENTIFIER","STRING"),c=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER"],q=c.concat("NUMBER","BOOL","NULL","UNDEFINED"),v=["INDENT","OUTDENT","TERMINATOR"]}).call(this)},require["./parser"]=new function(){var a=this,b=function(){var a={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Block:5,TERMINATOR:6,Line:7,Expression:8,Statement:9,Return:10,Comment:11,STATEMENT:12,Value:13,Invocation:14,Code:15,Operation:16,Assign:17,If:18,Try:19,While:20,For:21,Switch:22,Class:23,Throw:24,INDENT:25,OUTDENT:26,Identifier:27,IDENTIFIER:28,AlphaNumeric:29,NUMBER:30,STRING:31,Literal:32,JS:33,REGEX:34,DEBUGGER:35,UNDEFINED:36,NULL:37,BOOL:38,Assignable:39,"=":40,AssignObj:41,ObjAssignable:42,":":43,ThisProperty:44,RETURN:45,HERECOMMENT:46,PARAM_START:47,ParamList:48,PARAM_END:49,FuncGlyph:50,"->":51,"=>":52,OptComma:53,",":54,Param:55,ParamVar:56,"...":57,Array:58,Object:59,Splat:60,SimpleAssignable:61,Accessor:62,Parenthetical:63,Range:64,This:65,".":66,"?.":67,"::":68,Index:69,INDEX_START:70,IndexValue:71,INDEX_END:72,INDEX_SOAK:73,Slice:74,"{":75,AssignList:76,"}":77,CLASS:78,EXTENDS:79,OptFuncExist:80,Arguments:81,SUPER:82,FUNC_EXIST:83,CALL_START:84,CALL_END:85,ArgList:86,THIS:87,"@":88,"[":89,"]":90,RangeDots:91,"..":92,Arg:93,SimpleArgs:94,TRY:95,Catch:96,FINALLY:97,CATCH:98,THROW:99,"(":100,")":101,WhileSource:102,WHILE:103,WHEN:104,UNTIL:105,Loop:106,LOOP:107,ForBody:108,FOR:109,ForStart:110,ForSource:111,ForVariables:112,OWN:113,ForValue:114,FORIN:115,FOROF:116,BY:117,SWITCH:118,Whens:119,ELSE:120,When:121,LEADING_WHEN:122,IfBlock:123,IF:124,POST_IF:125,UNARY:126,"-":127,"+":128,"--":129,"++":130,"?":131,MATH:132,SHIFT:133,COMPARE:134,LOGIC:135,RELATION:136,COMPOUND_ASSIGN:137,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],performAction:function(a,b,c,d,e,f,g){var h=f.length-1;switch(e){case 1:return this.$=new d.Block;case 2:return this.$=f[h];case 3:return this.$=f[h-1];case 4:this.$=d.Block.wrap([f[h]]);break;case 5:this.$=f[h-2].push(f[h]);break;case 6:this.$=f[h-1];break;case 7:this.$=f[h];break;case 8:this.$=f[h];break;case 9:this.$=f[h];break;case 10:this.$=f[h];break;case 11:this.$=new d.Literal(f[h]);break;case 12:this.$=f[h];break;case 13:this.$=f[h];break;case 14:this.$=f[h];break;case 15:this.$=f[h];break;case 16:this.$=f[h];break;case 17:this.$=f[h];break;case 18:this.$=f[h];break;case 19:this.$=f[h];break;case 20:this.$=f[h];break;case 21:this.$=f[h];break;case 22:this.$=f[h];break;case 23:this.$=f[h];break;case 24:this.$=new d.Block;break;case 25:this.$=f[h-1];break;case 26:this.$=new d.Literal(f[h]);break;case 27:this.$=new d.Literal(f[h]);break;case 28:this.$=new d.Literal(f[h]);break;case 29:this.$=f[h];break;case 30:this.$=new d.Literal(f[h]);break;case 31:this.$=new d.Literal(f[h]);break;case 32:this.$=new d.Literal(f[h]);break;case 33:this.$=new d.Undefined;break;case 34:this.$=new d.Null;break;case 35:this.$=new d.Bool(f[h]);break;case 36:this.$=new d.Assign(f[h-2],f[h]);break;case 37:this.$=new d.Assign(f[h-3],f[h]);break;case 38:this.$=new d.Assign(f[h-4],f[h-1]);break;case 39:this.$=new d.Value(f[h]);break;case 40:this.$=new d.Assign(new d.Value(f[h-2]),f[h],"object");break;case 41:this.$=new d.Assign(new d.Value(f[h-4]),f[h-1],"object");break;case 42:this.$=f[h];break;case 43:this.$=f[h];break;case 44:this.$=f[h];break;case 45:this.$=f[h];break;case 46:this.$=new d.Return(f[h]);break;case 47:this.$=new d.Return;break;case 48:this.$=new d.Comment(f[h]);break;case 49:this.$=new d.Code(f[h-3],f[h],f[h-1]);break;case 50:this.$=new d.Code([],f[h],f[h-1]);break;case 51:this.$="func";break;case 52:this.$="boundfunc";break;case 53:this.$=f[h];break;case 54:this.$=f[h];break;case 55:this.$=[];break;case 56:this.$=[f[h]];break;case 57:this.$=f[h-2].concat(f[h]);break;case 58:this.$=f[h-3].concat(f[h]);break;case 59:this.$=f[h-5].concat(f[h-2]);break;case 60:this.$=new d.Param(f[h]);break;case 61:this.$=new d.Param(f[h-1],null,!0);break;case 62:this.$=new d.Param(f[h-2],f[h]);break;case 63:this.$=f[h];break;case 64:this.$=f[h];break;case 65:this.$=f[h];break;case 66:this.$=f[h];break;case 67:this.$=new d.Splat(f[h-1]);break;case 68:this.$=new d.Value(f[h]);break;case 69:this.$=f[h-1].add(f[h]);break;case 70:this.$=new d.Value(f[h-1],[].concat(f[h]));break;case 71:this.$=f[h];break;case 72:this.$=f[h];break;case 73:this.$=new d.Value(f[h]);break;case 74:this.$=new d.Value(f[h]);break;case 75:this.$=f[h];break;case 76:this.$=new d.Value(f[h]);break;case 77:this.$=new d.Value(f[h]);break;case 78:this.$=new d.Value(f[h]);break;case 79:this.$=f[h];break;case 80:this.$=new d.Access(f[h]);break;case 81:this.$=new d.Access(f[h],"soak");break;case 82:this.$=[new d.Access(new d.Literal("prototype")),new d.Access(f[h])];break;case 83:this.$=new d.Access(new d.Literal("prototype"));break;case 84:this.$=f[h];break;case 85:this.$=f[h-1];break;case 86:this.$=d.extend(f[h],{soak:!0});break;case 87:this.$=new d.Index(f[h]);break;case 88:this.$=new d.Slice(f[h]);break;case 89:this.$=new d.Obj(f[h-2],f[h-3].generated);break;case 90:this.$=[];break;case 91:this.$=[f[h]];break;case 92:this.$=f[h-2].concat(f[h]);break;case 93:this.$=f[h-3].concat(f[h]);break;case 94:this.$=f[h-5].concat(f[h-2]);break;case 95:this.$=new d.Class;break;case 96:this.$=new d.Class(null,null,f[h]);break;case 97:this.$=new d.Class(null,f[h]);break;case 98:this.$=new d.Class(null,f[h-1],f[h]);break;case 99:this.$=new d.Class(f[h]);break;case 100:this.$=new d.Class(f[h-1],null,f[h]);break;case 101:this.$=new d.Class(f[h-2],f[h]);break;case 102:this.$=new d.Class(f[h-3],f[h-1],f[h]);break;case 103:this.$=new d.Call(f[h-2],f[h],f[h-1]);break;case 104:this.$=new d.Call(f[h-2],f[h],f[h-1]);break;case 105:this.$=new d.Call("super",[new d.Splat(new d.Literal("arguments"))]);break;case 106:this.$=new d.Call("super",f[h]);break;case 107:this.$=!1;break;case 108:this.$=!0;break;case 109:this.$=[];break;case 110:this.$=f[h-2];break;case 111:this.$=new d.Value(new d.Literal("this"));break;case 112:this.$=new d.Value(new d.Literal("this"));break;case 113:this.$=new d.Value(new d.Literal("this"),[new d.Access(f[h])],"this");break;case 114:this.$=new d.Arr([]);break;case 115:this.$=new d.Arr(f[h-2]);break;case 116:this.$="inclusive";break;case 117:this.$="exclusive";break;case 118:this.$=new d.Range(f[h-3],f[h-1],f[h-2]);break;case 119:this.$=new d.Range(f[h-2],f[h],f[h-1]);break;case 120:this.$=new d.Range(f[h-1],null,f[h]);break;case 121:this.$=new d.Range(null,f[h],f[h-1]);break;case 122:this.$=new d.Range(null,null,f[h]);break;case 123:this.$=[f[h]];break;case 124:this.$=f[h-2].concat(f[h]);break;case 125:this.$=f[h-3].concat(f[h]);break;case 126:this.$=f[h-2];break;case 127:this.$=f[h-5].concat(f[h-2]);break;case 128:this.$=f[h];break;case 129:this.$=f[h];break;case 130:this.$=f[h];break;case 131:this.$=[].concat(f[h-2],f[h]);break;case 132:this.$=new d.Try(f[h]);break;case 133:this.$=new d.Try(f[h-1],f[h][0],f[h][1]);break;case 134:this.$=new d.Try(f[h-2],null,null,f[h]);break;case 135:this.$=new d.Try(f[h-3],f[h-2][0],f[h-2][1],f[h]);break;case 136:this.$=[f[h-1],f[h]];break;case 137:this.$=new d.Throw(f[h]);break;case 138:this.$=new d.Parens(f[h-1]);break;case 139:this.$=new d.Parens(f[h-2]);break;case 140:this.$=new d.While(f[h]);break;case 141:this.$=new d.While(f[h-2],{guard:f[h]});break;case 142:this.$=new d.While(f[h],{invert:!0});break;case 143:this.$=new d.While(f[h-2],{invert:!0,guard:f[h]});break;case 144:this.$=f[h-1].addBody(f[h]);break;case 145:this.$=f[h].addBody(d.Block.wrap([f[h-1]]));break;case 146:this.$=f[h].addBody(d.Block.wrap([f[h-1]]));break;case 147:this.$=f[h];break;case 148:this.$=(new d.While(new d.Literal("true"))).addBody(f[h]);break;case 149:this.$=(new d.While(new d.Literal("true"))).addBody(d.Block.wrap([f[h]]));break;case 150:this.$=new d.For(f[h-1],f[h]);break;case 151:this.$=new d.For(f[h-1],f[h]);break;case 152:this.$=new d.For(f[h],f[h-1]);break;case 153:this.$={source:new d.Value(f[h])};break;case 154:this.$=function(){f[h].own=f[h-1].own,f[h].name=f[h-1][0],f[h].index=f[h-1][1];return f[h]}();break;case 155:this.$=f[h];break;case 156:this.$=function(){f[h].own=!0;return f[h]}();break;case 157:this.$=f[h];break;case 158:this.$=f[h];break;case 159:this.$=new d.Value(f[h]);break;case 160:this.$=new d.Value(f[h]);break;case 161:this.$=[f[h]];break;case 162:this.$=[f[h-2],f[h]];break;case 163:this.$={source:f[h]};break;case 164:this.$={source:f[h],object:!0};break;case 165:this.$={source:f[h-2],guard:f[h]};break;case 166:this.$={source:f[h-2],guard:f[h],object:!0};break;case 167:this.$={source:f[h-2],step:f[h]};break;case 168:this.$={source:f[h-4],guard:f[h-2],step:f[h]};break;case 169:this.$={source:f[h-4],step:f[h-2],guard:f[h]};break;case 170:this.$=new d.Switch(f[h-3],f[h-1]);break;case 171:this.$=new d.Switch(f[h-5],f[h-3],f[h-1]);break;case 172:this.$=new d.Switch(null,f[h-1]);break;case 173:this.$=new d.Switch(null,f[h-3],f[h-1]);break;case 174:this.$=f[h];break;case 175:this.$=f[h-1].concat(f[h]);break;case 176:this.$=[[f[h-1],f[h]]];break;case 177:this.$=[[f[h-2],f[h-1]]];break;case 178:this.$=new d.If(f[h-1],f[h],{type:f[h-2]});break;case 179:this.$=f[h-4].addElse(new d.If(f[h-1],f[h],{type:f[h-2]}));break;case 180:this.$=f[h];break;case 181:this.$=f[h-2].addElse(f[h]);break;case 182:this.$=new d.If(f[h],d.Block.wrap([f[h-2]]),{type:f[h-1],statement:!0});break;case 183:this.$=new d.If(f[h],d.Block.wrap([f[h-2]]),{type:f[h-1],statement:!0});break;case 184:this.$=new d.Op(f[h-1],f[h]);break;case 185:this.$=new d.Op("-",f[h]);break;case 186:this.$=new d.Op("+",f[h]);break;case 187:this.$=new d.Op("--",f[h]);break;case 188:this.$=new d.Op("++",f[h]);break;case 189:this.$=new d.Op("--",f[h-1],null,!0);break;case 190:this.$=new d.Op("++",f[h-1],null,!0);break;case 191:this.$=new d.Existence(f[h-1]);break;case 192:this.$=new d.Op("+",f[h-2],f[h]);break;case 193:this.$=new d.Op("-",f[h-2],f[h]);break;case 194:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 195:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 196:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 197:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 198:this.$=function(){return f[h-1].charAt(0)==="!"?(new d.Op(f[h-1].slice(1),f[h-2],f[h])).invert():new d.Op(f[h-1],f[h-2],f[h])}();break;case 199:this.$=new d.Assign(f[h-2],f[h],f[h-1]);break;case 200:this.$=new d.Assign(f[h-4],f[h-1],f[h-3]);break;case 201:this.$=new d.Extends(f[h-2],f[h])}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}],defaultActions:{60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]},parseError:function(a,b){throw new Error(a)},parse:function(a){function o(){var a;a=b.lexer.lex()||1,typeof a!="number"&&(a=b.symbols_[a]||a);return a}function n(a){c.length=c.length-2*a,d.length=d.length-a,e.length=e.length-a}var b=this,c=[0],d=[null],e=[],f=this.table,g="",h=0,i=0,j=0,k=2,l=1;this.lexer.setInput(a),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var m=this.lexer.yylloc;e.push(m),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var p,q,r,s,t,u,v={},w,x,y,z;for(;;){r=c[c.length-1],this.defaultActions[r]?s=this.defaultActions[r]:(p==null&&(p=o()),s=f[r]&&f[r][p]);_handle_error:if(typeof s=="undefined"||!s.length||!s[0]){if(!j){z=[];for(w in f[r])this.terminals_[w]&&w>2&&z.push("'"+this.terminals_[w]+"'");var A="";this.lexer.showPosition?A="Parse error on line "+(h+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+z.join(", ")+", got '"+this.terminals_[p]+"'":A="Parse error on line "+(h+1)+": Unexpected "+(p==1?"end of input":"'"+(this.terminals_[p]||p)+"'"),this.parseError(A,{text:this.lexer.match,token:this.terminals_[p]||p,line:this.lexer.yylineno,loc:m,expected:z})}if(j==3){if(p==l)throw new Error(A||"Parsing halted.");i=this.lexer.yyleng,g=this.lexer.yytext,h=this.lexer.yylineno,m=this.lexer.yylloc,p=o()}for(;;){if(k.toString()in f[r])break;if(r==0)throw new Error(A||"Parsing halted.");n(1),r=c[c.length-1]}q=p,p=k,r=c[c.length-1],s=f[r]&&f[r][k],j=3}if(s[0]instanceof Array&&s.length>1)throw new Error("Parse Error: multiple actions possible at state: "+r+", token: "+p);switch(s[0]){case 1:c.push(p),d.push(this.lexer.yytext),e.push(this.lexer.yylloc),c.push(s[1]),p=null,q?(p=q,q=null):(i=this.lexer.yyleng,g=this.lexer.yytext,h=this.lexer.yylineno,m=this.lexer.yylloc,j>0&&j--);break;case 2:x=this.productions_[s[1]][1],v.$=d[d.length-x],v._$={first_line:e[e.length-(x||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(x||1)].first_column,last_column:e[e.length-1].last_column},u=this.performAction.call(v,g,i,h,this.yy,s[1],d,e);if(typeof u!="undefined")return u;x&&(c=c.slice(0,-1*x*2),d=d.slice(0,-1*x),e=e.slice(0,-1*x)),c.push(this.productions_[s[1]][0]),d.push(v.$),e.push(v._$),y=f[c[c.length-2]][c[c.length-1]],c.push(y);break;case 3:return!0}}return!0}};undefined;return a}();typeof require!="undefined"&&typeof a!="undefined"&&(a.parser=b,a.parse=function(){return b.parse.apply(b,arguments)},a.main=function(b){if(!b[1])throw new Error("Usage: "+b[0]+" FILE");if(typeof process!="undefined")var c=require("fs").readFileSync(require("path").join(process.cwd(),b[1]),"utf8");else var d=require("file").path(require("file").cwd()),c=d.join(b[1]).read({charset:"utf-8"});return a.parser.parse(c)},typeof module!="undefined"&&require.main===module&&a.main(typeof process!="undefined"?process.argv.slice(1):require("system").args))},require["./scope"]=new function(){var a=this;(function(){var b,c,d,e;e=require("./helpers"),c=e.extend,d=e.last,a.Scope=b=function(){function a(b,c,d){this.parent=b,this.expressions=c,this.method=d,this.variables=[{name:"arguments",type:"arguments"}],this.positions={},this.parent||(a.root=this)}a.root=null,a.prototype.add=function(a,b,c){if(this.shared&&!c)return this.parent.add(a,b,c);return Object.prototype.hasOwnProperty.call(this.positions,a)?this.variables[this.positions[a]].type=b:this.positions[a]=this.variables.push({name:a,type:b})-1},a.prototype.namedMethod=function(){if(this.method.name||!this.parent)return this.method;return this.parent.namedMethod()},a.prototype.find=function(a){if(this.check(a))return!0;this.add(a,"var");return!1},a.prototype.parameter=function(a){if(!this.shared||!this.parent.check(a,!0))return this.add(a,"param")},a.prototype.check=function(a){var b;return!!(this.type(a)||((b=this.parent)!=null?b.check(a):void 0))},a.prototype.temporary=function(a,b){return a.length>1?"_"+a+(b>1?b-1:""):"_"+(b+parseInt(a,36)).toString(36).replace(/\d/g,"a")},a.prototype.type=function(a){var b,c,d,e;e=this.variables;for(c=0,d=e.length;c1&&a.level>=w?"("+c+")":c},b.prototype.compileRoot=function(a){var b,c,d,e,f,g;a.indent=a.bare?"":R,a.scope=new N(null,this,null),a.level=z,this.spaced=!0,e="",a.bare||(f=function(){var a,b,e,f;e=this.expressions,f=[];for(d=a=0,b=e.length;a=u?"(void 0)":"void 0"};return b}(e),a.Null=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}bl(b,a),b.prototype.isAssignable=D,b.prototype.isComplex=D,b.prototype.compileNode=function(){return"null"};return b}(e),a.Bool=function(a){function b(a){this.val=a}bl(b,a),b.prototype.isAssignable=D,b.prototype.isComplex=D,b.prototype.compileNode=function(){return this.val};return b}(e),a.Return=K=function(a){function b(a){a&&!a.unwrap().isUndefined&&(this.expression=a)}bl(b,a),b.prototype.children=["expression"],b.prototype.isStatement=Y,b.prototype.makeReturn=S,b.prototype.jumps=S,b.prototype.compile=function(a,c){var d,e;d=(e=this.expression)!=null?e.makeReturn():void 0;return!d||d instanceof b?b.__super__.compile.call(this,a,c):d.compile(a,c)},b.prototype.compileNode=function(a){return this.tab+("return"+[this.expression?" "+this.expression.compile(a,y):void 0]+";")};return b}(e),a.Value=W=function(a){function b(a,c,d){if(!c&&a instanceof b)return a;this.base=a,this.properties=c||[],d&&(this[d]=!0);return this}bl(b,a),b.prototype.children=["base","properties"],b.prototype.add=function(a){this.properties=this.properties.concat(a);return this},b.prototype.hasProperties=function(){return!!this.properties.length},b.prototype.isArray=function(){return!this.properties.length&&this.base instanceof c},b.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},b.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},b.prototype.isSimpleNumber=function(){return this.base instanceof A&&L.test(this.base.value)},b.prototype.isString=function(){return this.base instanceof A&&q.test(this.base.value)},b.prototype.isAtomic=function(){var a,b,c,d;d=this.properties.concat(this.base);for(b=0,c=d.length;b"+this.equals],i=n[0],e=n[1],c=this.stepNum?+this.stepNum>0?""+i+" "+this.toVar:""+e+" "+this.toVar:h?(o=[+this.fromNum,+this.toNum],d=o[0],l=o[1],o,d<=l?""+i+" "+l:""+e+" "+l):(b=""+this.fromVar+" <= "+this.toVar,""+b+" ? "+i+" "+this.toVar+" : "+e+" "+this.toVar),k=this.stepVar?""+f+" += "+this.stepVar:h?j?d<=l?"++"+f:"--"+f:d<=l?""+f+"++":""+f+"--":j?""+b+" ? ++"+f+" : --"+f:""+b+" ? "+f+"++ : "+f+"--",j&&(m=""+g+" = "+m),j&&(k=""+g+" = "+k);return""+m+"; "+c+"; "+k},b.prototype.compileArray=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p;if(this.fromNum&&this.toNum&&Math.abs(this.fromNum-this.toNum)<=20){j=function(){p=[];for(var a=n=+this.fromNum,b=+this.toNum;n<=b?a<=b:a>=b;n<=b?a++:a--)p.push(a);return p}.apply(this),this.exclusive&&j.pop();return"["+j.join(", ")+"]"}g=this.tab+R,f=a.scope.freeVariable("i"),k=a.scope.freeVariable("results"),i="\n"+g+k+" = [];",this.fromNum&&this.toNum?(a.index=f,c=this.compileNode(a)):(l=""+f+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),d=""+this.fromVar+" <= "+this.toVar,c="var "+l+"; "+d+" ? "+f+" <"+this.equals+" "+this.toVar+" : "+f+" >"+this.equals+" "+this.toVar+"; "+d+" ? "+f+"++ : "+f+"--"),h="{ "+k+".push("+f+"); }\n"+g+"return "+k+";\n"+a.indent,e=function(a){return a!=null?a.contains(function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey}):void 0};if(e(this.from)||e(this.to))b=", arguments";return"(function() {"+i+"\n"+g+"for ("+c+")"+h+"}).apply(this"+(b!=null?b:"")+")"};return b}(e),a.Slice=O=function(a){function b(a){this.range=a,b.__super__.constructor.call(this)}bl(b,a),b.prototype.children=["range"],b.prototype.compileNode=function(a){var b,c,d,e,f,g;g=this.range,e=g.to,c=g.from,d=c&&c.compile(a,y)||"0",b=e&&e.compile(a,y),e&&(!!this.range.exclusive||+b!==-1)&&(f=", "+(this.range.exclusive?b:L.test(b)?""+(+b+1):(b=e.compile(a,u),""+b+" + 1 || 9e9")));return".slice("+d+(f||"")+")"};return b}(e),a.Obj=E=function(a){function b(a,b){this.generated=b!=null?b:!1,this.objects=this.properties=a||[]}bl(b,a),b.prototype.children=["properties"],b.prototype.compileNode=function(a){var b,c,e,f,g,h,i,j,l,m,n,o,p,q,r,s;n=this.properties,m=[],s=this.properties;for(o=0,q=s.length;o=0)throw SyntaxError('multiple object literal properties named "'+l+'"');m.push(l)}}if(!n.length)return this.front?"({})":"{}";if(this.generated)for(p=0,r=n.length;p=0?"[\n"+a.indent+b+"\n"+this.tab+"]":"["+b+"]"},b.prototype.assigns=function(a){var b,c,d,e;e=this.objects;for(c=0,d=e.length;c=0)throw SyntaxError("variable name may not be "+a);return a&&(a=o.test(a)&&a)},c.prototype.setContext=function(a){return this.body.traverseChildren(!1,function(b){if(b.classBody)return!1;if(b instanceof A&&b.value==="this")return b.value=a;if(b instanceof j){b.klass=a;if(b.bound)return b.context=a}})},c.prototype.addBoundFunctions=function(a){var c,d,e,f,g,h;if(this.boundFuncs.length){g=this.boundFuncs,h=[];for(e=0,f=g.length;e=0);if(e&&this.context!=="object")throw SyntaxError('variable name may not be "'+f+'"')}bl(c,a),c.prototype.children=["variable","value"],c.prototype.isStatement=function(a){return(a!=null?a.level:void 0)===z&&this.context!=null&&bm.call(this.context,"?")>=0},c.prototype.assigns=function(a){return this[this.context==="object"?"value":"variable"].assigns(a)},c.prototype.unfoldSoak=function(a){return bg(a,this,"variable")},c.prototype.compileNode=function(a){var b,c,d,e,f,g,h,i,k;if(b=this.variable instanceof W){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(a);if(this.variable.isSplice())return this.compileSplice(a);if((g=this.context)==="||="||g==="&&="||g==="?=")return this.compileConditional(a)}d=this.variable.compile(a,w);if(!this.context){if(!(f=this.variable.unwrapAll()).isAssignable())throw SyntaxError('"'+this.variable.compile(a)+'" cannot be assigned.');if(typeof f.hasProperties=="function"?!f.hasProperties():!void 0)this.param?a.scope.add(d,"var"):a.scope.find(d)}this.value instanceof j&&(c=B.exec(d))&&(c[1]&&(this.value.klass=c[1]),this.value.name=(h=(i=(k=c[2])!=null?k:c[3])!=null?i:c[4])!=null?h:c[5]),e=this.value.compile(a,w);if(this.context==="object")return""+d+": "+e;e=d+(" "+(this.context||"=")+" ")+e;return a.level<=w?e:"("+e+")"},c.prototype.compilePatternMatch=function(a){var d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,u,v,y,B,C,D,E,F,G,J,K,L;s=a.level===z,v=this.value,m=this.variable.base.objects;if(!(n=m.length)){f=v.compile(a);return a.level>=x?"("+f+")":f}i=this.variable.isObject();if(s&&n===1&&!((l=m[0])instanceof P)){l instanceof c?(D=l,E=D.variable,h=E.base,l=D.value):l.base instanceof H?(F=(new W(l.unwrapAll())).cacheReference(a),l=F[0],h=F[1]):h=i?l["this"]?l.properties[0].name:l:new A(0),d=o.test(h.unwrap().value||0),v=new W(v),v.properties.push(new(d?b:t)(h));if(G=l.unwrap().value,bm.call(I,G)>=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+v.compile(a));return(new c(l,v,null,{param:this.param})).compile(a,z)}y=v.compile(a,w),e=[],r=!1;if(!o.test(y)||this.variable.assigns(y))e.push(""+(p=a.scope.freeVariable("ref"))+" = "+y),y=p;for(g=B=0,C=m.length;B=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+u.compile(a));e.push((new c(l,u,null,{param:this.param,subpattern:!0})).compile(a,w))}!s&&!this.subpattern&&e.push(y),f=e.join(", ");return a.level=0&&(a.isExistentialEquals=!0);return(new F(this.context.slice(0,-1),b,new c(d,this.value,"="))).compile(a)},c.prototype.compileSplice=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;k=this.variable.properties.pop().range,d=k.from,h=k.to,c=k.exclusive,g=this.variable.compile(a),l=(d!=null?d.cache(a,x):void 0)||["0","0"],e=l[0],f=l[1],h?(d!=null?d.isSimpleNumber():void 0)&&h.isSimpleNumber()?(h=+h.compile(a)- +f,c||(h+=1)):(h=h.compile(a,u)+" - "+f,c||(h+=" + 1")):h="9e9",m=this.value.cache(a,w),i=m[0],j=m[1],b="[].splice.apply("+g+", ["+e+", "+h+"].concat("+i+")), "+j;return a.level>z?"("+b+")":b};return c}(e),a.Code=j=function(a){function b(a,b,c){this.params=a||[],this.body=b||new f,this.bound=c==="boundfunc",this.bound&&(this.context="_this")}bl(b,a),b.prototype.children=["params","body"],b.prototype.isStatement=function(){return!!this.ctor},b.prototype.jumps=D,b.prototype.compileNode=function(a){var b,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,v,w,x,y,z,B,C,D,E,G,H,I,J,K,L,M,O;a.scope=new N(a.scope,this.body,this),a.scope.shared=$(a,"sharedScope"),a.indent+=R,delete a.bare,delete a.isExistentialEquals,l=[],e=[],H=this.paramNames();for(s=0,x=H.length;s=u?"("+b+")":b},b.prototype.paramNames=function(){var a,b,c,d,e;a=[],e=this.params;for(c=0,d=e.length;c=0)throw SyntaxError('parameter name "'+a+'" is not allowed')}bl(b,a),b.prototype.children=["name","value"],b.prototype.compile=function(a){return this.name.compile(a,w)},b.prototype.asReference=function(a){var b;if(this.reference)return this.reference;b=this.name,b["this"]?(b=b.properties[0].name,b.value.reserved&&(b=new A(a.scope.freeVariable(b.value)))):b.isComplex()&&(b=new A(a.scope.freeVariable("arg"))),b=new W(b),this.splat&&(b=new P(b));return this.reference=b},b.prototype.isComplex=function(){return this.name.isComplex()},b.prototype.names=function(a){var b,c,e,f,g,h;a==null&&(a=this.name),b=function(a){var b;b=a.properties[0].name.value;return b.reserved?[]:[b]};if(a instanceof A)return[a.value];if(a instanceof W)return b(a);c=[],h=a.objects;for(f=0,g=h.length;f=c.length)return"";if(c.length===1){g=c[0].compile(a,w);if(d)return g;return""+bh("slice")+".call("+g+")"}e=c.slice(i);for(h=k=0,l=e.length;k1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),b="\n"+b.compile(a,z)+"\n"+this.tab),c=e+this.tab+("while ("+this.condition.compile(a,y)+") {"+b+"}"),this.returns&&(c+="\n"+this.tab+"return "+d+";");return c};return b}(e),a.Op=F=function(a){function e(a,c,d,e){if(a==="in")return new s(c,d);if(a==="do")return this.generateDo(c);if(a==="new"){if(c instanceof g&&!c["do"]&&!c.isNew)return c.newInstance();if(c instanceof j&&c.bound||c["do"])c=new H(c)}this.operator=b[a]||a,this.first=c,this.second=d,this.flip=!!e;return this}var b,c;bl(e,a),b={"==":"===","!=":"!==",of:"in"},c={"!==":"===","===":"!=="},e.prototype.children=["first","second"],e.prototype.isSimpleNumber=D,e.prototype.isUnary=function(){return!this.second},e.prototype.isComplex=function(){var a;return!this.isUnary()||(a=this.operator)!=="+"&&a!=="-"||this.first.isComplex()},e.prototype.isChainable=function(){var a;return(a=this.operator)==="<"||a===">"||a===">="||a==="<="||a==="==="||a==="!=="},e.prototype.invert=function(){var a,b,d,f,g;if(this.isChainable()&&this.first.isChainable()){a=!0,b=this;while(b&&b.operator)a&&(a=b.operator in c),b=b.first;if(!a)return(new H(this)).invert();b=this;while(b&&b.operator)b.invert=!b.invert,b.operator=c[b.operator],b=b.first;return this}if(f=c[this.operator]){this.operator=f,this.first.unwrap()instanceof e&&this.first.invert();return this}return this.second?(new H(this)).invert():this.operator==="!"&&(d=this.first.unwrap())instanceof e&&((g=d.operator)==="!"||g==="in"||g==="instanceof")?d:new e("!",this)},e.prototype.unfoldSoak=function(a){var b;return((b=this.operator)==="++"||b==="--"||b==="delete")&&bg(a,this,"first")},e.prototype.generateDo=function(a){var b,c,e,f,h,i,k,l;f=[],c=a instanceof d&&(h=a.value.unwrap())instanceof j?h:a,l=c.params||[];for(i=0,k=l.length;i=0))throw SyntaxError("prefix increment/decrement may not have eval or arguments operand");if(this.isUnary())return this.compileUnary(a);if(c)return this.compileChain(a);if(this.operator==="?")return this.compileExistence(a);b=this.first.compile(a,x)+" "+this.operator+" "+this.second.compile(a,x);return a.level<=x?b:"("+b+")"},e.prototype.compileChain=function(a){var b,c,d,e;e=this.first.second.cache(a),this.first.second=e[0],d=e[1],c=this.first.compile(a,x),b=""+c+" "+(this.invert?"&&":"||")+" "+d.compile(a)+" "+this.operator+" "+this.second.compile(a,x);return"("+b+")"},e.prototype.compileExistence=function(a){var b,c;this.first.isComplex()?(c=new A(a.scope.freeVariable("ref")),b=new H(new d(c,this.first))):(b=this.first,c=b);return(new r(new l(b),c,{type:"if"})).addElse(this.second).compile(a)},e.prototype.compileUnary=function(a){var b,c,d;if(a.level>=u)return(new H(this)).compile(a);c=[b=this.operator],d=b==="+"||b==="-",(b==="new"||b==="typeof"||b==="delete"||d&&this.first instanceof e&&this.first.operator===b)&&c.push(" ");if(d&&this.first instanceof e||b==="new"&&this.first.isStatement(a))this.first=new H(this.first);c.push(this.first.compile(a,x)),this.flip&&c.reverse();return c.join("")},e.prototype.toString=function(a){return e.__super__.toString.call(this,a,this.constructor.name+" "+this.operator)};return e}(e),a.In=s=function(a){function b(a,b){this.object=a,this.array=b}bl(b,a),b.prototype.children=["object","array"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e,f;if(this.array instanceof W&&this.array.isArray()){f=this.array.base.objects;for(d=0,e=f.length;d= 0");if(d===c)return b;b=d+", "+b;return a.level=0)throw SyntaxError('catch variable may not be "'+this.error.value+'"');a.scope.check(this.error.value)||a.scope.add(this.error.value,"param");return" catch"+d+"{\n"+this.recovery.compile(a,z)+"\n"+this.tab+"}"}if(!this.ensure&&!this.recovery)return" catch (_error) {}"}.call(this),c=this.ensure?" finally {\n"+this.ensure.compile(a,z)+"\n"+this.tab+"}":"";return""+this.tab+"try {\n"+e+"\n"+this.tab+"}"+(b||"")+c};return b}(e),a.Throw=T=function(a){function b(a){this.expression=a}bl(b,a),b.prototype.children=["expression"],b.prototype.isStatement=Y,b.prototype.jumps=D,b.prototype.makeReturn=S,b.prototype.compileNode=function(a){return this.tab+("throw "+this.expression.compile(a)+";")};return b}(e),a.Existence=l=function(a){function b(a){this.expression=a}bl(b,a),b.prototype.children=["expression"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e;this.expression.front=this.front,d=this.expression.compile(a,x),o.test(d)&&!a.scope.check(d)?(e=this.negated?["===","||"]:["!==","&&"],b=e[0],c=e[1],d="typeof "+d+" "+b+' "undefined" '+c+" "+d+" "+b+" null"):d=""+d+" "+(this.negated?"==":"!=")+" null";return a.level<=v?d:"("+d+")"};return b}(e),a.Parens=H=function(a){function b(a){this.body=a}bl(b,a),b.prototype.children=["body"],b.prototype.unwrap=function(){return this.body},b.prototype.isComplex=function(){return this.body.isComplex()},b.prototype.compileNode=function(a){var b,c,d;d=this.body.unwrap();if(d instanceof W&&d.isAtomic()){d.front=this.front;return d.compile(a)}c=d.compile(a,y),b=a.level1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),this.pattern&&b.expressions.unshift(new d(this.name,new A(""+F+"["+l+"]"))),c+=this.pluckDirectCall(a,b),s&&(G="\n"+i+s+";"),this.object&&(e=""+l+" in "+F,this.own&&(h="\n"+i+"if (!"+bh("hasProp")+".call("+F+", "+l+")) continue;")),b=b.compile(bd(a,{indent:i}),z),b&&(b="\n"+b+"\n");return""+c+(u||"")+this.tab+"for ("+e+") {"+h+G+b+this.tab+"}"+(v||"")},b.prototype.pluckDirectCall=function(a,b){var c,e,f,h,i,k,l,m,n,o,p,q,r,s,t;e="",o=b.expressions;for(i=m=0,n=o.length;m=v?"("+d+")":d},b.prototype.unfoldSoak=function(){return this.soak&&this};return b}(e),i={wrap:function(a,c,d){var e,h,i,k,l;if(a.jumps())return a;i=new j([],f.wrap([a])),e=[];if((k=a.contains(this.literalArgs))||a.contains(this.literalThis))l=new A(k?"apply":"call"),e=[new A("this")],k&&e.push(new A("arguments")),i=new W(i,[new b(l)]);i.noReturn=d,h=new g(i,e);return c?f.wrap([h]):h},literalArgs:function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey},literalThis:function(a){return a instanceof A&&a.value==="this"&&!a.asKey||a instanceof j&&a.bound||a instanceof g&&a.isSuper}},bg=function(a,b,c){var d;if(!!(d=b[c].unfoldSoak(a))){b[c]=d.body,d.body=new W(b);return d}},V={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+bh("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},hasProp:function(){return"{}.hasOwnProperty"},slice:function(){return"[].slice"}},z=1,y=2,w=3,v=4,x=5,u=6,R=" ",p="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",o=RegExp("^"+p+"$"),L=/^[+-]?\d+$/,B=RegExp("^(?:("+p+")\\.prototype(?:\\.("+p+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|("+p+")$"),q=/^['"]/,bh=function(a){var b;b="__"+a,N.root.assign(b,V[a]());return b},be=function(a,b){a=a.replace(/\n/g,"$&"+b);return a.replace(/\s+$/,"")}}).call(this)},require["./coffee-script"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k=({}).hasOwnProperty;e=require("fs"),h=require("path"),j=require("./lexer"),b=j.Lexer,c=j.RESERVED,g=require("./parser").parser,i=require("vm"),require.extensions?require.extensions[".coffee"]=function(a,b){var c;c=d(e.readFileSync(b,"utf8"),{filename:b});return a._compile(c,b)}:require.registerExtension&&require.registerExtension(".coffee",function(a){return d(a)}),a.VERSION="1.3.3",a.RESERVED=c,a.helpers=require("./helpers"),a.compile=d=function(b,c){var d,e,h;c==null&&(c={}),h=a.helpers.merge;try{e=g.parse(f.tokenize(b)).compile(c);if(!c.header)return e}catch(i){c.filename&&(i.message="In "+c.filename+", "+i.message);throw i}d="Generated by CoffeeScript "+this.VERSION;return"// "+d+"\n"+e},a.tokens=function(a,b){return f.tokenize(a,b)},a.nodes=function(a,b){return typeof a=="string"?g.parse(f.tokenize(a,b)):g.parse(a)},a.run=function(a,b){var c;b==null&&(b={}),c=require.main,c.filename=process.argv[1]=b.filename?e.realpathSync(b.filename):".",c.moduleCache&&(c.moduleCache={}),c.paths=require("module")._nodeModulePaths(h.dirname(e.realpathSync(b.filename)));return h.extname(c.filename)!==".coffee"||require.extensions?c._compile(d(a,b),c.filename):c._compile(a,c.filename)},a.eval=function(a,b){var c,e,f,g,j,l,m,n,o,p,q,r,s,t;b==null&&(b={});if(!!(a=a.trim())){e=i.Script;if(e){if(b.sandbox!=null){if(b.sandbox instanceof e.createContext().constructor)m=b.sandbox;else{m=e.createContext(),r=b.sandbox;for(g in r){if(!k.call(r,g))continue;n=r[g],m[g]=n}}m.global=m.root=m.GLOBAL=m}else m=global;m.__filename=b.filename||"eval",m.__dirname=h.dirname(m.__filename);if(m===global&&!m.module&&!m.require){c=require("module"),m.module=q=new c(b.modulename||"eval"),m.require=t=function(a){return c._load(a,q,!0)},q.filename=m.__filename,s=Object.getOwnPropertyNames(require);for(o=0,p=s.length;o=0)s+=1;else if(f=o[0],b.call(r,f)>=0)s-=1;e+=1}return e-1},e.prototype.removeLeadingNewlines=function(){var e,t,n,r,i;i=this.tokens;for(e=n=0,r=i.length;n=0)?(r.splice(t,1),0):1})},e.prototype.closeOpenCalls=function(){var e,t;return t=function(e,t){var n;return(n=e[0])===")"||n==="CALL_END"||e[0]==="OUTDENT"&&this.tag(t-1)===")"},e=function(e,t){return this.tokens[e[0]==="OUTDENT"?t-1:t][0]="CALL_END"},this.scanTokens(function(n,r){return n[0]==="CALL_START"&&this.detectEnd(r+1,t,e),1})},e.prototype.closeOpenIndexes=function(){var e,t;return t=function(e,t){var n;return(n=e[0])==="]"||n==="INDEX_END"},e=function(e,t){return e[0]="INDEX_END"},this.scanTokens(function(n,r){return n[0]==="INDEX_START"&&this.detectEnd(r+1,t,e),1})},e.prototype.addImplicitBraces=function(){var e,t,n,s,o,a,f,l;return s=[],o=null,l=null,n=!0,a=0,f=0,t=function(e,t){var r,i,s,o,a,h;return a=this.tokens.slice(t+1,+(t+3)+1||9e9),r=a[0],o=a[1],s=a[2],"HERECOMMENT"===(r!=null?r[0]:void 0)?!1:(i=e[0],b.call(c,i)>=0&&(n=!1),(i==="TERMINATOR"||i==="OUTDENT"||b.call(u,i)>=0&&n&&t-f!==1)&&(!l&&this.tag(t-1)!==","||(o!=null?o[0]:void 0)!==":"&&((r!=null?r[0]:void 0)!=="@"||(s!=null?s[0]:void 0)!==":"))||i===","&&r&&(h=r[0])!=="IDENTIFIER"&&h!=="NUMBER"&&h!=="STRING"&&h!=="@"&&h!=="TERMINATOR"&&h!=="OUTDENT")},e=function(e,t){var n;return n=this.generate("}","}",e[2]),this.tokens.splice(t,0,n)},this.scanTokens(function(u,a,h){var p,d,v,m,g,y,w,E;if(w=m=u[0],b.call(i,w)>=0)return s.push([m==="INDENT"&&this.tag(a-1)==="{"?"{":m,a]),1;if(b.call(r,m)>=0)return o=s.pop(),1;if(m!==":"||(p=this.tag(a-2))!==":"&&((E=s[s.length-1])!=null?E[0]:void 0)==="{")return 1;n=!0,f=a+1,s.push(["{"]),d=p==="@"?a-2:a-1;while(this.tag(d-2)==="HERECOMMENT")d-=2;return v=this.tag(d-1),l=!v||b.call(c,v)>=0,y=new String("{"),y.generated=!0,g=this.generate("{",y,u[2]),h.splice(d,0,g),this.detectEnd(a+2,t,e),2})},e.prototype.addImplicitParentheses=function(){var e,t,n,r,i;return n=i=r=!1,t=function(e,t){var n,o,a,f;o=e[0];if(!i&&e.fromThen)return!0;if(o==="IF"||o==="ELSE"||o==="CATCH"||o==="->"||o==="=>"||o==="CLASS")i=!0;if(o==="IF"||o==="ELSE"||o==="SWITCH"||o==="TRY"||o==="=")r=!0;return o!=="."&&o!=="?."&&o!=="::"||this.tag(t-1)!=="OUTDENT"?!e.generated&&this.tag(t-1)!==","&&(b.call(u,o)>=0||o==="INDENT"&&!r)&&(o!=="INDENT"||(a=this.tag(t-2))!=="CLASS"&&a!=="EXTENDS"&&(f=this.tag(t-1),b.call(s,f)<0)&&(!(n=this.tokens[t+1])||!n.generated||n[0]!=="{")):!0},e=function(e,t){return this.tokens.splice(t,0,this.generate("CALL_END",")",e[2]))},this.scanTokens(function(s,u,l){var h,p,d,v,m,g,y,w;m=s[0];if(m==="CLASS"||m==="IF"||m==="FOR"||m==="WHILE")n=!0;return g=l.slice(u-1,+(u+1)+1||9e9),v=g[0],p=g[1],d=g[2],h=!n&&m==="INDENT"&&d&&d.generated&&d[0]==="{"&&v&&(y=v[0],b.call(a,y)>=0),i=!1,r=!1,b.call(c,m)>=0&&(n=!1),v&&!v.spaced&&m==="?"&&(s.call=!0),s.fromThen?1:h||(v!=null?v.spaced:void 0)&&(v.call||(w=v[0],b.call(a,w)>=0))&&(b.call(o,m)>=0||!s.spaced&&!s.newLine&&b.call(f,m)>=0)?(l.splice(u,0,this.generate("CALL_START","(",s[2])),this.detectEnd(u+1,t,e),v[0]==="?"&&(v[0]="FUNC_EXIST"),2):1})},e.prototype.addImplicitIndentation=function(){var e,t,n,r,i;return i=n=r=null,t=function(e,t){var n;return e[1]!==";"&&(n=e[0],b.call(h,n)>=0)&&(e[0]!=="ELSE"||i==="IF"||i==="THEN")},e=function(e,t){return this.tokens.splice(this.tag(t-1)===","?t-1:t,0,r)},this.scanTokens(function(s,o,u){var a,f,l;return a=s[0],a==="TERMINATOR"&&this.tag(o+1)==="THEN"?(u.splice(o,1),0):a==="ELSE"&&this.tag(o-1)!=="OUTDENT"?(u.splice.apply(u,[o,0].concat(w.call(this.indentation(s)))),2):a!=="CATCH"||(f=this.tag(o+2))!=="OUTDENT"&&f!=="TERMINATOR"&&f!=="FINALLY"?b.call(p,a)>=0&&this.tag(o+1)!=="INDENT"&&(a!=="ELSE"||this.tag(o+1)!=="IF")?(i=a,l=this.indentation(s,!0),n=l[0],r=l[1],i==="THEN"&&(n.fromThen=!0),u.splice(o+1,0,n),this.detectEnd(o+2,t,e),a==="THEN"&&u.splice(o,1),1):1:(u.splice.apply(u,[o+2,0].concat(w.call(this.indentation(s)))),4)})},e.prototype.tagPostfixConditionals=function(){var e,t,n;return n=null,t=function(e,t){var n;return(n=e[0])==="TERMINATOR"||n==="INDENT"},e=function(e,t){if(e[0]!=="INDENT"||e.generated&&!e.fromThen)return n[0]="POST_"+n[0]},this.scanTokens(function(r,i){return r[0]!=="IF"?1:(n=r,this.detectEnd(i+1,t,e),1)})},e.prototype.indentation=function(e,t){var n,r;return t==null&&(t=!1),n=["INDENT",2,e[2]],r=["OUTDENT",2,e[2]],t&&(n.generated=r.generated=!0),[n,r]},e.prototype.generate=function(e,t,n){var r;return r=[e,t,n],r.generated=!0,r},e.prototype.tag=function(e){var t;return(t=this.tokens[e])!=null?t[0]:void 0},e}(),t=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],e.INVERSES=l={},i=[],r=[];for(m=0,g=t.length;m","=>","[","(","{","--","++"],f=["+","-"],s=["->","=>","{","[",","],u=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR","AWAIT"],p=["ELSE","->","=>","TRY","FINALLY","THEN"],h=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],c=["TERMINATOR","INDENT","OUTDENT"]}).call(this)},require["./lexer"]=new function(){var e=this;(function(){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,P,H,B,j,F,I,q,R,U,z,W,X,V,$,J,K=[].indexOf||function(e){for(var t=0,n=this.length;t=0||K.call(o,n)>=0)&&(f=n.toUpperCase(),f==="WHEN"&&(c=this.tag(),K.call(E,c)>=0)?f="LEADING_WHEN":f==="FOR"?this.seenFor=!0:f==="UNLESS"?f="IF":K.call(q,f)>=0?f="UNARY":K.call(D,f)>=0&&(f!=="INSTANCEOF"&&this.seenFor?(f="FOR"+f,this.seenFor=!1):(f="RELATION",this.value()==="!"&&(this.tokens.pop(),n="!"+n)))),K.call(b,n)>=0&&(t?(f="IDENTIFIER",n=new String(n),n.reserved=!0):K.call(P,n)>=0&&this.error('reserved word "'+n+'"')),t||(K.call(i,n)>=0&&(n=s[n]),f=function(){switch(n){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":return"BOOL";case"break":case"continue":return"STATEMENT";default:return f}}()),this.token(f,n),e&&this.token(":",":"),r.length)):0},e.prototype.numberToken=function(){var e,t,n,r,i;if(!(n=O.exec(this.chunk)))return 0;r=n[0],/^0[BOX]/.test(r)?this.error("radix prefix '"+r+"' must be lowercase"):/E/.test(r)&&!/^0x/.test(r)?this.error("exponential notation '"+r+"' must be indicated with a lowercase 'e'"):/^0\d*[89]/.test(r)?this.error("decimal literal '"+r+"' must not be prefixed with '0'"):/^0\d+/.test(r)&&this.error("octal literal '"+r+"' must be prefixed with '0o'"),t=r.length;if(i=/^0o([0-7]+)/.exec(r))r="0x"+parseInt(i[1],8).toString(16);if(e=/^0b([01]+)/.exec(r))r="0x"+parseInt(e[1],2).toString(16);return this.token("NUMBER",r),t},e.prototype.stringToken=function(){var e,t,n;switch(this.chunk.charAt(0)){case"'":if(!(e=j.exec(this.chunk)))return 0;this.token("STRING",(n=e[0]).replace(C,"\\\n"));break;case'"':if(!(n=this.balancedString(this.chunk,'"')))return 0;0=0)?0:(n=_.exec(this.chunk))?(o=n,n=o[0],i=o[1],e=o[2],i.slice(0,2)==="/*"&&this.error("regular expressions cannot begin with `*`"),i==="//"&&(i="/(?:)/"),this.token("REGEX",""+i+e),n.length):0)},e.prototype.heregexToken=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p;r=e[0],t=e[1],n=e[2];if(0>t.indexOf("#{"))return i=t.replace(d,"").replace(/\//g,"\\/"),i.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(i||"(?:)")+"/"+n),r.length;this.token("IDENTIFIER","RegExp"),this.tokens.push(["CALL_START","("]),o=[],l=this.interpolateString(t,{regex:!0});for(a=0,f=l.length;athis.indent){if(r)return this.indebt=i-this.indent,this.suppressNewlines(),t.length;e=i-this.indent+this.outdebt,this.token("INDENT",e),this.indents.push(e),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0}else this.indebt=0,this.outdentToken(this.indent-i,r);return this.indent=i,t.length},e.prototype.outdentToken=function(e,t){var n,r;while(e>0)r=this.indents.length-1,this.indents[r]===void 0?e=0:this.indents[r]===this.outdebt?(e-=this.outdebt,this.outdebt=0):this.indents[r]=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned");if((u=t[1])==="||"||u==="&&")return t[0]="COMPOUND_ASSIGN",t[1]+="=",s.length}if(s===";")this.seenFor=!1,i="TERMINATOR";else if(K.call(N,s)>=0)i="MATH";else if(K.call(a,s)>=0)i="COMPARE";else if(K.call(f,s)>=0)i="COMPOUND_ASSIGN";else if(K.call(q,s)>=0)i="UNARY";else if(K.call(B,s)>=0)i="SHIFT";else if(K.call(x,s)>=0||s==="?"&&(t!=null?t.spaced:void 0))i="LOGIC";else if(t&&!t.spaced)if(s==="("&&(l=t[0],K.call(n,l)>=0))t[0]==="?"&&(t[0]="FUNC_EXIST"),i="CALL_START";else if(s==="["&&(c=t[0],K.call(m,c)>=0)){i="INDEX_START";switch(t[0]){case"?":t[0]="INDEX_SOAK"}}switch(s){case"(":case"{":case"[":this.ends.push(g[s]);break;case")":case"}":case"]":this.pair(s)}return this.token(i,s),s.length},e.prototype.sanitizeHeredoc=function(e,t){var n,r,i,s,o;i=t.indent,r=t.herecomment;if(r){c.test(e)&&this.error('block comment cannot contain "*/", starting');if(e.indexOf("\n")<=0)return e}else while(s=h.exec(e)){n=s[1];if(i===null||0<(o=n.length)&&of;r=1<=f?++a:--a){if(n){--n;continue}switch(i=e.charAt(r)){case"\\":++n;continue;case t:u.pop();if(!u.length)return e.slice(0,+r+1||9e9);t=u[u.length-1];continue}t!=="}"||i!=='"'&&i!=="'"?t==="}"&&i==="/"&&(s=p.exec(e.slice(r))||_.exec(e.slice(r)))?n+=s[0].length-1:t==="}"&&i==="{"?u.push(t="}"):t==='"'&&o==="#"&&i==="{"&&u.push(t="}"):u.push(t=i),o=i}return this.error("missing "+u.pop()+", starting")},e.prototype.interpolateString=function(t,n){var r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w;n==null&&(n={}),i=n.heredoc,h=n.regex,d=[],c=0,s=-1;while(f=t.charAt(s+=1)){if(f==="\\"){s+=1;continue}if(f!=="#"||t.charAt(s+1)!=="{"||!(r=this.balancedString(t.slice(s+1),"}")))continue;c1&&(l.unshift(["(","(",this.line]),l.push([")",")",this.line])),d.push(["TOKENS",l])}s+=r.length,c=s+1}s>c&&c1)&&this.token("(","(");for(s=m=0,g=d.length;m|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/,R=/^[^\n\S]+/,u=/^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/,r=/^[-=]>/,k=/^(?:\n[^\n\S]*)+/,j=/^'[^\\']*(?:\\.[^\\']*)*'/,y=/^`[^\\`]*(?:\\.[^\\`]*)*`/,_=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,p=/^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/,d=/\s+(?:#.*)?/g,C=/\n/g,h=/\n+([^\n\S]*)/g,c=/\*\//,S=/^\s*(?:,|\??\.(?![.\d])|::)/,I=/\s+$/,f=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|="],q=["!","~","NEW","TYPEOF","DELETE","DO"],x=["&&","||","&","|","^"],B=["<<",">>",">>>"],a=["==","!=","<",">","<=",">="],N=["*","/","%"],D=["IN","OF","INSTANCEOF"],t=["TRUE","FALSE"],L=["NUMBER","REGEX","BOOL","NULL","UNDEFINED","++","--","]"],A=L.concat(")","}","THIS","IDENTIFIER","STRING"),n=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER","DEFER","TAMEREQUIRE"],m=n.concat("NUMBER","BOOL","NULL","UNDEFINED"),E=["INDENT","OUTDENT","TERMINATOR"]}).call(this)},require["./parser"]=new function(){var e=this,t=function(){var e={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Block:5,TERMINATOR:6,Line:7,Expression:8,Statement:9,Return:10,Comment:11,STATEMENT:12,Await:13,AWAIT:14,Value:15,Invocation:16,Code:17,Operation:18,Assign:19,If:20,Try:21,While:22,For:23,Switch:24,Class:25,Throw:26,Defer:27,INDENT:28,OUTDENT:29,Identifier:30,IDENTIFIER:31,AlphaNumeric:32,NUMBER:33,STRING:34,Literal:35,JS:36,REGEX:37,DEBUGGER:38,UNDEFINED:39,NULL:40,BOOL:41,Assignable:42,"=":43,AssignObj:44,ObjAssignable:45,":":46,ThisProperty:47,RETURN:48,HERECOMMENT:49,PARAM_START:50,ParamList:51,PARAM_END:52,FuncGlyph:53,"->":54,"=>":55,OptComma:56,",":57,Param:58,ParamVar:59,"...":60,Array:61,Object:62,Splat:63,SimpleAssignable:64,Accessor:65,Parenthetical:66,Range:67,This:68,".":69,"?.":70,"::":71,Index:72,INDEX_START:73,IndexValue:74,INDEX_END:75,INDEX_SOAK:76,Slice:77,"{":78,AssignList:79,"}":80,CLASS:81,EXTENDS:82,OptFuncExist:83,Arguments:84,SUPER:85,DEFER:86,FUNC_EXIST:87,CALL_START:88,CALL_END:89,ArgList:90,THIS:91,"@":92,"[":93,"]":94,RangeDots:95,"..":96,Arg:97,SimpleArgs:98,TRY:99,Catch:100,FINALLY:101,CATCH:102,THROW:103,"(":104,")":105,WhileSource:106,WHILE:107,WHEN:108,UNTIL:109,Loop:110,LOOP:111,ForBody:112,FOR:113,ForStart:114,ForSource:115,ForVariables:116,OWN:117,ForValue:118,FORIN:119,FOROF:120,BY:121,SWITCH:122,Whens:123,ELSE:124,When:125,LEADING_WHEN:126,IfBlock:127,IF:128,POST_IF:129,UNARY:130,"-":131,"+":132,"--":133,"++":134,"?":135,MATH:136,SHIFT:137,COMPARE:138,LOGIC:139,RELATION:140,COMPOUND_ASSIGN:141,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",12:"STATEMENT",14:"AWAIT",28:"INDENT",29:"OUTDENT",31:"IDENTIFIER",33:"NUMBER",34:"STRING",36:"JS",37:"REGEX",38:"DEBUGGER",39:"UNDEFINED",40:"NULL",41:"BOOL",43:"=",46:":",48:"RETURN",49:"HERECOMMENT",50:"PARAM_START",52:"PARAM_END",54:"->",55:"=>",57:",",60:"...",69:".",70:"?.",71:"::",73:"INDEX_START",75:"INDEX_END",76:"INDEX_SOAK",78:"{",80:"}",81:"CLASS",82:"EXTENDS",85:"SUPER",86:"DEFER",87:"FUNC_EXIST",88:"CALL_START",89:"CALL_END",91:"THIS",92:"@",93:"[",94:"]",96:"..",99:"TRY",101:"FINALLY",102:"CATCH",103:"THROW",104:"(",105:")",107:"WHILE",108:"WHEN",109:"UNTIL",111:"LOOP",113:"FOR",117:"OWN",119:"FORIN",120:"FOROF",121:"BY",122:"SWITCH",124:"ELSE",126:"LEADING_WHEN",128:"IF",129:"POST_IF",130:"UNARY",131:"-",132:"+",133:"--",134:"++",135:"?",136:"MATH",137:"SHIFT",138:"COMPARE",139:"LOGIC",140:"RELATION",141:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[13,2],[13,2],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[30,1],[32,1],[32,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[19,3],[19,4],[19,5],[44,1],[44,3],[44,5],[44,1],[45,1],[45,1],[45,1],[10,2],[10,1],[11,1],[17,5],[17,2],[53,1],[53,1],[56,0],[56,1],[51,0],[51,1],[51,3],[51,4],[51,6],[58,1],[58,2],[58,3],[59,1],[59,1],[59,1],[59,1],[63,2],[64,1],[64,2],[64,2],[64,1],[42,1],[42,1],[42,1],[15,1],[15,1],[15,1],[15,1],[15,1],[65,2],[65,2],[65,2],[65,2],[65,1],[65,1],[72,3],[72,2],[74,1],[74,1],[62,4],[79,0],[79,1],[79,3],[79,4],[79,6],[25,1],[25,2],[25,3],[25,4],[25,2],[25,3],[25,4],[25,5],[16,3],[16,3],[16,1],[16,2],[27,2],[83,0],[83,1],[84,2],[84,4],[68,1],[68,1],[47,2],[61,2],[61,4],[95,1],[95,1],[67,5],[77,3],[77,2],[77,2],[77,1],[90,1],[90,3],[90,4],[90,4],[90,6],[97,1],[97,1],[98,1],[98,3],[21,2],[21,3],[21,4],[21,5],[100,3],[26,2],[66,3],[66,5],[106,2],[106,4],[106,2],[106,4],[22,2],[22,2],[22,2],[22,1],[110,2],[110,2],[23,2],[23,2],[23,2],[112,2],[112,2],[114,2],[114,3],[118,1],[118,1],[118,1],[118,1],[116,1],[116,3],[115,2],[115,2],[115,4],[115,4],[115,4],[115,6],[115,6],[24,5],[24,7],[24,4],[24,6],[123,1],[123,2],[125,3],[125,4],[127,3],[127,5],[20,1],[20,3],[20,3],[20,3],[18,2],[18,2],[18,2],[18,2],[18,2],[18,2],[18,2],[18,2],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,5],[18,3]],performAction:function(t,n,r,i,s,o,u){var a=o.length-1;switch(s){case 1:return this.$=new i.Block;case 2:return this.$=o[a];case 3:return this.$=o[a-1];case 4:this.$=i.Block.wrap([o[a]]);break;case 5:this.$=o[a-2].push(o[a]);break;case 6:this.$=o[a-1];break;case 7:this.$=o[a];break;case 8:this.$=o[a];break;case 9:this.$=o[a];break;case 10:this.$=o[a];break;case 11:this.$=new i.Literal(o[a]);break;case 12:this.$=new i.Await(o[a]);break;case 13:this.$=new i.Await(i.Block.wrap([o[a]]));break;case 14:this.$=o[a];break;case 15:this.$=o[a];break;case 16:this.$=o[a];break;case 17:this.$=o[a];break;case 18:this.$=o[a];break;case 19:this.$=o[a];break;case 20:this.$=o[a];break;case 21:this.$=o[a];break;case 22:this.$=o[a];break;case 23:this.$=o[a];break;case 24:this.$=o[a];break;case 25:this.$=o[a];break;case 26:this.$=o[a];break;case 27:this.$=o[a];break;case 28:this.$=new i.Block;break;case 29:this.$=o[a-1];break;case 30:this.$=new i.Literal(o[a]);break;case 31:this.$=new i.Literal(o[a]);break;case 32:this.$=new i.Literal(o[a]);break;case 33:this.$=o[a];break;case 34:this.$=new i.Literal(o[a]);break;case 35:this.$=new i.Literal(o[a]);break;case 36:this.$=new i.Literal(o[a]);break;case 37:this.$=new i.Undefined;break;case 38:this.$=new i.Null;break;case 39:this.$=new i.Bool(o[a]);break;case 40:this.$=new i.Assign(o[a-2],o[a]);break;case 41:this.$=new i.Assign(o[a-3],o[a]);break;case 42:this.$=new i.Assign(o[a-4],o[a-1]);break;case 43:this.$=new i.Value(o[a]);break;case 44:this.$=new i.Assign(new i.Value(o[a-2]),o[a],"object");break;case 45:this.$=new i.Assign(new i.Value(o[a-4]),o[a-1],"object");break;case 46:this.$=o[a];break;case 47:this.$=o[a];break;case 48:this.$=o[a];break;case 49:this.$=o[a];break;case 50:this.$=new i.Return(o[a]);break;case 51:this.$=new i.Return;break;case 52:this.$=new i.Comment(o[a]);break;case 53:this.$=new i.Code(o[a-3],o[a],o[a-1]);break;case 54:this.$=new i.Code([],o[a],o[a-1]);break;case 55:this.$="func";break;case 56:this.$="boundfunc";break;case 57:this.$=o[a];break;case 58:this.$=o[a];break;case 59:this.$=[];break;case 60:this.$=[o[a]];break;case 61:this.$=o[a-2].concat(o[a]);break;case 62:this.$=o[a-3].concat(o[a]);break;case 63:this.$=o[a-5].concat(o[a-2]);break;case 64:this.$=new i.Param(o[a]);break;case 65:this.$=new i.Param(o[a-1],null,!0);break;case 66:this.$=new i.Param(o[a-2],o[a]);break;case 67:this.$=o[a];break;case 68:this.$=o[a];break;case 69:this.$=o[a];break;case 70:this.$=o[a];break;case 71:this.$=new i.Splat(o[a-1]);break;case 72:this.$=new i.Value(o[a]);break;case 73:this.$=o[a-1].add(o[a]);break;case 74:this.$=new i.Value(o[a-1],[].concat(o[a]));break;case 75:this.$=o[a];break;case 76:this.$=o[a];break;case 77:this.$=new i.Value(o[a]);break;case 78:this.$=new i.Value(o[a]);break;case 79:this.$=o[a];break;case 80:this.$=new i.Value(o[a]);break;case 81:this.$=new i.Value(o[a]);break;case 82:this.$=new i.Value(o[a]);break;case 83:this.$=o[a];break;case 84:this.$=new i.Access(o[a]);break;case 85:this.$=new i.Access(o[a]);break;case 86:this.$=new i.Access(o[a],"soak");break;case 87:this.$=[new i.Access(new i.Literal("prototype")),new i.Access(o[a])];break;case 88:this.$=new i.Access(new i.Literal("prototype"));break;case 89:this.$=o[a];break;case 90:this.$=o[a-1];break;case 91:this.$=i.extend(o[a],{soak:!0});break;case 92:this.$=new i.Index(o[a]);break;case 93:this.$=new i.Slice(o[a]);break;case 94:this.$=new i.Obj(o[a-2],o[a-3].generated);break;case 95:this.$=[];break;case 96:this.$=[o[a]];break;case 97:this.$=o[a-2].concat(o[a]);break;case 98:this.$=o[a-3].concat(o[a]);break;case 99:this.$=o[a-5].concat(o[a-2]);break;case 100:this.$=new i.Class;break;case 101:this.$=new i.Class(null,null,o[a]);break;case 102:this.$=new i.Class(null,o[a]);break;case 103:this.$=new i.Class(null,o[a-1],o[a]);break;case 104:this.$=new i.Class(o[a]);break;case 105:this.$=new i.Class(o[a-1],null,o[a]);break;case 106:this.$=new i.Class(o[a-2],o[a]);break;case 107:this.$=new i.Class(o[a-3],o[a-1],o[a]);break;case 108:this.$=new i.Call(o[a-2],o[a],o[a-1]);break;case 109:this.$=new i.Call(o[a-2],o[a],o[a-1]);break;case 110:this.$=new i.Call("super",[new i.Splat(new i.Literal("arguments"))]);break;case 111:this.$=new i.Call("super",o[a]);break;case 112:this.$=new i.Defer(o[a],r);break;case 113:this.$=!1;break;case 114:this.$=!0;break;case 115:this.$=[];break;case 116:this.$=o[a-2];break;case 117:this.$=new i.Value(new i.Literal("this"));break;case 118:this.$=new i.Value(new i.Literal("this"));break;case 119:this.$=new i.Value(new i.Literal("this"),[new i.Access(o[a])],"this");break;case 120:this.$=new i.Arr([]);break;case 121:this.$=new i.Arr(o[a-2]);break;case 122:this.$="inclusive";break;case 123:this.$="exclusive";break;case 124:this.$=new i.Range(o[a-3],o[a-1],o[a-2]);break;case 125:this.$=new i.Range(o[a-2],o[a],o[a-1]);break;case 126:this.$=new i.Range(o[a-1],null,o[a]);break;case 127:this.$=new i.Range(null,o[a],o[a-1]);break;case 128:this.$=new i.Range(null,null,o[a]);break;case 129:this.$=[o[a]];break;case 130:this.$=o[a-2].concat(o[a]);break;case 131:this.$=o[a-3].concat(o[a]);break;case 132:this.$=o[a-2];break;case 133:this.$=o[a-5].concat(o[a-2]);break;case 134:this.$=o[a];break;case 135:this.$=o[a];break;case 136:this.$=o[a];break;case 137:this.$=[].concat(o[a-2],o[a]);break;case 138:this.$=new i.Try(o[a]);break;case 139:this.$=new i.Try(o[a-1],o[a][0],o[a][1]);break;case 140:this.$=new i.Try(o[a-2],null,null,o[a]);break;case 141:this.$=new i.Try(o[a-3],o[a-2][0],o[a-2][1],o[a]);break;case 142:this.$=[o[a-1],o[a]];break;case 143:this.$=new i.Throw(o[a]);break;case 144:this.$=new i.Parens(o[a-1]);break;case 145:this.$=new i.Parens(o[a-2]);break;case 146:this.$=new i.While(o[a]);break;case 147:this.$=new i.While(o[a-2],{guard:o[a]});break;case 148:this.$=new i.While(o[a],{invert:!0});break;case 149:this.$=new i.While(o[a-2],{invert:!0,guard:o[a]});break;case 150:this.$=o[a-1].addBody(o[a]);break;case 151:this.$=o[a].addBody(i.Block.wrap([o[a-1]]));break;case 152:this.$=o[a].addBody(i.Block.wrap([o[a-1]]));break;case 153:this.$=o[a];break;case 154:this.$=(new i.While(new i.Literal("true"))).addBody(o[a]);break;case 155:this.$=(new i.While(new i.Literal("true"))).addBody(i.Block.wrap([o[a]]));break;case 156:this.$=new i.For(o[a-1],o[a]);break;case 157:this.$=new i.For(o[a-1],o[a]);break;case 158:this.$=new i.For(o[a],o[a-1]);break;case 159:this.$={source:new i.Value(o[a])};break;case 160:this.$=function(){return o[a].own=o[a-1].own,o[a].name=o[a-1][0],o[a].index=o[a-1][1],o[a]}();break;case 161:this.$=o[a];break;case 162:this.$=function(){return o[a].own=!0,o[a]}();break;case 163:this.$=o[a];break;case 164:this.$=o[a];break;case 165:this.$=new i.Value(o[a]);break;case 166:this.$=new i.Value(o[a]);break;case 167:this.$=[o[a]];break;case 168:this.$=[o[a-2],o[a]];break;case 169:this.$={source:o[a]};break;case 170:this.$={source:o[a],object:!0};break;case 171:this.$={source:o[a-2],guard:o[a]};break;case 172:this.$={source:o[a-2],guard:o[a],object:!0};break;case 173:this.$={source:o[a-2],step:o[a]};break;case 174:this.$={source:o[a-4],guard:o[a-2],step:o[a]};break;case 175:this.$={source:o[a-4],step:o[a-2],guard:o[a]};break;case 176:this.$=new i.Switch(o[a-3],o[a-1]);break;case 177:this.$=new i.Switch(o[a-5],o[a-3],o[a-1]);break;case 178:this.$=new i.Switch(null,o[a-1]);break;case 179:this.$=new i.Switch(null,o[a-3],o[a-1]);break;case 180:this.$=o[a];break;case 181:this.$=o[a-1].concat(o[a]);break;case 182:this.$=[[o[a-1],o[a]]];break;case 183:this.$=[[o[a-2],o[a-1]]];break;case 184:this.$=new i.If(o[a-1],o[a],{type:o[a-2]});break;case 185:this.$=o[a-4].addElse(new i.If(o[a-1],o[a],{type:o[a-2]}));break;case 186:this.$=o[a];break;case 187:this.$=o[a-2].addElse(o[a]);break;case 188:this.$=new i.If(o[a],i.Block.wrap([o[a-2]]),{type:o[a-1],statement:!0});break;case 189:this.$=new i.If(o[a],i.Block.wrap([o[a-2]]),{type:o[a-1],statement:!0});break;case 190:this.$=new i.Op(o[a-1],o[a]);break;case 191:this.$=new i.Op("-",o[a]);break;case 192:this.$=new i.Op("+",o[a]);break;case 193:this.$=new i.Op("--",o[a]);break;case 194:this.$=new i.Op("++",o[a]);break;case 195:this.$=new i.Op("--",o[a-1],null,!0);break;case 196:this.$=new i.Op("++",o[a-1],null,!0);break;case 197:this.$=new i.Existence(o[a-1]);break;case 198:this.$=new i.Op("+",o[a-2],o[a]);break;case 199:this.$=new i.Op("-",o[a-2],o[a]);break;case 200:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 201:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 202:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 203:this.$=new i.Op(o[a-1],o[a-2],o[a]);break;case 204:this.$=function(){return o[a-1].charAt(0)==="!"?(new i.Op(o[a-1].slice(1),o[a-2],o[a])).invert():new i.Op(o[a-1],o[a-2],o[a])}();break;case 205:this.$=new i.Assign(o[a-2],o[a],o[a-1]);break;case 206:this.$=new i.Assign(o[a-4],o[a-1],o[a-3]);break;case 207:this.$=new i.Extends(o[a-2],o[a])}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,5],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[3]},{1:[2,2],6:[1,78]},{6:[1,79]},{1:[2,4],6:[2,4],29:[2,4],105:[2,4]},{4:81,7:4,8:6,9:7,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,29:[1,80],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,7],6:[2,7],29:[2,7],105:[2,7],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,8],6:[2,8],29:[2,8],105:[2,8],106:94,107:[1,69],109:[1,70],112:95,113:[1,72],114:73,129:[1,93]},{1:[2,14],6:[2,14],28:[2,14],29:[2,14],52:[2,14],57:[2,14],60:[2,14],65:97,69:[1,99],70:[1,100],71:[1,101],72:102,73:[1,103],75:[2,14],76:[1,104],80:[2,14],83:96,87:[1,98],88:[2,113],89:[2,14],94:[2,14],96:[2,14],105:[2,14],107:[2,14],108:[2,14],109:[2,14],113:[2,14],121:[2,14],129:[2,14],131:[2,14],132:[2,14],135:[2,14],136:[2,14],137:[2,14],138:[2,14],139:[2,14],140:[2,14]},{1:[2,15],6:[2,15],28:[2,15],29:[2,15],52:[2,15],57:[2,15],60:[2,15],65:106,69:[1,99],70:[1,100],71:[1,101],72:102,73:[1,103],75:[2,15],76:[1,104],80:[2,15],83:105,87:[1,98],88:[2,113],89:[2,15],94:[2,15],96:[2,15],105:[2,15],107:[2,15],108:[2,15],109:[2,15],113:[2,15],121:[2,15],129:[2,15],131:[2,15],132:[2,15],135:[2,15],136:[2,15],137:[2,15],138:[2,15],139:[2,15],140:[2,15]},{1:[2,16],6:[2,16],28:[2,16],29:[2,16],52:[2,16],57:[2,16],60:[2,16],75:[2,16],80:[2,16],89:[2,16],94:[2,16],96:[2,16],105:[2,16],107:[2,16],108:[2,16],109:[2,16],113:[2,16],121:[2,16],129:[2,16],131:[2,16],132:[2,16],135:[2,16],136:[2,16],137:[2,16],138:[2,16],139:[2,16],140:[2,16]},{1:[2,17],6:[2,17],28:[2,17],29:[2,17],52:[2,17],57:[2,17],60:[2,17],75:[2,17],80:[2,17],89:[2,17],94:[2,17],96:[2,17],105:[2,17],107:[2,17],108:[2,17],109:[2,17],113:[2,17],121:[2,17],129:[2,17],131:[2,17],132:[2,17],135:[2,17],136:[2,17],137:[2,17],138:[2,17],139:[2,17],140:[2,17]},{1:[2,18],6:[2,18],28:[2,18],29:[2,18],52:[2,18],57:[2,18],60:[2,18],75:[2,18],80:[2,18],89:[2,18],94:[2,18],96:[2,18],105:[2,18],107:[2,18],108:[2,18],109:[2,18],113:[2,18],121:[2,18],129:[2,18],131:[2,18],132:[2,18],135:[2,18],136:[2,18],137:[2,18],138:[2,18],139:[2,18],140:[2,18]},{1:[2,19],6:[2,19],28:[2,19],29:[2,19],52:[2,19],57:[2,19],60:[2,19],75:[2,19],80:[2,19],89:[2,19],94:[2,19],96:[2,19],105:[2,19],107:[2,19],108:[2,19],109:[2,19],113:[2,19],121:[2,19],129:[2,19],131:[2,19],132:[2,19],135:[2,19],136:[2,19],137:[2,19],138:[2,19],139:[2,19],140:[2,19]},{1:[2,20],6:[2,20],28:[2,20],29:[2,20],52:[2,20],57:[2,20],60:[2,20],75:[2,20],80:[2,20],89:[2,20],94:[2,20],96:[2,20],105:[2,20],107:[2,20],108:[2,20],109:[2,20],113:[2,20],121:[2,20],129:[2,20],131:[2,20],132:[2,20],135:[2,20],136:[2,20],137:[2,20],138:[2,20],139:[2,20],140:[2,20]},{1:[2,21],6:[2,21],28:[2,21],29:[2,21],52:[2,21],57:[2,21],60:[2,21],75:[2,21],80:[2,21],89:[2,21],94:[2,21],96:[2,21],105:[2,21],107:[2,21],108:[2,21],109:[2,21],113:[2,21],121:[2,21],129:[2,21],131:[2,21],132:[2,21],135:[2,21],136:[2,21],137:[2,21],138:[2,21],139:[2,21],140:[2,21]},{1:[2,22],6:[2,22],28:[2,22],29:[2,22],52:[2,22],57:[2,22],60:[2,22],75:[2,22],80:[2,22],89:[2,22],94:[2,22],96:[2,22],105:[2,22],107:[2,22],108:[2,22],109:[2,22],113:[2,22],121:[2,22],129:[2,22],131:[2,22],132:[2,22],135:[2,22],136:[2,22],137:[2,22],138:[2,22],139:[2,22],140:[2,22]},{1:[2,23],6:[2,23],28:[2,23],29:[2,23],52:[2,23],57:[2,23],60:[2,23],75:[2,23],80:[2,23],89:[2,23],94:[2,23],96:[2,23],105:[2,23],107:[2,23],108:[2,23],109:[2,23],113:[2,23],121:[2,23],129:[2,23],131:[2,23],132:[2,23],135:[2,23],136:[2,23],137:[2,23],138:[2,23],139:[2,23],140:[2,23]},{1:[2,24],6:[2,24],28:[2,24],29:[2,24],52:[2,24],57:[2,24],60:[2,24],75:[2,24],80:[2,24],89:[2,24],94:[2,24],96:[2,24],105:[2,24],107:[2,24],108:[2,24],109:[2,24],113:[2,24],121:[2,24],129:[2,24],131:[2,24],132:[2,24],135:[2,24],136:[2,24],137:[2,24],138:[2,24],139:[2,24],140:[2,24]},{1:[2,25],6:[2,25],28:[2,25],29:[2,25],52:[2,25],57:[2,25],60:[2,25],75:[2,25],80:[2,25],89:[2,25],94:[2,25],96:[2,25],105:[2,25],107:[2,25],108:[2,25],109:[2,25],113:[2,25],121:[2,25],129:[2,25],131:[2,25],132:[2,25],135:[2,25],136:[2,25],137:[2,25],138:[2,25],139:[2,25],140:[2,25]},{1:[2,26],6:[2,26],28:[2,26],29:[2,26],52:[2,26],57:[2,26],60:[2,26],75:[2,26],80:[2,26],89:[2,26],94:[2,26],96:[2,26],105:[2,26],107:[2,26],108:[2,26],109:[2,26],113:[2,26],121:[2,26],129:[2,26],131:[2,26],132:[2,26],135:[2,26],136:[2,26],137:[2,26],138:[2,26],139:[2,26],140:[2,26]},{1:[2,27],6:[2,27],28:[2,27],29:[2,27],52:[2,27],57:[2,27],60:[2,27],75:[2,27],80:[2,27],89:[2,27],94:[2,27],96:[2,27],105:[2,27],107:[2,27],108:[2,27],109:[2,27],113:[2,27],121:[2,27],129:[2,27],131:[2,27],132:[2,27],135:[2,27],136:[2,27],137:[2,27],138:[2,27],139:[2,27],140:[2,27]},{1:[2,9],6:[2,9],29:[2,9],105:[2,9],107:[2,9],109:[2,9],113:[2,9],129:[2,9]},{1:[2,10],6:[2,10],29:[2,10],105:[2,10],107:[2,10],109:[2,10],113:[2,10],129:[2,10]},{1:[2,11],6:[2,11],29:[2,11],105:[2,11],107:[2,11],109:[2,11],113:[2,11],129:[2,11]},{1:[2,79],6:[2,79],28:[2,79],29:[2,79],43:[1,107],52:[2,79],57:[2,79],60:[2,79],69:[2,79],70:[2,79],71:[2,79],73:[2,79],75:[2,79],76:[2,79],80:[2,79],87:[2,79],88:[2,79],89:[2,79],94:[2,79],96:[2,79],105:[2,79],107:[2,79],108:[2,79],109:[2,79],113:[2,79],121:[2,79],129:[2,79],131:[2,79],132:[2,79],135:[2,79],136:[2,79],137:[2,79],138:[2,79],139:[2,79],140:[2,79]},{1:[2,80],6:[2,80],28:[2,80],29:[2,80],52:[2,80],57:[2,80],60:[2,80],69:[2,80],70:[2,80],71:[2,80],73:[2,80],75:[2,80],76:[2,80],80:[2,80],87:[2,80],88:[2,80],89:[2,80],94:[2,80],96:[2,80],105:[2,80],107:[2,80],108:[2,80],109:[2,80],113:[2,80],121:[2,80],129:[2,80],131:[2,80],132:[2,80],135:[2,80],136:[2,80],137:[2,80],138:[2,80],139:[2,80],140:[2,80]},{1:[2,81],6:[2,81],28:[2,81],29:[2,81],52:[2,81],57:[2,81],60:[2,81],69:[2,81],70:[2,81],71:[2,81],73:[2,81],75:[2,81],76:[2,81],80:[2,81],87:[2,81],88:[2,81],89:[2,81],94:[2,81],96:[2,81],105:[2,81],107:[2,81],108:[2,81],109:[2,81],113:[2,81],121:[2,81],129:[2,81],131:[2,81],132:[2,81],135:[2,81],136:[2,81],137:[2,81],138:[2,81],139:[2,81],140:[2,81]},{1:[2,82],6:[2,82],28:[2,82],29:[2,82],52:[2,82],57:[2,82],60:[2,82],69:[2,82],70:[2,82],71:[2,82],73:[2,82],75:[2,82],76:[2,82],80:[2,82],87:[2,82],88:[2,82],89:[2,82],94:[2,82],96:[2,82],105:[2,82],107:[2,82],108:[2,82],109:[2,82],113:[2,82],121:[2,82],129:[2,82],131:[2,82],132:[2,82],135:[2,82],136:[2,82],137:[2,82],138:[2,82],139:[2,82],140:[2,82]},{1:[2,83],6:[2,83],28:[2,83],29:[2,83],52:[2,83],57:[2,83],60:[2,83],69:[2,83],70:[2,83],71:[2,83],73:[2,83],75:[2,83],76:[2,83],80:[2,83],87:[2,83],88:[2,83],89:[2,83],94:[2,83],96:[2,83],105:[2,83],107:[2,83],108:[2,83],109:[2,83],113:[2,83],121:[2,83],129:[2,83],131:[2,83],132:[2,83],135:[2,83],136:[2,83],137:[2,83],138:[2,83],139:[2,83],140:[2,83]},{1:[2,110],6:[2,110],28:[2,110],29:[2,110],52:[2,110],57:[2,110],60:[2,110],69:[2,110],70:[2,110],71:[2,110],73:[2,110],75:[2,110],76:[2,110],80:[2,110],84:108,87:[2,110],88:[1,109],89:[2,110],94:[2,110],96:[2,110],105:[2,110],107:[2,110],108:[2,110],109:[2,110],113:[2,110],121:[2,110],129:[2,110],131:[2,110],132:[2,110],135:[2,110],136:[2,110],137:[2,110],138:[2,110],139:[2,110],140:[2,110]},{6:[2,59],28:[2,59],30:113,31:[1,77],47:114,51:110,52:[2,59],57:[2,59],58:111,59:112,61:115,62:116,78:[1,74],92:[1,117],93:[1,118]},{5:119,28:[1,5]},{8:120,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:122,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:123,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{15:125,16:126,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:127,47:67,61:51,62:52,64:124,66:27,67:28,68:29,78:[1,74],85:[1,30],91:[1,62],92:[1,63],93:[1,61],104:[1,60]},{15:125,16:126,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:127,47:67,61:51,62:52,64:128,66:27,67:28,68:29,78:[1,74],85:[1,30],91:[1,62],92:[1,63],93:[1,61],104:[1,60]},{1:[2,76],6:[2,76],28:[2,76],29:[2,76],43:[2,76],52:[2,76],57:[2,76],60:[2,76],69:[2,76],70:[2,76],71:[2,76],73:[2,76],75:[2,76],76:[2,76],80:[2,76],82:[1,132],87:[2,76],88:[2,76],89:[2,76],94:[2,76],96:[2,76],105:[2,76],107:[2,76],108:[2,76],109:[2,76],113:[2,76],121:[2,76],129:[2,76],131:[2,76],132:[2,76],133:[1,129],134:[1,130],135:[2,76],136:[2,76],137:[2,76],138:[2,76],139:[2,76],140:[2,76],141:[1,131]},{1:[2,186],6:[2,186],28:[2,186],29:[2,186],52:[2,186],57:[2,186],60:[2,186],75:[2,186],80:[2,186],89:[2,186],94:[2,186],96:[2,186],105:[2,186],107:[2,186],108:[2,186],109:[2,186],113:[2,186],121:[2,186],124:[1,133],129:[2,186],131:[2,186],132:[2,186],135:[2,186],136:[2,186],137:[2,186],138:[2,186],139:[2,186],140:[2,186]},{5:134,28:[1,5]},{5:135,28:[1,5]},{1:[2,153],6:[2,153],28:[2,153],29:[2,153],52:[2,153],57:[2,153],60:[2,153],75:[2,153],80:[2,153],89:[2,153],94:[2,153],96:[2,153],105:[2,153],107:[2,153],108:[2,153],109:[2,153],113:[2,153],121:[2,153],129:[2,153],131:[2,153],132:[2,153],135:[2,153],136:[2,153],137:[2,153],138:[2,153],139:[2,153],140:[2,153]},{5:136,28:[1,5]},{8:137,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,138],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,100],5:139,6:[2,100],15:125,16:126,28:[1,5],29:[2,100],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:127,47:67,52:[2,100],57:[2,100],60:[2,100],61:51,62:52,64:141,66:27,67:28,68:29,75:[2,100],78:[1,74],80:[2,100],82:[1,140],85:[1,30],89:[2,100],91:[1,62],92:[1,63],93:[1,61],94:[2,100],96:[2,100],104:[1,60],105:[2,100],107:[2,100],108:[2,100],109:[2,100],113:[2,100],121:[2,100],129:[2,100],131:[2,100],132:[2,100],135:[2,100],136:[2,100],137:[2,100],138:[2,100],139:[2,100],140:[2,100]},{8:142,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{84:143,88:[1,109]},{5:144,8:145,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,5],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,51],6:[2,51],8:146,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,29:[2,51],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],105:[2,51],106:41,107:[2,51],109:[2,51],110:42,111:[1,71],112:43,113:[2,51],114:73,122:[1,44],127:39,128:[1,68],129:[2,51],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,52],6:[2,52],28:[2,52],29:[2,52],57:[2,52],80:[2,52],105:[2,52],107:[2,52],109:[2,52],113:[2,52],129:[2,52]},{1:[2,77],6:[2,77],28:[2,77],29:[2,77],43:[2,77],52:[2,77],57:[2,77],60:[2,77],69:[2,77],70:[2,77],71:[2,77],73:[2,77],75:[2,77],76:[2,77],80:[2,77],87:[2,77],88:[2,77],89:[2,77],94:[2,77],96:[2,77],105:[2,77],107:[2,77],108:[2,77],109:[2,77],113:[2,77],121:[2,77],129:[2,77],131:[2,77],132:[2,77],135:[2,77],136:[2,77],137:[2,77],138:[2,77],139:[2,77],140:[2,77]},{1:[2,78],6:[2,78],28:[2,78],29:[2,78],43:[2,78],52:[2,78],57:[2,78],60:[2,78],69:[2,78],70:[2,78],71:[2,78],73:[2,78],75:[2,78],76:[2,78],80:[2,78],87:[2,78],88:[2,78],89:[2,78],94:[2,78],96:[2,78],105:[2,78],107:[2,78],108:[2,78],109:[2,78],113:[2,78],121:[2,78],129:[2,78],131:[2,78],132:[2,78],135:[2,78],136:[2,78],137:[2,78],138:[2,78],139:[2,78],140:[2,78]},{1:[2,33],6:[2,33],28:[2,33],29:[2,33],52:[2,33],57:[2,33],60:[2,33],69:[2,33],70:[2,33],71:[2,33],73:[2,33],75:[2,33],76:[2,33],80:[2,33],87:[2,33],88:[2,33],89:[2,33],94:[2,33],96:[2,33],105:[2,33],107:[2,33],108:[2,33],109:[2,33],113:[2,33],121:[2,33],129:[2,33],131:[2,33],132:[2,33],135:[2,33],136:[2,33],137:[2,33],138:[2,33],139:[2,33],140:[2,33]},{1:[2,34],6:[2,34],28:[2,34],29:[2,34],52:[2,34],57:[2,34],60:[2,34],69:[2,34],70:[2,34],71:[2,34],73:[2,34],75:[2,34],76:[2,34],80:[2,34],87:[2,34],88:[2,34],89:[2,34],94:[2,34],96:[2,34],105:[2,34],107:[2,34],108:[2,34],109:[2,34],113:[2,34],121:[2,34],129:[2,34],131:[2,34],132:[2,34],135:[2,34],136:[2,34],137:[2,34],138:[2,34],139:[2,34],140:[2,34]},{1:[2,35],6:[2,35],28:[2,35],29:[2,35],52:[2,35],57:[2,35],60:[2,35],69:[2,35],70:[2,35],71:[2,35],73:[2,35],75:[2,35],76:[2,35],80:[2,35],87:[2,35],88:[2,35],89:[2,35],94:[2,35],96:[2,35],105:[2,35],107:[2,35],108:[2,35],109:[2,35],113:[2,35],121:[2,35],129:[2,35],131:[2,35],132:[2,35],135:[2,35],136:[2,35],137:[2,35],138:[2,35],139:[2,35],140:[2,35]},{1:[2,36],6:[2,36],28:[2,36],29:[2,36],52:[2,36],57:[2,36],60:[2,36],69:[2,36],70:[2,36],71:[2,36],73:[2,36],75:[2,36],76:[2,36],80:[2,36],87:[2,36],88:[2,36],89:[2,36],94:[2,36],96:[2,36],105:[2,36],107:[2,36],108:[2,36],109:[2,36],113:[2,36],121:[2,36],129:[2,36],131:[2,36],132:[2,36],135:[2,36],136:[2,36],137:[2,36],138:[2,36],139:[2,36],140:[2,36]},{1:[2,37],6:[2,37],28:[2,37],29:[2,37],52:[2,37],57:[2,37],60:[2,37],69:[2,37],70:[2,37],71:[2,37],73:[2,37],75:[2,37],76:[2,37],80:[2,37],87:[2,37],88:[2,37],89:[2,37],94:[2,37],96:[2,37],105:[2,37],107:[2,37],108:[2,37],109:[2,37],113:[2,37],121:[2,37],129:[2,37],131:[2,37],132:[2,37],135:[2,37],136:[2,37],137:[2,37],138:[2,37],139:[2,37],140:[2,37]},{1:[2,38],6:[2,38],28:[2,38],29:[2,38],52:[2,38],57:[2,38],60:[2,38],69:[2,38],70:[2,38],71:[2,38],73:[2,38],75:[2,38],76:[2,38],80:[2,38],87:[2,38],88:[2,38],89:[2,38],94:[2,38],96:[2,38],105:[2,38],107:[2,38],108:[2,38],109:[2,38],113:[2,38],121:[2,38],129:[2,38],131:[2,38],132:[2,38],135:[2,38],136:[2,38],137:[2,38],138:[2,38],139:[2,38],140:[2,38]},{1:[2,39],6:[2,39],28:[2,39],29:[2,39],52:[2,39],57:[2,39],60:[2,39],69:[2,39],70:[2,39],71:[2,39],73:[2,39],75:[2,39],76:[2,39],80:[2,39],87:[2,39],88:[2,39],89:[2,39],94:[2,39],96:[2,39],105:[2,39],107:[2,39],108:[2,39],109:[2,39],113:[2,39],121:[2,39],129:[2,39],131:[2,39],132:[2,39],135:[2,39],136:[2,39],137:[2,39],138:[2,39],139:[2,39],140:[2,39]},{4:147,7:4,8:6,9:7,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,148],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:149,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,153],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],90:151,91:[1,62],92:[1,63],93:[1,61],94:[1,150],97:152,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,117],6:[2,117],28:[2,117],29:[2,117],52:[2,117],57:[2,117],60:[2,117],69:[2,117],70:[2,117],71:[2,117],73:[2,117],75:[2,117],76:[2,117],80:[2,117],87:[2,117],88:[2,117],89:[2,117],94:[2,117],96:[2,117],105:[2,117],107:[2,117],108:[2,117],109:[2,117],113:[2,117],121:[2,117],129:[2,117],131:[2,117],132:[2,117],135:[2,117],136:[2,117],137:[2,117],138:[2,117],139:[2,117],140:[2,117]},{1:[2,118],6:[2,118],28:[2,118],29:[2,118],30:155,31:[1,77],52:[2,118],57:[2,118],60:[2,118],69:[2,118],70:[2,118],71:[2,118],73:[2,118],75:[2,118],76:[2,118],80:[2,118],87:[2,118],88:[2,118],89:[2,118],94:[2,118],96:[2,118],105:[2,118],107:[2,118],108:[2,118],109:[2,118],113:[2,118],121:[2,118],129:[2,118],131:[2,118],132:[2,118],135:[2,118],136:[2,118],137:[2,118],138:[2,118],139:[2,118],140:[2,118]},{28:[2,55]},{28:[2,56]},{1:[2,72],6:[2,72],28:[2,72],29:[2,72],43:[2,72],52:[2,72],57:[2,72],60:[2,72],69:[2,72],70:[2,72],71:[2,72],73:[2,72],75:[2,72],76:[2,72],80:[2,72],82:[2,72],87:[2,72],88:[2,72],89:[2,72],94:[2,72],96:[2,72],105:[2,72],107:[2,72],108:[2,72],109:[2,72],113:[2,72],121:[2,72],129:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[2,72],138:[2,72],139:[2,72],140:[2,72],141:[2,72]},{1:[2,75],6:[2,75],28:[2,75],29:[2,75],43:[2,75],52:[2,75],57:[2,75],60:[2,75],69:[2,75],70:[2,75],71:[2,75],73:[2,75],75:[2,75],76:[2,75],80:[2,75],82:[2,75],87:[2,75],88:[2,75],89:[2,75],94:[2,75],96:[2,75],105:[2,75],107:[2,75],108:[2,75],109:[2,75],113:[2,75],121:[2,75],129:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75],137:[2,75],138:[2,75],139:[2,75],140:[2,75],141:[2,75]},{8:156,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:157,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:158,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{5:159,8:160,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,5],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{30:165,31:[1,77],47:166,61:167,62:168,67:161,78:[1,74],92:[1,117],93:[1,61],116:162,117:[1,163],118:164},{115:169,119:[1,170],120:[1,171]},{6:[2,95],11:175,28:[2,95],30:176,31:[1,77],32:177,33:[1,75],34:[1,76],44:173,45:174,47:178,49:[1,50],57:[2,95],79:172,80:[2,95],92:[1,117]},{1:[2,31],6:[2,31],28:[2,31],29:[2,31],46:[2,31],52:[2,31],57:[2,31],60:[2,31],69:[2,31],70:[2,31],71:[2,31],73:[2,31],75:[2,31],76:[2,31],80:[2,31],87:[2,31],88:[2,31],89:[2,31],94:[2,31],96:[2,31],105:[2,31],107:[2,31],108:[2,31],109:[2,31],113:[2,31],121:[2,31],129:[2,31],131:[2,31],132:[2,31],135:[2,31],136:[2,31],137:[2,31],138:[2,31],139:[2,31],140:[2,31]},{1:[2,32],6:[2,32],28:[2,32],29:[2,32],46:[2,32],52:[2,32],57:[2,32],60:[2,32],69:[2,32],70:[2,32],71:[2,32],73:[2,32],75:[2,32],76:[2,32],80:[2,32],87:[2,32],88:[2,32],89:[2,32],94:[2,32],96:[2,32],105:[2,32],107:[2,32],108:[2,32],109:[2,32],113:[2,32],121:[2,32],129:[2,32],131:[2,32],132:[2,32],135:[2,32],136:[2,32],137:[2,32],138:[2,32],139:[2,32],140:[2,32]},{1:[2,30],6:[2,30],28:[2,30],29:[2,30],43:[2,30],46:[2,30],52:[2,30],57:[2,30],60:[2,30],69:[2,30],70:[2,30],71:[2,30],73:[2,30],75:[2,30],76:[2,30],80:[2,30],82:[2,30],87:[2,30],88:[2,30],89:[2,30],94:[2,30],96:[2,30],105:[2,30],107:[2,30],108:[2,30],109:[2,30],113:[2,30],119:[2,30],120:[2,30],121:[2,30],129:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30],137:[2,30],138:[2,30],139:[2,30],140:[2,30],141:[2,30]},{1:[2,6],6:[2,6],7:179,8:6,9:7,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,29:[2,6],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],105:[2,6],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,3]},{1:[2,28],6:[2,28],28:[2,28],29:[2,28],52:[2,28],57:[2,28],60:[2,28],75:[2,28],80:[2,28],89:[2,28],94:[2,28],96:[2,28],101:[2,28],102:[2,28],105:[2,28],107:[2,28],108:[2,28],109:[2,28],113:[2,28],121:[2,28],124:[2,28],126:[2,28],129:[2,28],131:[2,28],132:[2,28],135:[2,28],136:[2,28],137:[2,28],138:[2,28],139:[2,28],140:[2,28]},{6:[1,78],29:[1,180]},{1:[2,197],6:[2,197],28:[2,197],29:[2,197],52:[2,197],57:[2,197],60:[2,197],75:[2,197],80:[2,197],89:[2,197],94:[2,197],96:[2,197],105:[2,197],107:[2,197],108:[2,197],109:[2,197],113:[2,197],121:[2,197],129:[2,197],131:[2,197],132:[2,197],135:[2,197],136:[2,197],137:[2,197],138:[2,197],139:[2,197],140:[2,197]},{8:181,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:182,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:183,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:184,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:185,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:186,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:187,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:188,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,152],6:[2,152],28:[2,152],29:[2,152],52:[2,152],57:[2,152],60:[2,152],75:[2,152],80:[2,152],89:[2,152],94:[2,152],96:[2,152],105:[2,152],107:[2,152],108:[2,152],109:[2,152],113:[2,152],121:[2,152],129:[2,152],131:[2,152],132:[2,152],135:[2,152],136:[2,152],137:[2,152],138:[2,152],139:[2,152],140:[2,152]},{1:[2,157],6:[2,157],28:[2,157],29:[2,157],52:[2,157],57:[2,157],60:[2,157],75:[2,157],80:[2,157],89:[2,157],94:[2,157],96:[2,157],105:[2,157],107:[2,157],108:[2,157],109:[2,157],113:[2,157],121:[2,157],129:[2,157],131:[2,157],132:[2,157],135:[2,157],136:[2,157],137:[2,157],138:[2,157],139:[2,157],140:[2,157]},{8:189,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,151],6:[2,151],28:[2,151],29:[2,151],52:[2,151],57:[2,151],60:[2,151],75:[2,151],80:[2,151],89:[2,151],94:[2,151],96:[2,151],105:[2,151],107:[2,151],108:[2,151],109:[2,151],113:[2,151],121:[2,151],129:[2,151],131:[2,151],132:[2,151],135:[2,151],136:[2,151],137:[2,151],138:[2,151],139:[2,151],140:[2,151]},{1:[2,156],6:[2,156],28:[2,156],29:[2,156],52:[2,156],57:[2,156],60:[2,156],75:[2,156],80:[2,156],89:[2,156],94:[2,156],96:[2,156],105:[2,156],107:[2,156],108:[2,156],109:[2,156],113:[2,156],121:[2,156],129:[2,156],131:[2,156],132:[2,156],135:[2,156],136:[2,156],137:[2,156],138:[2,156],139:[2,156],140:[2,156]},{84:190,88:[1,109]},{1:[2,73],6:[2,73],28:[2,73],29:[2,73],43:[2,73],52:[2,73],57:[2,73],60:[2,73],69:[2,73],70:[2,73],71:[2,73],73:[2,73],75:[2,73],76:[2,73],80:[2,73],82:[2,73],87:[2,73],88:[2,73],89:[2,73],94:[2,73],96:[2,73],105:[2,73],107:[2,73],108:[2,73],109:[2,73],113:[2,73],121:[2,73],129:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73],137:[2,73],138:[2,73],139:[2,73],140:[2,73],141:[2,73]},{88:[2,114]},{27:192,30:191,31:[1,77],86:[1,47]},{30:193,31:[1,77]},{1:[2,88],6:[2,88],28:[2,88],29:[2,88],30:194,31:[1,77],43:[2,88],52:[2,88],57:[2,88],60:[2,88],69:[2,88],70:[2,88],71:[2,88],73:[2,88],75:[2,88],76:[2,88],80:[2,88],82:[2,88],87:[2,88],88:[2,88],89:[2,88],94:[2,88],96:[2,88],105:[2,88],107:[2,88],108:[2,88],109:[2,88],113:[2,88],121:[2,88],129:[2,88],131:[2,88],132:[2,88],133:[2,88],134:[2,88],135:[2,88],136:[2,88],137:[2,88],138:[2,88],139:[2,88],140:[2,88],141:[2,88]},{1:[2,89],6:[2,89],28:[2,89],29:[2,89],43:[2,89],52:[2,89],57:[2,89],60:[2,89],69:[2,89],70:[2,89],71:[2,89],73:[2,89],75:[2,89],76:[2,89],80:[2,89],82:[2,89],87:[2,89],88:[2,89],89:[2,89],94:[2,89],96:[2,89],105:[2,89],107:[2,89],108:[2,89],109:[2,89],113:[2,89],121:[2,89],129:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89],137:[2,89],138:[2,89],139:[2,89],140:[2,89],141:[2,89]},{8:196,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],60:[1,200],61:51,62:52,64:38,66:27,67:28,68:29,74:195,77:197,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],95:198,96:[1,199],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{72:201,73:[1,103],76:[1,104]},{84:202,88:[1,109]},{1:[2,74],6:[2,74],28:[2,74],29:[2,74],43:[2,74],52:[2,74],57:[2,74],60:[2,74],69:[2,74],70:[2,74],71:[2,74],73:[2,74],75:[2,74],76:[2,74],80:[2,74],82:[2,74],87:[2,74],88:[2,74],89:[2,74],94:[2,74],96:[2,74],105:[2,74],107:[2,74],108:[2,74],109:[2,74],113:[2,74],121:[2,74],129:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74],137:[2,74],138:[2,74],139:[2,74],140:[2,74],141:[2,74]},{6:[1,204],8:203,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,205],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,111],6:[2,111],28:[2,111],29:[2,111],52:[2,111],57:[2,111],60:[2,111],69:[2,111],70:[2,111],71:[2,111],73:[2,111],75:[2,111],76:[2,111],80:[2,111],87:[2,111],88:[2,111],89:[2,111],94:[2,111],96:[2,111],105:[2,111],107:[2,111],108:[2,111],109:[2,111],113:[2,111],121:[2,111],129:[2,111],131:[2,111],132:[2,111],135:[2,111],136:[2,111],137:[2,111],138:[2,111],139:[2,111],140:[2,111]},{8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,153],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],89:[1,206],90:207,91:[1,62],92:[1,63],93:[1,61],97:152,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,57],28:[2,57],52:[1,209],56:211,57:[1,210]},{6:[2,60],28:[2,60],29:[2,60],52:[2,60],57:[2,60]},{6:[2,64],28:[2,64],29:[2,64],43:[1,213],52:[2,64],57:[2,64],60:[1,212]},{6:[2,67],28:[2,67],29:[2,67],43:[2,67],52:[2,67],57:[2,67],60:[2,67]},{6:[2,68],28:[2,68],29:[2,68],43:[2,68],52:[2,68],57:[2,68],60:[2,68]},{6:[2,69],28:[2,69],29:[2,69],43:[2,69],52:[2,69],57:[2,69],60:[2,69]},{6:[2,70],28:[2,70],29:[2,70],43:[2,70],52:[2,70],57:[2,70],60:[2,70]},{30:155,31:[1,77]},{8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,153],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],90:151,91:[1,62],92:[1,63],93:[1,61],94:[1,150],97:152,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,54],6:[2,54],28:[2,54],29:[2,54],52:[2,54],57:[2,54],60:[2,54],75:[2,54],80:[2,54],89:[2,54],94:[2,54],96:[2,54],105:[2,54],107:[2,54],108:[2,54],109:[2,54],113:[2,54],121:[2,54],129:[2,54],131:[2,54],132:[2,54],135:[2,54],136:[2,54],137:[2,54],138:[2,54],139:[2,54],140:[2,54]},{1:[2,190],6:[2,190],28:[2,190],29:[2,190],52:[2,190],57:[2,190],60:[2,190],75:[2,190],80:[2,190],89:[2,190],94:[2,190],96:[2,190],105:[2,190],106:91,107:[2,190],108:[2,190],109:[2,190],112:92,113:[2,190],114:73,121:[2,190],129:[2,190],131:[2,190],132:[2,190],135:[1,82],136:[2,190],137:[2,190],138:[2,190],139:[2,190],140:[2,190]},{106:94,107:[1,69],109:[1,70],112:95,113:[1,72],114:73,129:[1,93]},{1:[2,191],6:[2,191],28:[2,191],29:[2,191],52:[2,191],57:[2,191],60:[2,191],75:[2,191],80:[2,191],89:[2,191],94:[2,191],96:[2,191],105:[2,191],106:91,107:[2,191],108:[2,191],109:[2,191],112:92,113:[2,191],114:73,121:[2,191],129:[2,191],131:[2,191],132:[2,191],135:[1,82],136:[2,191],137:[2,191],138:[2,191],139:[2,191],140:[2,191]},{1:[2,192],6:[2,192],28:[2,192],29:[2,192],52:[2,192],57:[2,192],60:[2,192],75:[2,192],80:[2,192],89:[2,192],94:[2,192],96:[2,192],105:[2,192],106:91,107:[2,192],108:[2,192],109:[2,192],112:92,113:[2,192],114:73,121:[2,192],129:[2,192],131:[2,192],132:[2,192],135:[1,82],136:[2,192],137:[2,192],138:[2,192],139:[2,192],140:[2,192]},{1:[2,193],6:[2,193],28:[2,193],29:[2,193],52:[2,193],57:[2,193],60:[2,193],69:[2,76],70:[2,76],71:[2,76],73:[2,76],75:[2,193],76:[2,76],80:[2,193],87:[2,76],88:[2,76],89:[2,193],94:[2,193],96:[2,193],105:[2,193],107:[2,193],108:[2,193],109:[2,193],113:[2,193],121:[2,193],129:[2,193],131:[2,193],132:[2,193],135:[2,193],136:[2,193],137:[2,193],138:[2,193],139:[2,193],140:[2,193]},{65:97,69:[1,99],70:[1,100],71:[1,101],72:102,73:[1,103],76:[1,104],83:96,87:[1,98],88:[2,113]},{65:106,69:[1,99],70:[1,100],71:[1,101],72:102,73:[1,103],76:[1,104],83:105,87:[1,98],88:[2,113]},{69:[2,79],70:[2,79],71:[2,79],73:[2,79],76:[2,79],87:[2,79],88:[2,79]},{1:[2,194],6:[2,194],28:[2,194],29:[2,194],52:[2,194],57:[2,194],60:[2,194],69:[2,76],70:[2,76],71:[2,76],73:[2,76],75:[2,194],76:[2,76],80:[2,194],87:[2,76],88:[2,76],89:[2,194],94:[2,194],96:[2,194],105:[2,194],107:[2,194],108:[2,194],109:[2,194],113:[2,194],121:[2,194],129:[2,194],131:[2,194],132:[2,194],135:[2,194],136:[2,194],137:[2,194],138:[2,194],139:[2,194],140:[2,194]},{1:[2,195],6:[2,195],28:[2,195],29:[2,195],52:[2,195],57:[2,195],60:[2,195],75:[2,195],80:[2,195],89:[2,195],94:[2,195],96:[2,195],105:[2,195],107:[2,195],108:[2,195],109:[2,195],113:[2,195],121:[2,195],129:[2,195],131:[2,195],132:[2,195],135:[2,195],136:[2,195],137:[2,195],138:[2,195],139:[2,195],140:[2,195]},{1:[2,196],6:[2,196],28:[2,196],29:[2,196],52:[2,196],57:[2,196],60:[2,196],75:[2,196],80:[2,196],89:[2,196],94:[2,196],96:[2,196],105:[2,196],107:[2,196],108:[2,196],109:[2,196],113:[2,196],121:[2,196],129:[2,196],131:[2,196],132:[2,196],135:[2,196],136:[2,196],137:[2,196],138:[2,196],139:[2,196],140:[2,196]},{8:214,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,215],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:216,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{5:217,28:[1,5],128:[1,218]},{1:[2,138],6:[2,138],28:[2,138],29:[2,138],52:[2,138],57:[2,138],60:[2,138],75:[2,138],80:[2,138],89:[2,138],94:[2,138],96:[2,138],100:219,101:[1,220],102:[1,221],105:[2,138],107:[2,138],108:[2,138],109:[2,138],113:[2,138],121:[2,138],129:[2,138],131:[2,138],132:[2,138],135:[2,138],136:[2,138],137:[2,138],138:[2,138],139:[2,138],140:[2,138]},{1:[2,150],6:[2,150],28:[2,150],29:[2,150],52:[2,150],57:[2,150],60:[2,150],75:[2,150],80:[2,150],89:[2,150],94:[2,150],96:[2,150],105:[2,150],107:[2,150],108:[2,150],109:[2,150],113:[2,150],121:[2,150],129:[2,150],131:[2,150],132:[2,150],135:[2,150],136:[2,150],137:[2,150],138:[2,150],139:[2,150],140:[2,150]},{1:[2,158],6:[2,158],28:[2,158],29:[2,158],52:[2,158],57:[2,158],60:[2,158],75:[2,158],80:[2,158],89:[2,158],94:[2,158],96:[2,158],105:[2,158],107:[2,158],108:[2,158],109:[2,158],113:[2,158],121:[2,158],129:[2,158],131:[2,158],132:[2,158],135:[2,158],136:[2,158],137:[2,158],138:[2,158],139:[2,158],140:[2,158]},{28:[1,222],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{123:223,125:224,126:[1,225]},{1:[2,101],6:[2,101],28:[2,101],29:[2,101],52:[2,101],57:[2,101],60:[2,101],75:[2,101],80:[2,101],89:[2,101],94:[2,101],96:[2,101],105:[2,101],107:[2,101],108:[2,101],109:[2,101],113:[2,101],121:[2,101],129:[2,101],131:[2,101],132:[2,101],135:[2,101],136:[2,101],137:[2,101],138:[2,101],139:[2,101],140:[2,101]},{8:226,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,104],5:227,6:[2,104],28:[1,5],29:[2,104],52:[2,104],57:[2,104],60:[2,104],69:[2,76],70:[2,76],71:[2,76],73:[2,76],75:[2,104],76:[2,76],80:[2,104],82:[1,228],87:[2,76],88:[2,76],89:[2,104],94:[2,104],96:[2,104],105:[2,104],107:[2,104],108:[2,104],109:[2,104],113:[2,104],121:[2,104],129:[2,104],131:[2,104],132:[2,104],135:[2,104],136:[2,104],137:[2,104],138:[2,104],139:[2,104],140:[2,104]},{1:[2,143],6:[2,143],28:[2,143],29:[2,143],52:[2,143],57:[2,143],60:[2,143],75:[2,143],80:[2,143],89:[2,143],94:[2,143],96:[2,143],105:[2,143],106:91,107:[2,143],108:[2,143],109:[2,143],112:92,113:[2,143],114:73,121:[2,143],129:[2,143],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,112],6:[2,112],28:[2,112],29:[2,112],43:[2,112],52:[2,112],57:[2,112],60:[2,112],69:[2,112],70:[2,112],71:[2,112],73:[2,112],75:[2,112],76:[2,112],80:[2,112],82:[2,112],87:[2,112],88:[2,112],89:[2,112],94:[2,112],96:[2,112],105:[2,112],107:[2,112],108:[2,112],109:[2,112],113:[2,112],121:[2,112],129:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112],137:[2,112],138:[2,112],139:[2,112],140:[2,112],141:[2,112]},{1:[2,12],6:[2,12],28:[2,12],29:[2,12],52:[2,12],57:[2,12],60:[2,12],75:[2,12],80:[2,12],89:[2,12],94:[2,12],96:[2,12],105:[2,12],107:[2,12],108:[2,12],109:[2,12],113:[2,12],121:[2,12],129:[2,12],131:[2,12],132:[2,12],135:[2,12],136:[2,12],137:[2,12],138:[2,12],139:[2,12],140:[2,12]},{1:[2,13],6:[2,13],28:[2,13],29:[2,13],52:[2,13],57:[2,13],60:[2,13],75:[2,13],80:[2,13],89:[2,13],94:[2,13],96:[2,13],105:[2,13],106:91,107:[1,69],108:[2,13],109:[1,70],112:92,113:[1,72],114:73,121:[2,13],129:[2,13],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,50],6:[2,50],29:[2,50],105:[2,50],106:91,107:[2,50],109:[2,50],112:92,113:[2,50],114:73,129:[2,50],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[1,78],105:[1,229]},{4:230,7:4,8:6,9:7,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,134],28:[2,134],57:[2,134],60:[1,232],94:[2,134],95:231,96:[1,199],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,120],6:[2,120],28:[2,120],29:[2,120],43:[2,120],52:[2,120],57:[2,120],60:[2,120],69:[2,120],70:[2,120],71:[2,120],73:[2,120],75:[2,120],76:[2,120],80:[2,120],87:[2,120],88:[2,120],89:[2,120],94:[2,120],96:[2,120],105:[2,120],107:[2,120],108:[2,120],109:[2,120],113:[2,120],119:[2,120],120:[2,120],121:[2,120],129:[2,120],131:[2,120],132:[2,120],135:[2,120],136:[2,120],137:[2,120],138:[2,120],139:[2,120],140:[2,120]},{6:[2,57],28:[2,57],56:233,57:[1,234],94:[2,57]},{6:[2,129],28:[2,129],29:[2,129],57:[2,129],89:[2,129],94:[2,129]},{8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,153],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],90:235,91:[1,62],92:[1,63],93:[1,61],97:152,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,135],28:[2,135],29:[2,135],57:[2,135],89:[2,135],94:[2,135]},{1:[2,119],6:[2,119],28:[2,119],29:[2,119],43:[2,119],46:[2,119],52:[2,119],57:[2,119],60:[2,119],69:[2,119],70:[2,119],71:[2,119],73:[2,119],75:[2,119],76:[2,119],80:[2,119],82:[2,119],87:[2,119],88:[2,119],89:[2,119],94:[2,119],96:[2,119],105:[2,119],107:[2,119],108:[2,119],109:[2,119],113:[2,119],119:[2,119],120:[2,119],121:[2,119],129:[2,119],131:[2,119],132:[2,119],133:[2,119],134:[2,119],135:[2,119],136:[2,119],137:[2,119],138:[2,119],139:[2,119],140:[2,119],141:[2,119]},{5:236,28:[1,5],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,146],6:[2,146],28:[2,146],29:[2,146],52:[2,146],57:[2,146],60:[2,146],75:[2,146],80:[2,146],89:[2,146],94:[2,146],96:[2,146],105:[2,146],106:91,107:[1,69],108:[1,237],109:[1,70],112:92,113:[1,72],114:73,121:[2,146],129:[2,146],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,148],6:[2,148],28:[2,148],29:[2,148],52:[2,148],57:[2,148],60:[2,148],75:[2,148],80:[2,148],89:[2,148],94:[2,148],96:[2,148],105:[2,148],106:91,107:[1,69],108:[1,238],109:[1,70],112:92,113:[1,72],114:73,121:[2,148],129:[2,148],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,154],6:[2,154],28:[2,154],29:[2,154],52:[2,154],57:[2,154],60:[2,154],75:[2,154],80:[2,154],89:[2,154],94:[2,154],96:[2,154],105:[2,154],107:[2,154],108:[2,154],109:[2,154],113:[2,154],121:[2,154],129:[2,154],131:[2,154],132:[2,154],135:[2,154],136:[2,154],137:[2,154],138:[2,154],139:[2,154],140:[2,154]},{1:[2,155],6:[2,155],28:[2,155],29:[2,155],52:[2,155],57:[2,155],60:[2,155],75:[2,155],80:[2,155],89:[2,155],94:[2,155],96:[2,155],105:[2,155],106:91,107:[1,69],108:[2,155],109:[1,70],112:92,113:[1,72],114:73,121:[2,155],129:[2,155],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,159],6:[2,159],28:[2,159],29:[2,159],52:[2,159],57:[2,159],60:[2,159],75:[2,159],80:[2,159],89:[2,159],94:[2,159],96:[2,159],105:[2,159],107:[2,159],108:[2,159],109:[2,159],113:[2,159],121:[2,159],129:[2,159],131:[2,159],132:[2,159],135:[2,159],136:[2,159],137:[2,159],138:[2,159],139:[2,159],140:[2,159]},{119:[2,161],120:[2,161]},{30:165,31:[1,77],47:166,61:167,62:168,78:[1,74],92:[1,117],93:[1,118],116:239,118:164},{57:[1,240],119:[2,167],120:[2,167]},{57:[2,163],119:[2,163],120:[2,163]},{57:[2,164],119:[2,164],120:[2,164]},{57:[2,165],119:[2,165],120:[2,165]},{57:[2,166],119:[2,166],120:[2,166]},{1:[2,160],6:[2,160],28:[2,160],29:[2,160],52:[2,160],57:[2,160],60:[2,160],75:[2,160],80:[2,160],89:[2,160],94:[2,160],96:[2,160],105:[2,160],107:[2,160],108:[2,160],109:[2,160],113:[2,160],121:[2,160],129:[2,160],131:[2,160],132:[2,160],135:[2,160],136:[2,160],137:[2,160],138:[2,160],139:[2,160],140:[2,160]},{8:241,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:242,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,57],28:[2,57],56:243,57:[1,244],80:[2,57]},{6:[2,96],28:[2,96],29:[2,96],57:[2,96],80:[2,96]},{6:[2,43],28:[2,43],29:[2,43],46:[1,245],57:[2,43],80:[2,43]},{6:[2,46],28:[2,46],29:[2,46],57:[2,46],80:[2,46]},{6:[2,47],28:[2,47],29:[2,47],46:[2,47],57:[2,47],80:[2,47]},{6:[2,48],28:[2,48],29:[2,48],46:[2,48],57:[2,48],80:[2,48]},{6:[2,49],28:[2,49],29:[2,49],46:[2,49],57:[2,49],80:[2,49]},{1:[2,5],6:[2,5],29:[2,5],105:[2,5]},{1:[2,29],6:[2,29],28:[2,29],29:[2,29],52:[2,29],57:[2,29],60:[2,29],75:[2,29],80:[2,29],89:[2,29],94:[2,29],96:[2,29],101:[2,29],102:[2,29],105:[2,29],107:[2,29],108:[2,29],109:[2,29],113:[2,29],121:[2,29],124:[2,29],126:[2,29],129:[2,29],131:[2,29],132:[2,29],135:[2,29],136:[2,29],137:[2,29],138:[2,29],139:[2,29],140:[2,29]},{1:[2,198],6:[2,198],28:[2,198],29:[2,198],52:[2,198],57:[2,198],60:[2,198],75:[2,198],80:[2,198],89:[2,198],94:[2,198],96:[2,198],105:[2,198],106:91,107:[2,198],108:[2,198],109:[2,198],112:92,113:[2,198],114:73,121:[2,198],129:[2,198],131:[2,198],132:[2,198],135:[1,82],136:[1,85],137:[2,198],138:[2,198],139:[2,198],140:[2,198]},{1:[2,199],6:[2,199],28:[2,199],29:[2,199],52:[2,199],57:[2,199],60:[2,199],75:[2,199],80:[2,199],89:[2,199],94:[2,199],96:[2,199],105:[2,199],106:91,107:[2,199],108:[2,199],109:[2,199],112:92,113:[2,199],114:73,121:[2,199],129:[2,199],131:[2,199],132:[2,199],135:[1,82],136:[1,85],137:[2,199],138:[2,199],139:[2,199],140:[2,199]},{1:[2,200],6:[2,200],28:[2,200],29:[2,200],52:[2,200],57:[2,200],60:[2,200],75:[2,200],80:[2,200],89:[2,200],94:[2,200],96:[2,200],105:[2,200],106:91,107:[2,200],108:[2,200],109:[2,200],112:92,113:[2,200],114:73,121:[2,200],129:[2,200],131:[2,200],132:[2,200],135:[1,82],136:[2,200],137:[2,200],138:[2,200],139:[2,200],140:[2,200]},{1:[2,201],6:[2,201],28:[2,201],29:[2,201],52:[2,201],57:[2,201],60:[2,201],75:[2,201],80:[2,201],89:[2,201],94:[2,201],96:[2,201],105:[2,201],106:91,107:[2,201],108:[2,201],109:[2,201],112:92,113:[2,201],114:73,121:[2,201],129:[2,201],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[2,201],138:[2,201],139:[2,201],140:[2,201]},{1:[2,202],6:[2,202],28:[2,202],29:[2,202],52:[2,202],57:[2,202],60:[2,202],75:[2,202],80:[2,202],89:[2,202],94:[2,202],96:[2,202],105:[2,202],106:91,107:[2,202],108:[2,202],109:[2,202],112:92,113:[2,202],114:73,121:[2,202],129:[2,202],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[2,202],139:[2,202],140:[1,89]},{1:[2,203],6:[2,203],28:[2,203],29:[2,203],52:[2,203],57:[2,203],60:[2,203],75:[2,203],80:[2,203],89:[2,203],94:[2,203],96:[2,203],105:[2,203],106:91,107:[2,203],108:[2,203],109:[2,203],112:92,113:[2,203],114:73,121:[2,203],129:[2,203],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[2,203],140:[1,89]},{1:[2,204],6:[2,204],28:[2,204],29:[2,204],52:[2,204],57:[2,204],60:[2,204],75:[2,204],80:[2,204],89:[2,204],94:[2,204],96:[2,204],105:[2,204],106:91,107:[2,204],108:[2,204],109:[2,204],112:92,113:[2,204],114:73,121:[2,204],129:[2,204],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[2,204],139:[2,204],140:[2,204]},{1:[2,189],6:[2,189],28:[2,189],29:[2,189],52:[2,189],57:[2,189],60:[2,189],75:[2,189],80:[2,189],89:[2,189],94:[2,189],96:[2,189],105:[2,189],106:91,107:[1,69],108:[2,189],109:[1,70],112:92,113:[1,72],114:73,121:[2,189],129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,188],6:[2,188],28:[2,188],29:[2,188],52:[2,188],57:[2,188],60:[2,188],75:[2,188],80:[2,188],89:[2,188],94:[2,188],96:[2,188],105:[2,188],106:91,107:[1,69],108:[2,188],109:[1,70],112:92,113:[1,72],114:73,121:[2,188],129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,108],6:[2,108],28:[2,108],29:[2,108],52:[2,108],57:[2,108],60:[2,108],69:[2,108],70:[2,108],71:[2,108],73:[2,108],75:[2,108],76:[2,108],80:[2,108],87:[2,108],88:[2,108],89:[2,108],94:[2,108],96:[2,108],105:[2,108],107:[2,108],108:[2,108],109:[2,108],113:[2,108],121:[2,108],129:[2,108],131:[2,108],132:[2,108],135:[2,108],136:[2,108],137:[2,108],138:[2,108],139:[2,108],140:[2,108]},{1:[2,84],6:[2,84],28:[2,84],29:[2,84],43:[2,84],52:[2,84],57:[2,84],60:[2,84],69:[2,84],70:[2,84],71:[2,84],73:[2,84],75:[2,84],76:[2,84],80:[2,84],82:[2,84],87:[2,84],88:[2,84],89:[2,84],94:[2,84],96:[2,84],105:[2,84],107:[2,84],108:[2,84],109:[2,84],113:[2,84],121:[2,84],129:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84],138:[2,84],139:[2,84],140:[2,84],141:[2,84]},{1:[2,85],6:[2,85],28:[2,85],29:[2,85],43:[2,85],52:[2,85],57:[2,85],60:[2,85],69:[2,85],70:[2,85],71:[2,85],73:[2,85],75:[2,85],76:[2,85],80:[2,85],82:[2,85],87:[2,85],88:[2,85],89:[2,85],94:[2,85],96:[2,85],105:[2,85],107:[2,85],108:[2,85],109:[2,85],113:[2,85],121:[2,85],129:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85],138:[2,85],139:[2,85],140:[2,85],141:[2,85]},{1:[2,86],6:[2,86],28:[2,86],29:[2,86],43:[2,86],52:[2,86],57:[2,86],60:[2,86],69:[2,86],70:[2,86],71:[2,86],73:[2,86],75:[2,86],76:[2,86],80:[2,86],82:[2,86],87:[2,86],88:[2,86],89:[2,86],94:[2,86],96:[2,86],105:[2,86],107:[2,86],108:[2,86],109:[2,86],113:[2,86],121:[2,86],129:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86],138:[2,86],139:[2,86],140:[2,86],141:[2,86]},{1:[2,87],6:[2,87],28:[2,87],29:[2,87],43:[2,87],52:[2,87],57:[2,87],60:[2,87],69:[2,87],70:[2,87],71:[2,87],73:[2,87],75:[2,87],76:[2,87],80:[2,87],82:[2,87],87:[2,87],88:[2,87],89:[2,87],94:[2,87],96:[2,87],105:[2,87],107:[2,87],108:[2,87],109:[2,87],113:[2,87],121:[2,87],129:[2,87],131:[2,87],132:[2,87],133:[2,87],134:[2,87],135:[2,87],136:[2,87],137:[2,87],138:[2,87],139:[2,87],140:[2,87],141:[2,87]},{75:[1,246]},{60:[1,200],75:[2,92],95:247,96:[1,199],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{75:[2,93]},{8:248,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,75:[2,128],78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{12:[2,122],14:[2,122],31:[2,122],33:[2,122],34:[2,122],36:[2,122],37:[2,122],38:[2,122],39:[2,122],40:[2,122],41:[2,122],48:[2,122],49:[2,122],50:[2,122],54:[2,122],55:[2,122],75:[2,122],78:[2,122],81:[2,122],85:[2,122],86:[2,122],91:[2,122],92:[2,122],93:[2,122],99:[2,122],103:[2,122],104:[2,122],107:[2,122],109:[2,122],111:[2,122],113:[2,122],122:[2,122],128:[2,122],130:[2,122],131:[2,122],132:[2,122],133:[2,122],134:[2,122]},{12:[2,123],14:[2,123],31:[2,123],33:[2,123],34:[2,123],36:[2,123],37:[2,123],38:[2,123],39:[2,123],40:[2,123],41:[2,123],48:[2,123],49:[2,123],50:[2,123],54:[2,123],55:[2,123],75:[2,123],78:[2,123],81:[2,123],85:[2,123],86:[2,123],91:[2,123],92:[2,123],93:[2,123],99:[2,123],103:[2,123],104:[2,123],107:[2,123],109:[2,123],111:[2,123],113:[2,123],122:[2,123],128:[2,123],130:[2,123],131:[2,123],132:[2,123],133:[2,123],134:[2,123]},{1:[2,91],6:[2,91],28:[2,91],29:[2,91],43:[2,91],52:[2,91],57:[2,91],60:[2,91],69:[2,91],70:[2,91],71:[2,91],73:[2,91],75:[2,91],76:[2,91],80:[2,91],82:[2,91],87:[2,91],88:[2,91],89:[2,91],94:[2,91],96:[2,91],105:[2,91],107:[2,91],108:[2,91],109:[2,91],113:[2,91],121:[2,91],129:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91],135:[2,91],136:[2,91],137:[2,91],138:[2,91],139:[2,91],140:[2,91],141:[2,91]},{1:[2,109],6:[2,109],28:[2,109],29:[2,109],52:[2,109],57:[2,109],60:[2,109],69:[2,109],70:[2,109],71:[2,109],73:[2,109],75:[2,109],76:[2,109],80:[2,109],87:[2,109],88:[2,109],89:[2,109],94:[2,109],96:[2,109],105:[2,109],107:[2,109],108:[2,109],109:[2,109],113:[2,109],121:[2,109],129:[2,109],131:[2,109],132:[2,109],135:[2,109],136:[2,109],137:[2,109],138:[2,109],139:[2,109],140:[2,109]},{1:[2,40],6:[2,40],28:[2,40],29:[2,40],52:[2,40],57:[2,40],60:[2,40],75:[2,40],80:[2,40],89:[2,40],94:[2,40],96:[2,40],105:[2,40],106:91,107:[2,40],108:[2,40],109:[2,40],112:92,113:[2,40],114:73,121:[2,40],129:[2,40],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{8:249,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:250,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,115],6:[2,115],28:[2,115],29:[2,115],43:[2,115],52:[2,115],57:[2,115],60:[2,115],69:[2,115],70:[2,115],71:[2,115],73:[2,115],75:[2,115],76:[2,115],80:[2,115],82:[2,115],87:[2,115],88:[2,115],89:[2,115],94:[2,115],96:[2,115],105:[2,115],107:[2,115],108:[2,115],109:[2,115],113:[2,115],121:[2,115],129:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115],137:[2,115],138:[2,115],139:[2,115],140:[2,115],141:[2,115]},{6:[2,57],28:[2,57],56:251,57:[1,234],89:[2,57]},{6:[2,134],28:[2,134],29:[2,134],57:[2,134],60:[1,252],89:[2,134],94:[2,134],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{53:253,54:[1,64],55:[1,65]},{6:[2,58],28:[2,58],29:[2,58],30:113,31:[1,77],47:114,58:254,59:112,61:115,62:116,78:[1,74],92:[1,117],93:[1,118]},{6:[1,255],28:[1,256]},{6:[2,65],28:[2,65],29:[2,65],52:[2,65],57:[2,65]},{8:257,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,205],6:[2,205],28:[2,205],29:[2,205],52:[2,205],57:[2,205],60:[2,205],75:[2,205],80:[2,205],89:[2,205],94:[2,205],96:[2,205],105:[2,205],106:91,107:[2,205],108:[2,205],109:[2,205],112:92,113:[2,205],114:73,121:[2,205],129:[2,205],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{8:258,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,207],6:[2,207],28:[2,207],29:[2,207],52:[2,207],57:[2,207],60:[2,207],75:[2,207],80:[2,207],89:[2,207],94:[2,207],96:[2,207],105:[2,207],106:91,107:[2,207],108:[2,207],109:[2,207],112:92,113:[2,207],114:73,121:[2,207],129:[2,207],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,187],6:[2,187],28:[2,187],29:[2,187],52:[2,187],57:[2,187],60:[2,187],75:[2,187],80:[2,187],89:[2,187],94:[2,187],96:[2,187],105:[2,187],107:[2,187],108:[2,187],109:[2,187],113:[2,187],121:[2,187],129:[2,187],131:[2,187],132:[2,187],135:[2,187],136:[2,187],137:[2,187],138:[2,187],139:[2,187],140:[2,187]},{8:259,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,139],6:[2,139],28:[2,139],29:[2,139],52:[2,139],57:[2,139],60:[2,139],75:[2,139],80:[2,139],89:[2,139],94:[2,139],96:[2,139],101:[1,260],105:[2,139],107:[2,139],108:[2,139],109:[2,139],113:[2,139],121:[2,139],129:[2,139],131:[2,139],132:[2,139],135:[2,139],136:[2,139],137:[2,139],138:[2,139],139:[2,139],140:[2,139]},{5:261,28:[1,5]},{30:262,31:[1,77]},{123:263,125:224,126:[1,225]},{29:[1,264],124:[1,265],125:266,126:[1,225]},{29:[2,180],124:[2,180],126:[2,180]},{8:268,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],98:267,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,102],5:269,6:[2,102],28:[1,5],29:[2,102],52:[2,102],57:[2,102],60:[2,102],75:[2,102],80:[2,102],89:[2,102],94:[2,102],96:[2,102],105:[2,102],106:91,107:[1,69],108:[2,102],109:[1,70],112:92,113:[1,72],114:73,121:[2,102],129:[2,102],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,105],6:[2,105],28:[2,105],29:[2,105],52:[2,105],57:[2,105],60:[2,105],75:[2,105],80:[2,105],89:[2,105],94:[2,105],96:[2,105],105:[2,105],107:[2,105],108:[2,105],109:[2,105],113:[2,105],121:[2,105],129:[2,105],131:[2,105],132:[2,105],135:[2,105],136:[2,105],137:[2,105],138:[2,105],139:[2,105],140:[2,105]},{8:270,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,144],6:[2,144],28:[2,144],29:[2,144],52:[2,144],57:[2,144],60:[2,144],69:[2,144],70:[2,144],71:[2,144],73:[2,144],75:[2,144],76:[2,144],80:[2,144],87:[2,144],88:[2,144],89:[2,144],94:[2,144],96:[2,144],105:[2,144],107:[2,144],108:[2,144],109:[2,144],113:[2,144],121:[2,144],129:[2,144],131:[2,144],132:[2,144],135:[2,144],136:[2,144],137:[2,144],138:[2,144],139:[2,144],140:[2,144]},{6:[1,78],29:[1,271]},{8:272,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,71],12:[2,123],14:[2,123],28:[2,71],31:[2,123],33:[2,123],34:[2,123],36:[2,123],37:[2,123],38:[2,123],39:[2,123],40:[2,123],41:[2,123],48:[2,123],49:[2,123],50:[2,123],54:[2,123],55:[2,123],57:[2,71],78:[2,123],81:[2,123],85:[2,123],86:[2,123],91:[2,123],92:[2,123],93:[2,123],94:[2,71],99:[2,123],103:[2,123],104:[2,123],107:[2,123],109:[2,123],111:[2,123],113:[2,123],122:[2,123],128:[2,123],130:[2,123],131:[2,123],132:[2,123],133:[2,123],134:[2,123]},{6:[1,274],28:[1,275],94:[1,273]},{6:[2,58],8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[2,58],29:[2,58],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],89:[2,58],91:[1,62],92:[1,63],93:[1,61],94:[2,58],97:276,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,57],28:[2,57],29:[2,57],56:277,57:[1,234]},{1:[2,184],6:[2,184],28:[2,184],29:[2,184],52:[2,184],57:[2,184],60:[2,184],75:[2,184],80:[2,184],89:[2,184],94:[2,184],96:[2,184],105:[2,184],107:[2,184],108:[2,184],109:[2,184],113:[2,184],121:[2,184],124:[2,184],129:[2,184],131:[2,184],132:[2,184],135:[2,184],136:[2,184],137:[2,184],138:[2,184],139:[2,184],140:[2,184]},{8:278,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:279,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{119:[2,162],120:[2,162]},{30:165,31:[1,77],47:166,61:167,62:168,78:[1,74],92:[1,117],93:[1,118],118:280},{1:[2,169],6:[2,169],28:[2,169],29:[2,169],52:[2,169],57:[2,169],60:[2,169],75:[2,169],80:[2,169],89:[2,169],94:[2,169],96:[2,169],105:[2,169],106:91,107:[2,169],108:[1,281],109:[2,169],112:92,113:[2,169],114:73,121:[1,282],129:[2,169],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,170],6:[2,170],28:[2,170],29:[2,170],52:[2,170],57:[2,170],60:[2,170],75:[2,170],80:[2,170],89:[2,170],94:[2,170],96:[2,170],105:[2,170],106:91,107:[2,170],108:[1,283],109:[2,170],112:92,113:[2,170],114:73,121:[2,170],129:[2,170],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[1,285],28:[1,286],80:[1,284]},{6:[2,58],11:175,28:[2,58],29:[2,58],30:176,31:[1,77],32:177,33:[1,75],34:[1,76],44:287,45:174,47:178,49:[1,50],80:[2,58],92:[1,117]},{8:288,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,289],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,90],6:[2,90],28:[2,90],29:[2,90],43:[2,90],52:[2,90],57:[2,90],60:[2,90],69:[2,90],70:[2,90],71:[2,90],73:[2,90],75:[2,90],76:[2,90],80:[2,90],82:[2,90],87:[2,90],88:[2,90],89:[2,90],94:[2,90],96:[2,90],105:[2,90],107:[2,90],108:[2,90],109:[2,90],113:[2,90],121:[2,90],129:[2,90],131:[2,90],132:[2,90],133:[2,90],134:[2,90],135:[2,90],136:[2,90],137:[2,90],138:[2,90],139:[2,90],140:[2,90],141:[2,90]},{8:290,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,75:[2,126],78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{75:[2,127],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,41],6:[2,41],28:[2,41],29:[2,41],52:[2,41],57:[2,41],60:[2,41],75:[2,41],80:[2,41],89:[2,41],94:[2,41],96:[2,41],105:[2,41],106:91,107:[2,41],108:[2,41],109:[2,41],112:92,113:[2,41],114:73,121:[2,41],129:[2,41],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{29:[1,291],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[1,274],28:[1,275],89:[1,292]},{6:[2,71],28:[2,71],29:[2,71],57:[2,71],89:[2,71],94:[2,71]},{5:293,28:[1,5]},{6:[2,61],28:[2,61],29:[2,61],52:[2,61],57:[2,61]},{30:113,31:[1,77],47:114,58:294,59:112,61:115,62:116,78:[1,74],92:[1,117],93:[1,118]},{6:[2,59],28:[2,59],29:[2,59],30:113,31:[1,77],47:114,51:295,57:[2,59],58:111,59:112,61:115,62:116,78:[1,74],92:[1,117],93:[1,118]},{6:[2,66],28:[2,66],29:[2,66],52:[2,66],57:[2,66],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{29:[1,296],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{5:297,28:[1,5],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{5:298,28:[1,5]},{1:[2,140],6:[2,140],28:[2,140],29:[2,140],52:[2,140],57:[2,140],60:[2,140],75:[2,140],80:[2,140],89:[2,140],94:[2,140],96:[2,140],105:[2,140],107:[2,140],108:[2,140],109:[2,140],113:[2,140],121:[2,140],129:[2,140],131:[2,140],132:[2,140],135:[2,140],136:[2,140],137:[2,140],138:[2,140],139:[2,140],140:[2,140]},{5:299,28:[1,5]},{29:[1,300],124:[1,301],125:266,126:[1,225]},{1:[2,178],6:[2,178],28:[2,178],29:[2,178],52:[2,178],57:[2,178],60:[2,178],75:[2,178],80:[2,178],89:[2,178],94:[2,178],96:[2,178],105:[2,178],107:[2,178],108:[2,178],109:[2,178],113:[2,178],121:[2,178],129:[2,178],131:[2,178],132:[2,178],135:[2,178],136:[2,178],137:[2,178],138:[2,178],139:[2,178],140:[2,178]},{5:302,28:[1,5]},{29:[2,181],124:[2,181],126:[2,181]},{5:303,28:[1,5],57:[1,304]},{28:[2,136],57:[2,136],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,103],6:[2,103],28:[2,103],29:[2,103],52:[2,103],57:[2,103],60:[2,103],75:[2,103],80:[2,103],89:[2,103],94:[2,103],96:[2,103],105:[2,103],107:[2,103],108:[2,103],109:[2,103],113:[2,103],121:[2,103],129:[2,103],131:[2,103],132:[2,103],135:[2,103],136:[2,103],137:[2,103],138:[2,103],139:[2,103],140:[2,103]},{1:[2,106],5:305,6:[2,106],28:[1,5],29:[2,106],52:[2,106],57:[2,106],60:[2,106],75:[2,106],80:[2,106],89:[2,106],94:[2,106],96:[2,106],105:[2,106],106:91,107:[1,69],108:[2,106],109:[1,70],112:92,113:[1,72],114:73,121:[2,106],129:[2,106],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{105:[1,306]},{94:[1,307],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,121],6:[2,121],28:[2,121],29:[2,121],43:[2,121],52:[2,121],57:[2,121],60:[2,121],69:[2,121],70:[2,121],71:[2,121],73:[2,121],75:[2,121],76:[2,121],80:[2,121],87:[2,121],88:[2,121],89:[2,121],94:[2,121],96:[2,121],105:[2,121],107:[2,121],108:[2,121],109:[2,121],113:[2,121],119:[2,121],120:[2,121],121:[2,121],129:[2,121],131:[2,121],132:[2,121],135:[2,121],136:[2,121],137:[2,121],138:[2,121],139:[2,121],140:[2,121]},{8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],97:308,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:208,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,28:[1,153],30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,63:154,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],90:309,91:[1,62],92:[1,63],93:[1,61],97:152,99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[2,130],28:[2,130],29:[2,130],57:[2,130],89:[2,130],94:[2,130]},{6:[1,274],28:[1,275],29:[1,310]},{1:[2,147],6:[2,147],28:[2,147],29:[2,147],52:[2,147],57:[2,147],60:[2,147],75:[2,147],80:[2,147],89:[2,147],94:[2,147],96:[2,147],105:[2,147],106:91,107:[1,69],108:[2,147],109:[1,70],112:92,113:[1,72],114:73,121:[2,147],129:[2,147],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,149],6:[2,149],28:[2,149],29:[2,149],52:[2,149],57:[2,149],60:[2,149],75:[2,149],80:[2,149],89:[2,149],94:[2,149],96:[2,149],105:[2,149],106:91,107:[1,69],108:[2,149],109:[1,70],112:92,113:[1,72],114:73,121:[2,149],129:[2,149],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{119:[2,168],120:[2,168]},{8:311,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:312,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:313,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,94],6:[2,94],28:[2,94],29:[2,94],43:[2,94],52:[2,94],57:[2,94],60:[2,94],69:[2,94],70:[2,94],71:[2,94],73:[2,94],75:[2,94],76:[2,94],80:[2,94],87:[2,94],88:[2,94],89:[2,94],94:[2,94],96:[2,94],105:[2,94],107:[2,94],108:[2,94],109:[2,94],113:[2,94],119:[2,94],120:[2,94],121:[2,94],129:[2,94],131:[2,94],132:[2,94],135:[2,94],136:[2,94],137:[2,94],138:[2,94],139:[2,94],140:[2,94]},{11:175,30:176,31:[1,77],32:177,33:[1,75],34:[1,76],44:314,45:174,47:178,49:[1,50],92:[1,117]},{6:[2,95],11:175,28:[2,95],29:[2,95],30:176,31:[1,77],32:177,33:[1,75],34:[1,76],44:173,45:174,47:178,49:[1,50],57:[2,95],79:315,92:[1,117]},{6:[2,97],28:[2,97],29:[2,97],57:[2,97],80:[2,97]},{6:[2,44],28:[2,44],29:[2,44],57:[2,44],80:[2,44],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{8:316,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{75:[2,125],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,42],6:[2,42],28:[2,42],29:[2,42],52:[2,42],57:[2,42],60:[2,42],75:[2,42],80:[2,42],89:[2,42],94:[2,42],96:[2,42],105:[2,42],107:[2,42],108:[2,42],109:[2,42],113:[2,42],121:[2,42],129:[2,42],131:[2,42],132:[2,42],135:[2,42],136:[2,42],137:[2,42],138:[2,42],139:[2,42],140:[2,42]},{1:[2,116],6:[2,116],28:[2,116],29:[2,116],43:[2,116],52:[2,116],57:[2,116],60:[2,116],69:[2,116],70:[2,116],71:[2,116],73:[2,116],75:[2,116],76:[2,116],80:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],94:[2,116],96:[2,116],105:[2,116],107:[2,116],108:[2,116],109:[2,116],113:[2,116],121:[2,116],129:[2,116],131:[2,116],132:[2,116],133:[2,116],134:[2,116],135:[2,116],136:[2,116],137:[2,116],138:[2,116],139:[2,116],140:[2,116],141:[2,116]},{1:[2,53],6:[2,53],28:[2,53],29:[2,53],52:[2,53],57:[2,53],60:[2,53],75:[2,53],80:[2,53],89:[2,53],94:[2,53],96:[2,53],105:[2,53],107:[2,53],108:[2,53],109:[2,53],113:[2,53],121:[2,53],129:[2,53],131:[2,53],132:[2,53],135:[2,53],136:[2,53],137:[2,53],138:[2,53],139:[2,53],140:[2,53]},{6:[2,62],28:[2,62],29:[2,62],52:[2,62],57:[2,62]},{6:[2,57],28:[2,57],29:[2,57],56:317,57:[1,210]},{1:[2,206],6:[2,206],28:[2,206],29:[2,206],52:[2,206],57:[2,206],60:[2,206],75:[2,206],80:[2,206],89:[2,206],94:[2,206],96:[2,206],105:[2,206],107:[2,206],108:[2,206],109:[2,206],113:[2,206],121:[2,206],129:[2,206],131:[2,206],132:[2,206],135:[2,206],136:[2,206],137:[2,206],138:[2,206],139:[2,206],140:[2,206]},{1:[2,185],6:[2,185],28:[2,185],29:[2,185],52:[2,185],57:[2,185],60:[2,185],75:[2,185],80:[2,185],89:[2,185],94:[2,185],96:[2,185],105:[2,185],107:[2,185],108:[2,185],109:[2,185],113:[2,185],121:[2,185],124:[2,185],129:[2,185],131:[2,185],132:[2,185],135:[2,185],136:[2,185],137:[2,185],138:[2,185],139:[2,185],140:[2,185]},{1:[2,141],6:[2,141],28:[2,141],29:[2,141],52:[2,141],57:[2,141],60:[2,141],75:[2,141],80:[2,141],89:[2,141],94:[2,141],96:[2,141],105:[2,141],107:[2,141],108:[2,141],109:[2,141],113:[2,141],121:[2,141],129:[2,141],131:[2,141],132:[2,141],135:[2,141],136:[2,141],137:[2,141],138:[2,141],139:[2,141],140:[2,141]},{1:[2,142],6:[2,142],28:[2,142],29:[2,142],52:[2,142],57:[2,142],60:[2,142],75:[2,142],80:[2,142],89:[2,142],94:[2,142],96:[2,142],101:[2,142],105:[2,142],107:[2,142],108:[2,142],109:[2,142],113:[2,142],121:[2,142],129:[2,142],131:[2,142],132:[2,142],135:[2,142],136:[2,142],137:[2,142],138:[2,142],139:[2,142],140:[2,142]},{1:[2,176],6:[2,176],28:[2,176],29:[2,176],52:[2,176],57:[2,176],60:[2,176],75:[2,176],80:[2,176],89:[2,176],94:[2,176],96:[2,176],105:[2,176],107:[2,176],108:[2,176],109:[2,176],113:[2,176],121:[2,176],129:[2,176],131:[2,176],132:[2,176],135:[2,176],136:[2,176],137:[2,176],138:[2,176],139:[2,176],140:[2,176]},{5:318,28:[1,5]},{29:[1,319]},{6:[1,320],29:[2,182],124:[2,182],126:[2,182]},{8:321,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{1:[2,107],6:[2,107],28:[2,107],29:[2,107],52:[2,107],57:[2,107],60:[2,107],75:[2,107],80:[2,107],89:[2,107],94:[2,107],96:[2,107],105:[2,107],107:[2,107],108:[2,107],109:[2,107],113:[2,107],121:[2,107],129:[2,107],131:[2,107],132:[2,107],135:[2,107],136:[2,107],137:[2,107],138:[2,107],139:[2,107],140:[2,107]},{1:[2,145],6:[2,145],28:[2,145],29:[2,145],52:[2,145],57:[2,145],60:[2,145],69:[2,145],70:[2,145],71:[2,145],73:[2,145],75:[2,145],76:[2,145],80:[2,145],87:[2,145],88:[2,145],89:[2,145],94:[2,145],96:[2,145],105:[2,145],107:[2,145],108:[2,145],109:[2,145],113:[2,145],121:[2,145],129:[2,145],131:[2,145],132:[2,145],135:[2,145],136:[2,145],137:[2,145],138:[2,145],139:[2,145],140:[2,145]},{1:[2,124],6:[2,124],28:[2,124],29:[2,124],52:[2,124],57:[2,124],60:[2,124],69:[2,124],70:[2,124],71:[2,124],73:[2,124],75:[2,124],76:[2,124],80:[2,124],87:[2,124],88:[2,124],89:[2,124],94:[2,124],96:[2,124],105:[2,124],107:[2,124],108:[2,124],109:[2,124],113:[2,124],121:[2,124],129:[2,124],131:[2,124],132:[2,124],135:[2,124],136:[2,124],137:[2,124],138:[2,124],139:[2,124],140:[2,124]},{6:[2,131],28:[2,131],29:[2,131],57:[2,131],89:[2,131],94:[2,131]},{6:[2,57],28:[2,57],29:[2,57],56:322,57:[1,234]},{6:[2,132],28:[2,132],29:[2,132],57:[2,132],89:[2,132],94:[2,132]},{1:[2,171],6:[2,171],28:[2,171],29:[2,171],52:[2,171],57:[2,171],60:[2,171],75:[2,171],80:[2,171],89:[2,171],94:[2,171],96:[2,171],105:[2,171],106:91,107:[2,171],108:[2,171],109:[2,171],112:92,113:[2,171],114:73,121:[1,323],129:[2,171],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,173],6:[2,173],28:[2,173],29:[2,173],52:[2,173],57:[2,173],60:[2,173],75:[2,173],80:[2,173],89:[2,173],94:[2,173],96:[2,173],105:[2,173],106:91,107:[2,173],108:[1,324],109:[2,173],112:92,113:[2,173],114:73,121:[2,173],129:[2,173],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,172],6:[2,172],28:[2,172],29:[2,172],52:[2,172],57:[2,172],60:[2,172],75:[2,172],80:[2,172],89:[2,172],94:[2,172],96:[2,172],105:[2,172],106:91,107:[2,172],108:[2,172],109:[2,172],112:92,113:[2,172],114:73,121:[2,172],129:[2,172],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[2,98],28:[2,98],29:[2,98],57:[2,98],80:[2,98]},{6:[2,57],28:[2,57],29:[2,57],56:325,57:[1,244]},{29:[1,326],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[1,255],28:[1,256],29:[1,327]},{29:[1,328]},{1:[2,179],6:[2,179],28:[2,179],29:[2,179],52:[2,179],57:[2,179],60:[2,179],75:[2,179],80:[2,179],89:[2,179],94:[2,179],96:[2,179],105:[2,179],107:[2,179],108:[2,179],109:[2,179],113:[2,179],121:[2,179],129:[2,179],131:[2,179],132:[2,179],135:[2,179],136:[2,179],137:[2,179],138:[2,179],139:[2,179],140:[2,179]},{29:[2,183],124:[2,183],126:[2,183]},{28:[2,137],57:[2,137],106:91,107:[1,69],109:[1,70],112:92,113:[1,72],114:73,129:[1,90],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[1,274],28:[1,275],29:[1,329]},{8:330,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{8:331,9:121,10:22,11:23,12:[1,24],13:21,14:[1,48],15:8,16:9,17:10,18:11,19:12,20:13,21:14,22:15,23:16,24:17,25:18,26:19,27:20,30:66,31:[1,77],32:53,33:[1,75],34:[1,76],35:26,36:[1,54],37:[1,55],38:[1,56],39:[1,57],40:[1,58],41:[1,59],42:25,47:67,48:[1,49],49:[1,50],50:[1,31],53:32,54:[1,64],55:[1,65],61:51,62:52,64:38,66:27,67:28,68:29,78:[1,74],81:[1,45],85:[1,30],86:[1,47],91:[1,62],92:[1,63],93:[1,61],99:[1,40],103:[1,46],104:[1,60],106:41,107:[1,69],109:[1,70],110:42,111:[1,71],112:43,113:[1,72],114:73,122:[1,44],127:39,128:[1,68],130:[1,33],131:[1,34],132:[1,35],133:[1,36],134:[1,37]},{6:[1,285],28:[1,286],29:[1,332]},{6:[2,45],28:[2,45],29:[2,45],57:[2,45],80:[2,45]},{6:[2,63],28:[2,63],29:[2,63],52:[2,63],57:[2,63]},{1:[2,177],6:[2,177],28:[2,177],29:[2,177],52:[2,177],57:[2,177],60:[2,177],75:[2,177],80:[2,177],89:[2,177],94:[2,177],96:[2,177],105:[2,177],107:[2,177],108:[2,177],109:[2,177],113:[2,177],121:[2,177],129:[2,177],131:[2,177],132:[2,177],135:[2,177],136:[2,177],137:[2,177],138:[2,177],139:[2,177],140:[2,177]},{6:[2,133],28:[2,133],29:[2,133],57:[2,133],89:[2,133],94:[2,133]},{1:[2,174],6:[2,174],28:[2,174],29:[2,174],52:[2,174],57:[2,174],60:[2,174],75:[2,174],80:[2,174],89:[2,174],94:[2,174],96:[2,174],105:[2,174],106:91,107:[2,174],108:[2,174],109:[2,174],112:92,113:[2,174],114:73,121:[2,174],129:[2,174],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{1:[2,175],6:[2,175],28:[2,175],29:[2,175],52:[2,175],57:[2,175],60:[2,175],75:[2,175],80:[2,175],89:[2,175],94:[2,175],96:[2,175],105:[2,175],106:91,107:[2,175],108:[2,175],109:[2,175],112:92,113:[2,175],114:73,121:[2,175],129:[2,175],131:[1,84],132:[1,83],135:[1,82],136:[1,85],137:[1,86],138:[1,87],139:[1,88],140:[1,89]},{6:[2,99],28:[2,99],29:[2,99],57:[2,99],80:[2,99]}],defaultActions:{64:[2,55],65:[2,56],79:[2,3],98:[2,114],197:[2,93]},parseError:function(t,n){throw new Error(t)},parse:function(t){function d(e){r.length=r.length-2*e,i.length=i.length-e,s.length=s.length-e}function v(){var e;return e=n.lexer.lex()||1,typeof e!="number"&&(e=n.symbols_[e]||e),e}var n=this,r=[0],i=[null],s=[],o=this.table,u="",a=0,f=0,l=0,c=2,h=1;this.lexer.setInput(t),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var p=this.lexer.yylloc;s.push(p),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var m,g,y,b,w,E,S={},x,T,N,C;for(;;){y=r[r.length-1],this.defaultActions[y]?b=this.defaultActions[y]:(m==null&&(m=v()),b=o[y]&&o[y][m]);if(typeof b=="undefined"||!b.length||!b[0]){if(!l){C=[];for(x in o[y])this.terminals_[x]&&x>2&&C.push("'"+this.terminals_[x]+"'");var k="";this.lexer.showPosition?k="Parse error on line "+(a+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+C.join(", ")+", got '"+this.terminals_[m]+"'":k="Parse error on line "+(a+1)+": Unexpected "+(m==1?"end of input":"'"+(this.terminals_[m]||m)+"'"),this.parseError(k,{text:this.lexer.match,token:this.terminals_[m]||m,line:this.lexer.yylineno,loc:p,expected:C})}if(l==3){if(m==h)throw new Error(k||"Parsing halted.");f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,m=v()}for(;;){if(c.toString()in o[y])break;if(y==0)throw new Error(k||"Parsing halted.");d(1),y=r[r.length-1]}g=m,m=c,y=r[r.length-1],b=o[y]&&o[y][c],l=3}if(b[0]instanceof Array&&b.length>1)throw new Error("Parse Error: multiple actions possible at state: "+y+", token: "+m);switch(b[0]){case 1:r.push(m),i.push(this.lexer.yytext),s.push(this.lexer.yylloc),r.push(b[1]),m=null,g?(m=g,g=null):(f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,l>0&&l--);break;case 2:T=this.productions_[b[1]][1],S.$=i[i.length-T],S._$={first_line:s[s.length-(T||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(T||1)].first_column,last_column:s[s.length-1].last_column},E=this.performAction.call(S,u,f,a,this.yy,b[1],i,s);if(typeof E!="undefined")return E;T&&(r=r.slice(0,-1*T*2),i=i.slice(0,-1*T),s=s.slice(0,-1*T)),r.push(this.productions_[b[1]][0]),i.push(S.$),s.push(S._$),N=o[r[r.length-2]][r[r.length-1]],r.push(N);break;case 3:return!0}}return!0}};return undefined,e}();typeof require!="undefined"&&typeof e!="undefined"&&(e.parser=t,e.parse=function(){return t.parse.apply(t,arguments)},e.main=function(n){if(!n[1])throw new Error("Usage: "+n[0]+" FILE");if(typeof process!="undefined")var r=require("fs").readFileSync(require("path").join(process.cwd(),n[1]),"utf8");else var i=require("file").path(require("file").cwd()),r=i.join(n[1]).read({charset:"utf-8"});return e.parser.parse(r)},typeof module!="undefined"&&require.main===module&&e.main(typeof process!="undefined"?process.argv.slice(1):require("system").args))},require["./iced"]=new function(){var e=this;(function(){var t,n=[].slice;e.generator=t=function(e,t,r){var i,s,o,u,a,f;return t.transform=function(e){return e.icedTransform()},t["const"]=i={k:"__iced_k",k_noop:"__iced_k_noop",param:"__iced_p_",ns:"iced",Deferrals:"Deferrals",deferrals:"__iced_deferrals",fulfill:"_fulfill",b_while:"_break",t_while:"_while",c_while:"_continue",n_while:"_next",n_arg:"__iced_next_arg",defer_method:"defer",slot:"__slot",assign_fn:"assign_fn",autocb:"autocb",retslot:"ret",trace:"__iced_trace",passed_deferral:"__iced_passed_deferral",findDeferral:"findDeferral",lineno:"lineno",parent:"parent",filename:"filename",funcname:"funcname",catchExceptions:"catchExceptions",runtime_modes:["node","inline","window","none"]},e.makeDeferReturn=function(t,r,s,o,u){var a,f,l,c;l={};for(a in o)c=o[a],l[a]=c;return l[i.lineno]=r!=null?r[i.lineno]:void 0,f=function(){var i,o,a;return i=1<=arguments.length?n.call(arguments,0):[],r!=null&&(a=r.assign_fn)!=null&&a.apply(null,i),t?(o=t,u||(t=null),o._fulfill(s,l)):e._warn("overused deferral at "+e._trace_to_string(l))},f[i.trace]=l,f},e.__c=0,e.tickCounter=function(t){return e.__c++,e.__c%t===0?(e.__c=0,!0):!1},e.__active_trace=null,e._trace_to_string=function(e){var t;return t=e[i.funcname]||"",""+t+" ("+e[i.filename]+":"+(e[i.lineno]+1)+")"},e._warn=function(e){return typeof console!="undefined"&&console!==null?console.log("ICED warning: "+e):void 0},r.Deferrals=s=function(){function t(e,t){this.trace=t,this.continuation=e,this.count=1,this.ret=null}return t.prototype._call=function(t){var n;return this.continuation?(e.__active_trace=t,n=this.continuation,this.continuation=null,n(this.ret)):e._warn("Entered dead await at "+e._trace_to_string(t))},t.prototype._fulfill=function(t,n){var r=this;if(!(--this.count>0))return e.tickCounter(500)?typeof process!="undefined"&&process!==null?process.nextTick(function(){return r._call(n)}):setTimeout(function(){return r._call(n)},0):this._call(n)},t.prototype.defer=function(t){var n;return this.count++,n=this,e.makeDeferReturn(n,t,null,this.trace)},t}(),r.findDeferral=a=function(e){var t,n,r;for(n=0,r=e.length;n1?"_"+e+(t>1?t-1:""):"_"+(t+parseInt(e,36)).toString(36).replace(/\d/g,"a")},e.prototype.type=function(e){var t,n,r,i;i=this.variables;for(n=0,r=i.length;n1?t.__super__.compileCps.call(this,e):this.compileNode(e)},t.prototype.compile=function(e,n){return e==null&&(e={}),e.scope?t.__super__.compile.call(this,e,n):this.compileRoot(e)},t.prototype.compileNode=function(e){var n,r,i,s,o,u,a,f;this.tab=e.indent,o=e.level===_,i=[],f=this.expressions;for(u=0,a=f.length;u1&&e.level>=A?"("+r+")":r)},t.prototype.compileRoot=function(e){var t,n,r,i,s,o;return e.indent=e.bare?"":Y,e.scope=new $(null,this,null),e.level=_,this.spaced=!0,i="",e.bare||(s=function(){var e,t,i,s;i=this.expressions,s=[];for(r=e=0,t=i.length;e=k?"(void 0)":"void 0":this.value==="this"?((n=e.scope.method)!=null?n.bound:void 0)?e.scope.method.context:this.value:this.value.reserved?'"'+this.value+'"':this.icedLoopFlag&&this.icedIsJump()?this.compileIced(e):this.value,this.isStatement()?""+this.tab+t+";":t},t.prototype.toString=function(){return' "'+this.value+'"'},t}(s),e.Undefined=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return St(t,e),t.prototype.isAssignable=B,t.prototype.isComplex=B,t.prototype.compileNode=function(e){return e.level>=k?"(void 0)":"void 0"},t}(s),e.Null=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return St(t,e),t.prototype.isAssignable=B,t.prototype.isComplex=B,t.prototype.compileNode=function(){return"null"},t}(s),e.Bool=function(e){function t(e){this.val=e,t.__super__.constructor.call(this)}return St(t,e),t.prototype.isAssignable=B,t.prototype.isComplex=B,t.prototype.compileNode=function(){return this.val},t}(s),e.Return=W=function(e){function t(e,n){t.__super__.constructor.call(this),this.icedHasAutocbFlag=n,e&&!e.unwrap().isUndefined&&(this.expression=e)}return St(t,e),t.prototype.children=["expression"],t.prototype.isStatement=st,t.prototype.makeReturn=Z,t.prototype.jumps=Z,t.prototype.compile=function(e,n){var r,i;return r=(i=this.expression)!=null?i.makeReturn():void 0,!r||r instanceof t?t.__super__.compile.call(this,e,n):r.compile(e,n)},t.prototype.compileNode=function(e){var t,n,r,i,s;return this.icedHasAutocbFlag?(i=new rt(new D(ct["const"].autocb)),t=this.expression?[this.expression]:[],r=new u(i,t),s=new D("return"),n=new o([r,s]),n.compile(e)):this.tab+("return"+[this.expression?" "+this.expression.compile(e,M):void 0]+";")},t}(s),e.Value=rt=function(e){function t(e,n,r){return t.__super__.constructor.call(this),!n&&e instanceof t?e:(this.base=e,this.properties=n||[],r&&(this[r]=!0),this)}return St(t,e),t.prototype.children=["base","properties"],t.prototype.copy=function(){return new t(this.base,this.properties)},t.prototype.add=function(e){return this.properties=this.properties.concat(e),this},t.prototype.hasProperties=function(){return!!this.properties.length},t.prototype.isArray=function(){return!this.properties.length&&this.base instanceof n},t.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},t.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},t.prototype.isSimpleNumber=function(){return this.base instanceof D&&X.test(this.base.value)},t.prototype.isString=function(){return this.base instanceof D&&b.test(this.base.value)},t.prototype.isAtomic=function(){var e,t,n,r;r=this.properties.concat(this.base);for(t=0,n=r.length;t"+this.equals],a=p[0],i=p[1],n=this.stepNum?+this.stepNum>0?""+a+" "+this.toVar:""+i+" "+this.toVar:u?(d=[+this.fromNum,+this.toNum],r=d[0],c=d[1],d,r<=c?""+a+" "+c:""+i+" "+c):(t=""+this.fromVar+" <= "+this.toVar,""+t+" ? "+a+" "+this.toVar+" : "+i+" "+this.toVar),l=this.stepVar?""+s+" += "+this.stepVar:u?f?r<=c?"++"+s:"--"+s:r<=c?""+s+"++":""+s+"--":f?""+t+" ? ++"+s+" : --"+s:""+t+" ? "+s+"++ : "+s+"--",f&&(h=""+o+" = "+h),f&&(l=""+o+" = "+l),""+h+"; "+n+"; "+l):this.compileArray(e)},t.prototype.compileArray=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v;if(this.fromNum&&this.toNum&&Math.abs(this.fromNum-this.toNum)<=20)return f=function(){v=[];for(var e=p=+this.fromNum,t=+this.toNum;p<=t?e<=t:e>=t;p<=t?e++:e--)v.push(e);return v}.apply(this),this.exclusive&&f.pop(),"["+f.join(", ")+"]";o=this.tab+Y,s=e.scope.freeVariable("i"),l=e.scope.freeVariable("results"),a="\n"+o+l+" = [];",this.fromNum&&this.toNum?(e.index=s,n=this.compileNode(e)):(c=""+s+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),r=""+this.fromVar+" <= "+this.toVar,n="var "+c+"; "+r+" ? "+s+" <"+this.equals+" "+this.toVar+" : "+s+" >"+this.equals+" "+this.toVar+"; "+r+" ? "+s+"++ : "+s+"--"),u="{ "+l+".push("+s+"); }\n"+o+"return "+l+";\n"+e.indent,i=function(e){return e!=null?e.contains(function(e){return e instanceof D&&e.value==="arguments"&&!e.asKey}):void 0};if(i(this.from)||i(this.to))t=", arguments";return"(function() {"+a+"\n"+o+"for ("+n+")"+u+"}).apply(this"+(t!=null?t:"")+")"},t}(s),e.Slice=J=function(e){function t(e){this.range=e,t.__super__.constructor.call(this)}return St(t,e),t.prototype.children=["range"],t.prototype.compileNode=function(e){var t,n,r,i,s,o;return o=this.range,i=o.to,n=o.from,r=n&&n.compile(e,M)||"0",t=i&&i.compile(e,M),i&&(!!this.range.exclusive||+t!==-1)&&(s=", "+(this.range.exclusive?t:X.test(t)?""+(+t+1):(t=i.compile(e,k),"+"+t+" + 1 || 9e9"))),".slice("+r+(s||"")+")"},t}(s),e.Obj=F=function(e){function t(e,n){this.generated=n!=null?n:!1,t.__super__.constructor.call(this),this.objects=this.properties=e||[]}return St(t,e),t.prototype.children=["properties"],t.prototype.toSlot=function(e){var t,n,i,s,o;s=this.properties,o=[];for(n=0,i=s.length;n=0?"[\n"+e.indent+t+"\n"+this.tab+"]":"["+t+"]")):"[]"},t.prototype.assigns=function(e){var t,n,r,i;i=this.objects;for(n=0,r=i.length;n=0)throw SyntaxError("variable name may not be "+e);return e&&(e=g.test(e)&&e)},n.prototype.setContext=function(e){return this.body.traverseChildren(!1,function(t){if(t.classBody)return!1;if(t instanceof D&&t.value==="this")return t.value=e;if(t instanceof l){t.klass=e;if(t.bound)return t.context=e}})},n.prototype.addBoundFunctions=function(e){var n,r,i,s,o,u;if(this.boundFuncs.length){o=this.boundFuncs,u=[];for(i=0,s=o.length;i=0);if(s&&this.context!=="object")throw SyntaxError('variable name may not be "'+o+'"');this.icedlocal=i&&i.icedlocal}return St(n,e),n.prototype.children=["variable","value"],n.prototype.isStatement=function(e){return(e!=null?e.level:void 0)===_&&this.context!=null&&xt.call(this.context,"?")>=0},n.prototype.assigns=function(e){return this[this.context==="object"?"value":"variable"].assigns(e)},n.prototype.unfoldSoak=function(e){return gt(e,this,"variable")},n.prototype.icedCpsRotate=function(){var e;if(e=this.icedCpsExprRotate(this.value))return this.value=e},n.prototype.compileNode=function(e){var t,n,r,i,s,o,u,a,f;if(t=this.variable instanceof rt){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(e);if(this.variable.isSplice())return this.compileSplice(e);if((o=this.context)==="||="||o==="&&="||o==="?=")return this.compileConditional(e)}r=this.variable.compile(e,A);if(!this.context){if(!(s=this.variable.unwrapAll()).isAssignable())throw SyntaxError('"'+this.variable.compile(e)+'" cannot be assigned.');if(typeof s.hasProperties=="function"?!s.hasProperties():!void 0)this.param||this.icedlocal?e.scope.add(r,"var",this.icedlocal):e.scope.find(r)}return this.value instanceof l&&(n=P.exec(r))&&(n[1]&&(this.value.klass=n[1]),this.value.name=(u=(a=(f=n[2])!=null?f:n[3])!=null?a:n[4])!=null?u:n[5]),i=this.value.compile(e,A),this.context==="object"?""+r+": "+i:(i=r+(" "+(this.context||"=")+" ")+i,e.level<=A?i:"("+i+")")},n.prototype.compilePatternMatch=function(e){var r,i,s,o,u,a,f,l,c,h,p,d,v,m,y,b,w,E,S,x,T,C,k,L,M,P,H;y=e.level===_,w=this.value,h=this.variable.base.objects;if(!(p=h.length))return s=w.compile(e),e.level>=O?"("+s+")":s;a=this.variable.isObject();if(y&&p===1&&!((c=h[0])instanceof Q)){c instanceof n?(T=c,C=T.variable,u=C.base,c=T.value):c.base instanceof R?(k=(new rt(c.unwrapAll())).cacheReference(e),c=k[0],u=k[1]):u=a?c["this"]?c.properties[0].name:c:new D(0),r=g.test(u.unwrap().value||0),w=new rt(w),w.properties.push(new(r?t:N)(u));if(L=c.unwrap().value,xt.call(U,L)>=0)throw new SyntaxError("assignment to a reserved word: "+c.compile(e)+" = "+w.compile(e));return(new n(c,w,null,{param:this.param})).compile(e,_)}E=w.compile(e,A),i=[],m=!1;if(!g.test(E)||this.variable.assigns(E))i.push(""+(d=e.scope.freeVariable("ref"))+" = "+E),E=d;for(o=S=0,x=h.length;S=0)throw new SyntaxError("assignment to a reserved word: "+c.compile(e)+" = "+b.compile(e));i.push((new n(c,b,null,{param:this.param,subpattern:!0})).compile(e,A))}return!y&&!this.subpattern&&i.push(E),s=i.join(", "),e.level=0&&(e.isExistentialEquals=!0),(new I(this.context.slice(0,-1),t,new n(r,this.value,"="))).compile(e)},n.prototype.compileSplice=function(e){var t,n,r,i,s,o,u,a,f,l,c,h;return l=this.variable.properties.pop().range,r=l.from,u=l.to,n=l.exclusive,o=this.variable.compile(e),c=(r!=null?r.cache(e,O):void 0)||["0","0"],i=c[0],s=c[1],u?(r!=null?r.isSimpleNumber():void 0)&&u.isSimpleNumber()?(u=+u.compile(e)- +s,n||(u+=1)):(u=u.compile(e,k)+" - "+s,n||(u+=" + 1")):u="9e9",h=this.value.cache(e,A),a=h[0],f=h[1],t="[].splice.apply("+o+", ["+i+", "+u+"].concat("+a+")), "+f,e.level>_?"("+t+")":t},n}(s),e.Code=l=function(e){function i(e,t,n){i.__super__.constructor.call(this),this.params=e||[],this.body=t||new o,this.icedgen=n==="icedgen",this.bound=n==="boundfunc"||this.icedgen;if(this.bound||this.icedgen)this.context="_this";this.icedPassedDeferral=null}return St(i,e),i.prototype.children=["params","body"],i.prototype.isStatement=function(){return!!this.ctor},i.prototype.traceName=function(){var e;return e=[],this.klass&&e.push(this.klass),this.name&&e.push(this.name),e.join(".")},i.prototype.jumps=B,i.prototype.compileNode=function(e){var i,s,o,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,T,N,C,L,A,O,M,_,P,H,B,j,F,q,R,U,z,W,X;e.scope=new $(e.scope,this.body,this),e.scope.shared=ut(e,"sharedScope")||this.icedgen,e.scope.icedgen=this.icedgen,e.indent+=Y,delete e.bare,delete e.isExistentialEquals,v=[],s=[],F=this.paramNames();for(T=0,A=F.length;T=k?"("+i+")":i},i.prototype.paramNames=function(){var e,t,n,r,i;e=[],i=this.params;for(n=0,r=i.length;n=0)throw SyntaxError('parameter name "'+e+'" is not allowed')}return St(t,e),t.prototype.children=["name","value"],t.prototype.compile=function(e){return this.name.compile(e,A)},t.prototype.asReference=function(e){var t;return this.reference?this.reference:(t=this.name,t["this"]?(t=t.properties[0].name,t.value.reserved&&(t=new D(e.scope.freeVariable(t.value)))):t.isComplex()&&(t=new D(e.scope.freeVariable("arg"))),t=new rt(t),this.splat&&(t=new Q(t)),this.reference=t)},t.prototype.isComplex=function(){return this.name.isComplex()},t.prototype.names=function(e){var t,n,i,s,o,u;e==null&&(e=this.name),t=function(e){var t;return t=e.properties[0].name.value,t.reserved?[]:[t]};if(e instanceof D)return[e.value];if(e instanceof rt)return t(e);n=[],u=e.objects;for(s=0,o=u.length;s=n.length)return"";if(n.length===1)return o=n[0].compile(e,A),r?o:""+yt("slice")+".call("+o+")";i=n.slice(a);for(u=l=0,c=i.length;l1?t.expressions.unshift(new x((new R(this.guard)).invert(),new D("continue"))):this.guard&&(t=o.wrap([new x(this.guard,t)]))),t="\n"+t.compile(e,_)+"\n"+this.tab),n=i+this.tab+("while ("+this.condition.compile(e,M)+") {"+t+"}"),this.returns&&(this.icedHasAutocbFlag?(n+="\n"+this.tab+ct["const"].autocb+"("+r+");",n+="\n"+this.tab+"return;"):n+="\n"+this.tab+"return "+r+";"),n)},i}(s),e.Op=I=function(e){function i(e,n,r,s){i.__super__.constructor.call(this);if(e==="in")return new T(n,r);if(e==="do")return this.generateDo(n);if(e==="new"){if(n instanceof u&&!n["do"]&&!n.isNew)return n.newInstance();if(n instanceof l&&n.bound||n["do"])n=new R(n)}return this.operator=t[e]||e,this.first=n,this.second=r,this.flip=!!s,this}var t,n;return St(i,e),i.prototype.icedWrapContinuation=function(){return this.icedCallContinuationFlag},t={"==":"===","!=":"!==",of:"in"},n={"!==":"===","===":"!=="},i.prototype.children=["first","second"],i.prototype.isSimpleNumber=B,i.prototype.isUnary=function(){return!this.second},i.prototype.isComplex=function(){var e;return!this.isUnary()||(e=this.operator)!=="+"&&e!=="-"||this.first.isComplex()},i.prototype.isChainable=function(){var e;return(e=this.operator)==="<"||e===">"||e===">="||e==="<="||e==="==="||e==="!=="},i.prototype.icedCpsRotate=function(){var e,t;this.first&&(e=this.icedCpsExprRotate(this.first))&&(this.first=e);if(this.second&&(t=this.icedCpsExprRotate(this.second)))return this.second=t},i.prototype.invert=function(){var e,t,r,s,o;if(this.isChainable()&&this.first.isChainable()){e=!0,t=this;while(t&&t.operator)e&&(e=t.operator in n),t=t.first;if(!e)return(new R(this)).invert();t=this;while(t&&t.operator)t.invert=!t.invert,t.operator=n[t.operator],t=t.first;return this}return(s=n[this.operator])?(this.operator=s,this.first.unwrap()instanceof i&&this.first.invert(),this):this.second?(new R(this)).invert():this.operator==="!"&&(r=this.first.unwrap())instanceof i&&((o=r.operator)==="!"||o==="in"||o==="instanceof")?r:new i("!",this)},i.prototype.unfoldSoak=function(e){var t;return((t=this.operator)==="++"||t==="--"||t==="delete")&>(e,this,"first")},i.prototype.generateDo=function(e){var t,n,i,s,o,a,f,c;s=[],n=e instanceof r&&(o=e.value.unwrap())instanceof l?o:e,c=n.params||[];for(a=0,f=c.length;a=0))throw SyntaxError("prefix increment/decrement may not have eval or arguments operand");return this.isUnary()?this.compileUnary(e):n?this.compileChain(e):this.operator==="?"?this.compileExistence(e):(t=this.first.compile(e,O)+" "+this.operator+" "+this.second.compile(e,O),e.level<=O?t:"("+t+")")},i.prototype.compileChain=function(e){var t,n,r,i;return i=this.first.second.cache(e),this.first.second=i[0],r=i[1],n=this.first.compile(e,O),t=""+n+" "+(this.invert?"&&":"||")+" "+r.compile(e)+" "+this.operator+" "+this.second.compile(e,O),"("+t+")"},i.prototype.compileExistence=function(e){var t,n;return this.first.isComplex()?(n=new D(e.scope.freeVariable("ref")),t=new R(new r(n,this.first))):(t=this.first,n=t),(new x(new d(t),n,{type:"if"})).addElse(this.second).compile(e)},i.prototype.compileUnary=function(e){var t,n,r;if(e.level>=k)return(new R(this)).compile(e);n=[t=this.operator],r=t==="+"||t==="-",(t==="new"||t==="typeof"||t==="delete"||r&&this.first instanceof i&&this.first.operator===t)&&n.push(" ");if(r&&this.first instanceof i||t==="new"&&this.first.isStatement(e))this.first=new R(this.first);return n.push(this.first.compile(e,O)),this.flip&&n.reverse(),n.join("")},i.prototype.toString=function(e){return i.__super__.toString.call(this,e,this.constructor.name+" "+this.operator)},i}(s),e.In=T=function(e){function t(e,n){this.object=e,this.array=n,t.__super__.constructor.call(this)}return St(t,e),t.prototype.children=["object","array"],t.prototype.invert=H,t.prototype.compileNode=function(e){var t,n,r,i,s;if(this.array instanceof rt&&this.array.isArray()){s=this.array.base.objects;for(r=0,i=s.length;r= 0"),r===n?t:(t=r+", "+t,e.level=0)throw SyntaxError('catch variable may not be "'+this.error.value+'"');return e.scope.check(this.error.value)||e.scope.add(this.error.value,"param")," catch"+r+"{\n"+this.recovery.compile(e,_)+"\n"+this.tab+"}"}if(!this.ensure&&!this.recovery)return" catch (_error) {}"}.call(this),n=this.ensure?" finally {\n"+this.ensure.compile(e,_)+"\n"+this.tab+"}":"",""+this.tab+"try {\n"+i+"\n"+this.tab+"}"+(t||"")+n},t}(s),e.Throw=et=function(e){function t(e){this.expression=e,t.__super__.constructor.call(this)}return St(t,e),t.prototype.children=["expression"],t.prototype.isStatement=st,t.prototype.jumps=B,t.prototype.makeReturn=Z,t.prototype.compileNode=function(e){return this.tab+("throw "+this.expression.compile(e)+";")},t}(s),e.Existence=d=function(e){function t(e){this.expression=e,t.__super__.constructor.call(this)}return St(t,e),t.prototype.children=["expression"],t.prototype.invert=H,t.prototype.compileNode=function(e){var t,n,r,i;return this.expression.front=this.front,r=this.expression.compile(e,O),g.test(r)&&!e.scope.check(r)?(i=this.negated?["===","||"]:["!==","&&"],t=i[0],n=i[1],r="typeof "+r+" "+t+' "undefined" '+n+" "+r+" "+t+" null"):r=""+r+" "+(this.negated?"==":"!=")+" null",e.level<=L?r:"("+r+")"},t}(s),e.Parens=R=function(e){function t(e){this.body=e,t.__super__.constructor.call(this)}return St(t,e),t.prototype.children=["body"],t.prototype.unwrap=function(){return this.icedUnwrap(this.body)},t.prototype.isComplex=function(){return this.body.isComplex()},t.prototype.compileNode=function(e){var t,n,r;return r=this.body.unwrap(),r instanceof rt&&r.isAtomic()?(r.front=this.front,r.compile(e)):(n=r.compile(e,M),t=e.level1?t.expressions.unshift(new x((new R(this.guard)).invert(),new D("continue"))):this.guard&&(t=o.wrap([new x(this.guard,t)]))),this.pattern&&t.expressions.unshift(new r(this.name,new D(""+L+"["+h+"]"))),i+=this.pluckDirectCall(e,t),y&&(M="\n"+f+y+";"),this.object&&(s=""+h+" in "+L,this.own&&(a="\n"+f+"if (!"+yt("hasProp")+".call("+L+", "+h+")) continue;")),t=t.compile(pt(e,{indent:f}),_),t&&(t="\n"+t+"\n"),""+i+(w||"")+this.tab+"for ("+s+") {"+a+M+t+this.tab+"}"+(E||""))},i.prototype.pluckDirectCall=function(e,t){var n,i,s,o,a,f,c,h,p,d,v,m,g,y,b;i="",d=t.expressions;for(a=h=0,p=d.length;hs.length+r.length?""+this.tab+"if ("+s+") "+r.replace(/^\s+/,""):(r&&(r="\n"+r+"\n"+this.tab),u="if ("+s+") {"+r+"}",i||(u=this.tab+u),this.elseBody?u+" else "+(this.isChain?(e.indent=this.tab,e.chainChild=!0,this.elseBody.unwrap().compile(e,_)):"{\n"+this.elseBody.compile(e,_)+"\n"+this.tab+"}"):u))},t.prototype.compileExpression=function(e){var t,n,r,i;return i=this.condition.compile(e,L),n=this.bodyNode().compile(e,A),t=this.elseBodyNode()?this.elseBodyNode().compile(e,A):"void 0",r=""+i+" ? "+n+" : "+t,e.level>=L?"("+r+")":r},t.prototype.unfoldSoak=function(){return this.soak&&this},t}(s),f={wrap:function(e,n,r){var i,s,a,f,c;if(e.jumps())return e;a=new l([],o.wrap([e])),i=[];if((f=e.contains(this.literalArgs))||e.contains(this.literalThis))c=new D(f?"apply":"call"),i=[new D("this")],f&&i.push(new D("arguments")),a=new rt(a,[new t(c)]);return a.noReturn=r,s=new u(a,i),n?o.wrap([s]):s},literalArgs:function(e){return e instanceof D&&e.value==="arguments"&&!e.asKey},literalThis:function(e){return e instanceof D&&e.value==="this"&&!e.asKey||e instanceof l&&e.bound||e instanceof u&&e.isSuper}},h={wrap:function(e,t,n,r){var i,s,a,f,c,h;return h=new l([new q(new D(ct["const"].k))],o.wrap([e]),"icedgen"),i=[],n&&(n.bindName(r),i.push(n)),s=o.wrap([t]),(c=s.getSingle())&&c instanceof S&&c.canInline()?f=c.extractFunc():f=new l(i,s,"icedgen"),a=new u(h,[f]),new o([a])}},S=function(e){function t(e,n){this.func=e,n==null&&(n=null),t.__super__.constructor.call(this),this.func||(this.func=ct["const"].k),this.value=n}return St(t,e),t.prototype.children=["value"],t.prototype.assignValue=function(e){return this.value=e},t.prototype.canInline=function(){return!this.value||this.value instanceof w},t.prototype.literalFunc=function(){return new D(this.func)},t.prototype.extractFunc=function(){return new rt(this.literalFunc())},t.prototype.icedCpsRotate=function(){var e;if(this.value)if(e=this.icedCpsExprRotate(this.value))return this.value=e},t.prototype.compileNode=function(e){var t,n,r;return n=this.literalFunc(),r=e.level===_?this.value?new o([this.value,new u(n)]):new u(n):(t=this.value?[this.value]:[],new u(n,t)),r.compileNode(e)},t}(s),w=function(e){function t(){t.__super__.constructor.call(this,null,null,!1)}return St(t,e),t.counter=0,t.prototype.bindName=function(e){var n;return n=""+e.scope.freeVariable(ct["const"].param,!1)+"_"+t.counter++,this.name=new D(n)},t.prototype.compile=function(e){return this.name||this.bindName(e),t.__super__.compile.call(this,e)},t}(q),C={generate:function(e){var n,i,s,f,c,h,p,d,v,m,g,y,b,w,E,S,T,N,C,k,L,A,O,M,_,P,H,B,R,U,z,W,X,V,$,J,K,Q,G,Y,Z,et,tt,nt,it,st,ot,ut,at,ft,lt,ht,pt,dt;return $=new D("continuation"),v=new D("count"),d=new rt(new D(ct["const"].Deferrals)),et=new rt(new D(ct["const"].ns)),e&&(e.add(new t(et)),et=e),J=new rt(new D("this")),J.add(new t($)),ot=new q(J),m=new rt(new D("this")),m.add(new t(v)),ut=new rt(new D("this")),ut.add(new t(new rt(new D(ct["const"].retslot)))),n=new r(m,new rt(new D(1))),i=new r(ut,j()),E=[ot],y=new o([n,i]),b=new l(E,y),w=new rt(new D("constructor")),g=new r(w,b),R=new u(J,[ut]),H=new o([R]),S=new I("--",m),B=new I("!",S),Y=new x(B,H),ft=new o([Y]),ht=new l([],ft),dt=new rt(new D(ct["const"].fulfill)),at=new r(dt,ht),U=new I("++",m),V=new D("inner_params"),A=new D("defer_params"),O=new rt(A),p=new rt(A),s=new D(ct["const"].assign_fn),p.add(new t(s,"soak")),G=new D("apply"),p.add(new t(G,"soak")),Z=j(),f=new u(p,[Z,new rt(V)]),pt=new rt(new D("this")),pt.add(new t(new D(ct["const"].fulfill))),lt=new u(pt,[]),z=new o([f,lt]),X=[new q(V,null,!0)],W=new l(X,z,"boundfunc"),N=new o([U,W]),L=[new q(A)],C=new l(L,N),k=new rt(new D(ct["const"].defer_method)),T=new r(k,C),c=[g,at,T],it=new F(c,!0),h=new o([new rt(it)]),K=new a(null,null,h),Q=new r(d,K,"object"),st=new o([j()]),_=new l([],st),P=new rt(new D(ct["const"].findDeferral)),M=new r(P,_,"object"),tt=new F([Q,M],!0),nt=new rt(tt),new r(et,nt)}},gt=function(e,t,n){var r;if(!(r=t[n].unfoldSoak(e)))return;return t[n]=r.body,r.body=new rt(t),r},nt={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+yt("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},hasProp:function(){return"{}.hasOwnProperty"},slice:function(){return"[].slice"}},_=1,M=2,A=3,L=4,O=5,k=6,Y=" ",y="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",g=RegExp("^"+y+"$"),X=/^[+-]?\d+$/,P=RegExp("^(?:("+y+")\\.prototype(?:\\.("+y+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|("+y+")$"),b=/^['"]/,yt=function(e){var t;return t="__"+e,$.root.assign(t,nt[e]()),t},dt=function(e,t){return e=e.replace(/\n/g,"$&"+t),e.replace(/\s+$/,"")}}).call(this)},require["./coffee-script"]=new function(){var e=this;(function(){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y={}.hasOwnProperty;o=require("fs"),c=require("path"),g=require("./lexer"),n=g.Lexer,r=g.RESERVED,l=require("./parser").parser,h=require("vm"),u=require("./iced"),e.EXTENSIONS=t=[".coffee",".iced"],a=function(e){var n,r,i;for(r=0,i=t.length;r=o.window))return u();(function(e){r=new n.Deferrals(e,{parent:t,filename:"src/icedlib.coffee",funcname:"Pipeliner.waitInQueue"}),o.cb=r.defer({lineno:88}),r._fulfill()})(f)},s(e)}(function(){o.n_out++,function(e){if(!o.delay)return e();(function(e){r=new n.Deferrals(e,{parent:t,filename:"src/icedlib.coffee",funcname:"Pipeliner.waitInQueue"}),setTimeout(r.defer({lineno:96}),o.delay),r._fulfill()})(e)}(function(){return e()})})},e.prototype.__defer=function(e,t){var r,i,o,u,a,l=this;a=s,o=n.findDeferral(arguments),function(r){u=new n.Deferrals(r,{parent:o,filename:"src/icedlib.coffee",funcname:"Pipeliner.__defer"}),i=u.defer({lineno:109}),e[0]=function(){var e,n;return e=1<=arguments.length?f.call(arguments,0):[],(n=t.assign_fn)!=null&&n.apply(null,e),i()},u._fulfill()}(function(){l.n_out--;if(l.cb)return r=l.cb,l.cb=null,r()})},e.prototype._defer=function(e){var t;return t=[],this.__defer(t,e),t[0]},e.prototype.flush=function(e){var t,r,i,s,o,u=this;i=e,t=n.findDeferral(arguments),s=[],o=function(e){var i,a,f;i=function(){return e(s)},a=function(){return o(e)},f=function(e){return s.push(e),a()};if(!u.n_out)return i();(function(e){r=new n.Deferrals(e,{parent:t,filename:"src/icedlib.coffee",funcname:"Pipeliner.flush"}),u.cb=r.defer({lineno:136}),r._fulfill()})(f)},o(i)},e}()}).call(this)},require["./coffee-script"]}();typeof define=="function"&&define.amd?(define(function(){return CoffeeScript}),define(function(){return CoffeeScript.iced})):(root.CoffeeScript=CoffeeScript,root.iced=CoffeeScript.iced)})(this); \ No newline at end of file diff --git a/EditorExtensions/Resources/Scripts/JSDocComments.js b/EditorExtensions/Resources/Scripts/JSDocComments.js new file mode 100644 index 000000000..a8987834e --- /dev/null +++ b/EditorExtensions/Resources/Scripts/JSDocComments.js @@ -0,0 +1,185 @@ +(function () { + + intellisense.addEventListener("statementcompletionhint", function (event) { + var itemValue = event.completionItem.value; + if (typeof itemValue === "function") + if (!canApplyComments(event.symbolHelp.functionHelp)) return; + //non functions will only have one documentation type, therefore, no need to check symbolHelp fileds + var comments = event.completionItem.comments; + if (!isJSDocComment(comments)) return; + parseComment(comments, event); + }); + + function canApplyComments(functionHelp) { + var signatures = functionHelp.signatures; + var signature = signatures[0]; + if (signatures.length > 1) return false; + if (signature.description && signature.description.charAt(0) != "*") return false; + if (!signature.params.every(function (param) { return !param.description; })) return false; + return true; + } + + intellisense.addEventListener("signaturehelp", function (event) { + if (!canApplyComments(event.functionHelp)) return; + if (!isJSDocComment(event.functionComments.above)) return + parseComment(event.functionComments.above, event); + }); + + intellisense.addEventListener("statementcompletion", function (event) { + var i = 0; + while (i < event.items.length) { + var item = event.items[i]; + var isHidden = false; + var comments = item.comments; + if (isJSDocComment(comments)) + isHidden = parseCommentForCompletionItem(comments, item); + if (isHidden) event.items.splice(i, 1); + else i++; + } + }); + + function isJSDocComment(comments) { + return comments.length > 0 && comments.charAt(0) == "*"; + } + + var tagPattern = /^[* ]*@(\w+)[ ]?(.*)$/img; + + function parseCommentForCompletionItem(comment, completionItem) { + ///Returns true if the cpmpletionItem should be hidden from the + /// completionItem list + var obj = {}; + var tag = null; + while (tag = tagPattern.exec(comment)) obj["_" + tag[1]] = true; + completionItem.glyph = (obj._class && "vs:GlyphGroupClass") || + (obj._constructor && "vs:GlyphGroupClass") || + (obj._namespace && "vs:GlyphGroupNamespace") || + (obj._event && "vs:GlyphGroupEvent") || + (obj._enum && "vs:GlyphGroupEnum") || + (obj._interface && "vs:GlyphGroupInterface"); + return obj._private || obj._ignore; + } + + var typePattern = /{([a-zA-Z0-9(),=.]+)}/; + var namePattern = /\[*(\w+)\]*/; + + function JSDoc(commentStringArr) { + this.params = []; + //to prevent ShowPlainComments from overwriting description field for items with JSDoc + //set the description to " ". + this.description = " "; + this.returnType = null; + this.type = null; + this._deprecated = false; + for (var i = 0; i < commentStringArr.length; i++) { + var description = commentStringArr[i]; + var desArr = description.split(" "); + this["_" + desArr[0].substr(1)] = true; + tagName = desArr[0]; + switch (tagName) { + case "@description": + desArr.splice(0, 1); + this.description = desArr.join(" "); + break; + case "@type": + this.type = desArr[1]; + break; + case "@returns": + this.returnType = typePattern.exec(desArr[1])[1]; + if (this.returnType == "void") this.returnType = ""; + break; + case "@param": + var param = {}; + var name = namePattern.exec(desArr[2]); + param.name = name[1]; + param.type = typePattern.exec(desArr[1])[1].replace("...", ""); + if (param.type.charAt(param.type.length - 1) == "=") { + param.isOptional = true; + param.type = param.type.substr(0, param.type.length - 1); + } + if (param.type.toLowerCase().indexOf("function") >= 0) { + var type = param.type; + param.type = "function"; + param.functionParas = type.slice(type.indexOf("(") + 1, type.indexOf(")")).split(","); + } + param.isOptional = param.isOptional || name[0].charAt(0) == "["; + desArr.splice(0, 3); + param.description = desArr.join(" "); + this.params.push(param); + break; + } + } + }; + + var splitAtRegExp = /[ *]*[\r\n][ *]*/; + + function processComment(commentString) { + //replace the first "*" with a "*\r\n" + commentString = commentString.replace("*", "*\r\n"); + //remove consecutive spaces + commentString = commentString.replace(/[ ]+/g, " "); + //split at each new line [strip leading "*"s and spaces] + var arr = commentString.split(splitAtRegExp); + index = 0; + while (index < arr.length) { + if (arr[index].length == 0) { + arr.splice(index, 1); + continue; + } + if (arr[index].charAt(0) != "@") { + if (index != 0) { + //remainder of a description found. concatinate it with the string above it. + arr[index] = arr[index - 1] + " " + arr[index]; + //remove the previous string from the array. + arr.splice(index - 1, 1); + } else { + //inline description found - add "@description" tag + arr[index] = "@description " + arr[index]; + } + } else { + //new tag found. continue to the next tag + index++; + } + } + return arr; + } + + function parseComment(comment, event) { + var doc = new JSDoc(processComment(comment)); + //if the completion item is a function, then do + var sig = event.functionHelp.signatures[0] || event.symbolHelp.functionHelp.signatures[0]; + var symHlp = event.symbolHelp; + if (symHlp) symHlp.description = ((doc._deprecated && "[deprecated]") || "") + (doc.description || ""); + sig.description = ((doc._deprecated && "[deprecated]") || "") + (doc.description || ""); + + if (symHlp) { + symHlp.type = doc.type; + symHlp.symbolDisplayType = doc.type; + } + sig.returnValue = new ReturnValue(); + sig.returnValue.type = doc.returnType; + sig.returnValue.elementType = doc.returnType; + for (var i = 0; i < doc.params.length; i++) { + var param = doc.params[i]; + for (var j = 0; j < sig.params.length; j++) { + //search for the right parameter to modify + if (sig.params[j].name == param.name) { + //if param type is function, set the params for the function + if (param.type.toLowerCase() == "function") { + sig.params[j].funcParamSignature = new Signature(); + sig.params[j].funcParamSignature.params = []; + for (var k = 0; k < param.functionParas.length; k++) { + var para = new Parameter(); + para.name = param.functionParas[k]; + sig.params[j].funcParamSignature.params.push(para); + } + } + sig.params[j].type = param.type; + sig.params[j].optional = param.isOptional; + sig.params[j].description = param.description; + break; + } + } + } + return doc._private || doc._ignore; + } +})(); diff --git a/EditorExtensions/Resources/Scripts/jshint.js b/EditorExtensions/Resources/Scripts/jshint.js new file mode 100644 index 000000000..9d1d0ebec --- /dev/null +++ b/EditorExtensions/Resources/Scripts/jshint.js @@ -0,0 +1,4538 @@ +/*! + * JSHint, by JSHint Community. + * + * Licensed under the same slightly modified MIT license that JSLint is. + * It stops evil-doers everywhere. + * + * JSHint is a derivative work of JSLint: + * + * Copyright (c) 2002 Douglas Crockford (www.JSLint.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * The Software shall be used for Good, not Evil. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * JSHint was forked from 2010-12-16 edition of JSLint. + * + */ + +/* + JSHINT is a global function. It takes two parameters. + + var myResult = JSHINT(source, option); + + The first parameter is either a string or an array of strings. If it is a + string, it will be split on '\n' or '\r'. If it is an array of strings, it + is assumed that each string represents one line. The source can be a + JavaScript text or a JSON text. + + The second parameter is an optional object of options which control the + operation of JSHINT. Most of the options are booleans: They are all + optional and have a default value of false. One of the options, predef, + can be an array of names, which will be used to declare global variables, + or an object whose keys are used as global names, with a boolean value + that determines if they are assignable. + + If it checks out, JSHINT returns true. Otherwise, it returns false. + + If false, you can inspect JSHINT.errors to find out the problems. + JSHINT.errors is an array of objects containing these members: + + { + line : The line (relative to 1) at which the lint was found + character : The character (relative to 1) at which the lint was found + reason : The problem + evidence : The text line in which the problem occurred + raw : The raw message before the details were inserted + a : The first detail + b : The second detail + c : The third detail + d : The fourth detail + } + + If a fatal error was found, a null will be the last element of the + JSHINT.errors array. + + You can request a Function Report, which shows all of the functions + and the parameters and vars that they use. This can be used to find + implied global variables and other problems. The report is in HTML and + can be inserted in an HTML . + + var myReport = JSHINT.report(limited); + + If limited is true, then the report will be limited to only errors. + + You can request a data structure which contains JSHint's results. + + var myData = JSHINT.data(); + + It returns a structure with this form: + + { + errors: [ + { + line: NUMBER, + character: NUMBER, + reason: STRING, + evidence: STRING + } + ], + functions: [ + name: STRING, + line: NUMBER, + character: NUMBER, + last: NUMBER, + lastcharacter: NUMBER, + param: [ + STRING + ], + closure: [ + STRING + ], + var: [ + STRING + ], + exception: [ + STRING + ], + outer: [ + STRING + ], + unused: [ + STRING + ], + global: [ + STRING + ], + label: [ + STRING + ] + ], + globals: [ + STRING + ], + member: { + STRING: NUMBER + }, + unused: [ + { + name: STRING, + line: NUMBER + } + ], + implieds: [ + { + name: STRING, + line: NUMBER + } + ], + urls: [ + STRING + ], + json: BOOLEAN + } + + Empty arrays will not be included. + +*/ + +/*jshint + evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, + undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true +*/ + +/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", + "(breakage)", "(character)", "(context)", "(error)", "(global)", "(identifier)", "(last)", + "(lastcharacter)", "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", + "(statement)", "(verb)", "(tokens)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, + __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, + Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, + CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser, Drag, + E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, + FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, + HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, + HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement, + HTMLDivElement, HTMLDListElement, HTMLFieldSetElement, + HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, + HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement, + HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement, + HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement, + HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement, + HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, + HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement, + HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement, + HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, + HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, + HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement, + Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array, + Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, + MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort, + MoveAnimation, MooTools, MutationObserver, Native, NEGATIVE_INFINITY, Node, NodeFilter, + Number, Object, ObjectRange, + Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, + RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, + ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, + Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, + SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, + Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, + VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer, + XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, + "\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity, + asi, atob, b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, btoa, c, + call, callee, caller, camelcase, cases, charAt, charCodeAt, character, clearInterval, + clearTimeout, close, closed, closure, comment, condition, confirm, console, constructor, + content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, + decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent, + eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach, + forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, + g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict, + hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, + indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, + isDigit, isFinite, isNaN, iterator, java, join, jshint, + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak, + laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, + moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, + nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, + onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, + parent, parseFloat, parseInt, passfail, plusplus, postMessage, predef, print, process, prompt, + proto, prototype, prototypejs, provides, push, quit, quotmark, range, raw, reach, reason, regexp, + readFile, readUrl, regexdash, removeEventListener, replace, report, require, + reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, + runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, self, + send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice, + smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow, + supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, tokens, top, + trailing, type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, + urls, validthis, value, valueOf, var, vars, version, WebSocket, withstmt, white, window, windows, + Worker, worker, wsh*/ + +/*global exports: false */ + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSHINT function itself. + +var JSHINT = (function () { + "use strict"; + + var anonname, // The guessed name for anonymous functions. + +// These are operators that should not be used with the ! operator. + + bang = { + "<" : true, + "<=" : true, + "==" : true, + "===": true, + "!==": true, + "!=" : true, + ">" : true, + ">=" : true, + "+" : true, + "-" : true, + "*" : true, + "/" : true, + "%" : true + }, + + // These are the JSHint boolean options. + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + bitwise : true, // if bitwise operators should not be allowed + boss : true, // if advanced usage of assignments should be allowed + browser : true, // if the standard browser globals should be predefined + camelcase : true, // if identifiers should be required in camel case + couch : true, // if CouchDB globals should be predefined + curly : true, // if curly braces around all blocks should be required + debug : true, // if debugger statements should be allowed + devel : true, // if logging globals should be predefined (console, + // alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es5 : true, // if ES5 syntax should be allowed + esnext : true, // if es.next specific syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + funcscope : true, // if only function scope should be used for scope tests + globalstrict: true, // if global "use strict"; should be allowed (also + // enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be allowed + jquery : true, // if jQuery globals should be predefined + lastsemic : true, // if semicolons may be ommitted for the trailing + // statements inside of a one-line blocks. + latedef : true, // if the use before definition should not be tolerated + laxbreak : true, // if line breaks should not be checked + laxcomma : true, // if line breaks should not be checked around commas + loopfunc : true, // if functions should be allowed to be defined within + // loops + mootools : true, // if MooTools globals should be predefined + multistr : true, // allow multiline strings + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be + // disallowed + node : true, // if the Node.js environment globals should be + // predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nonstandard : true, // if non-standard (but widely adopted) globals should + // be predefined + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be + // allowed + onecase : true, // if one case switch statements should be allowed + passfail : true, // if the scan should stop on first error + plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be + // predefined + regexdash : true, // if unescaped first/last dash (-) inside brackets + // should be tolerated + regexp : true, // if the . should not be allowed in regexp literals + rhino : true, // if the Rhino environment globals should be predefined + undef : true, // if variables should be declared before used + unused : true, // if variables should be always used + scripturl : true, // if script-targeted URLs should be tolerated + shadow : true, // if variable shadowing should be tolerated + smarttabs : true, // if smarttabs should be tolerated + // (http://www.emacswiki.org/emacs/SmartTabs) + strict : true, // require the "use strict"; pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` + // should be tolerated + trailing : true, // if trailing whitespace rules apply + validthis : true, // if 'this' inside a non-constructor function is valid. + // This is a function scoped option only. + withstmt : true, // if with statements should be allowed + white : true, // if strict whitespace rules apply + worker : true, // if Web Worker script symbols should be allowed + wsh : true // if the Windows Scripting Host environment globals + // should be predefined + }, + + // These are the JSHint options that can take any value + // (we use this object to detect invalid options) + valOptions = { + maxlen: false, + indent: false, + maxerr: false, + predef: false, + quotmark: false //'single'|'double'|true + }, + + // These are JSHint boolean options which are shared with JSLint + // where the definition in JSHint is opposite JSLint + invertedOptions = { + bitwise : true, + forin : true, + newcap : true, + nomen : true, + plusplus : true, + regexp : true, + undef : true, + white : true, + + // Inverted and renamed, use JSHint name here + eqeqeq : true, + onevar : true + }, + + // These are JSHint boolean options which are shared with JSLint + // where the name has been changed but the effect is unchanged + renamedOptions = { + eqeq : "eqeqeq", + vars : "onevar", + windows : "wsh" + }, + + + // browser contains a set of global names which are commonly provided by a + // web browser environment. + browser = { + ArrayBuffer : false, + ArrayBufferView : false, + Audio : false, + addEventListener : false, + applicationCache : false, + atob : false, + blur : false, + btoa : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + DataView : false, + DOMParser : false, + defaultStatus : false, + document : false, + event : false, + FileReader : false, + Float32Array : false, + Float64Array : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement : false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement : false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement : false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Image : false, + length : false, + localStorage : false, + location : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, + moveBy : false, + moveTo : false, + MutationObserver : false, + name : false, + Node : false, + NodeFilter : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + top : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XMLSerializer : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false + }, + + couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false, + provides : false + }, + + declared, // Globals that were declared using /*global ... */ syntax. + + devel = { + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false + }, + + funct, // The current function + + functionicity = [ + "closure", "exception", "global", "label", + "outer", "unused", "var" + ], + + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + jsonmode, + + jquery = { + "$" : false, + jQuery : false + }, + + lines, + lookahead, + member, + membersOnly, + + mootools = { + "$" : false, + "$$" : false, + Assets : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator : false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false + }, + + nexttoken, + + node = { + __filename : false, + __dirname : false, + Buffer : false, + console : false, + exports : true, // In Node it is ok to exports = module.exports = foo(); + GLOBAL : false, + global : false, + module : false, + process : false, + require : false, + setTimeout : false, + clearTimeout : false, + setInterval : false, + clearInterval : false + }, + + noreach, + option, + predefined, // Global variables defined by option + prereg, + prevtoken, + + prototypejs = { + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false + }, + + quotmark, + + rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false + }, + + scope, // The current scope + stack, + + // standard contains the global names that are provided by the + // ECMAScript standard. + standard = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + "eval" : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Math : false, + Number : false, + Object : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false + }, + + // widely adopted global names that are not part of ECMAScript standard + nonstandard = { + escape : false, + unescape : false + }, + + directive, + syntax = {}, + tab, + token, + urls, + useESNextSyntax, + warnings, + + worker = { + importScripts : true, + postMessage : true, + self : true + }, + + wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true, + XDomainRequest : true + }; + + // Regular expressions. Some of these are stupidly long. + var ax, cx, tx, nx, nxg, lx, ix, jx, ft; + (function () { + /*jshint maxlen:300 */ + + // unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + + // unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + + // token + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; + + // characters in strings that need escapement + nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + // star slash + lx = /\*\/|\/\*/; + + // identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + + // javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + // catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + }()); + + function F() {} // Used by Object.create + + function is_own(object, name) { + // The object.hasOwnProperty method fails when the property under consideration + // is named 'hasOwnProperty'. So we have to use this more convoluted form. + return Object.prototype.hasOwnProperty.call(object, name); + } + + function checkOption(name, t) { + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + warning("Bad option: '" + name + "'.", t); + } + } + + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; + } + + // Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== "function") { + Array.isArray = function (o) { + return Object.prototype.toString.apply(o) === "[object Array]"; + }; + } + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, scope) { + var len = this.length; + + for (var i = 0; i < len; i++) { + fn.call(scope || this, this[i], i, this); + } + }; + } + + if (typeof Object.create !== "function") { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== "function") { + Object.keys = function (o) { + var a = [], k; + for (k in o) { + if (is_own(o, k)) { + a.push(k); + } + } + return a; + }; + } + + // Non standard methods + + function isAlpha(str) { + return (str >= "a" && str <= "z\uffff") || + (str >= "A" && str <= "Z\uffff"); + } + + function isDigit(str) { + return (str >= "0" && str <= "9"); + } + + function supplant(str, data) { + return str.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = data[b]; + return typeof r === "string" || typeof r === "number" ? r : a; + }); + } + + function combine(t, o) { + var n; + for (n in o) { + if (is_own(o, n)) { + t[n] = o[n]; + } + } + } + + function assume() { + if (option.couch) { + combine(predefined, couch); + } + + if (option.rhino) { + combine(predefined, rhino); + } + + if (option.prototypejs) { + combine(predefined, prototypejs); + } + + if (option.node) { + combine(predefined, node); + option.globalstrict = true; + } + + if (option.devel) { + combine(predefined, devel); + } + + if (option.dojo) { + combine(predefined, dojo); + } + + if (option.browser) { + combine(predefined, browser); + } + + if (option.nonstandard) { + combine(predefined, nonstandard); + } + + if (option.jquery) { + combine(predefined, jquery); + } + + if (option.mootools) { + combine(predefined, mootools); + } + + if (option.worker) { + combine(predefined, worker); + } + + if (option.wsh) { + combine(predefined, wsh); + } + + if (option.esnext) { + useESNextSyntax(); + } + + if (option.globalstrict && option.strict !== false) { + option.strict = true; + } + } + + + // Produce an error warning. + function quit(message, line, chr) { + var percentage = Math.floor((line / lines.length) * 100); + + throw { + name: "JSHintError", + line: line, + character: chr, + message: message + " (" + percentage + "% scanned).", + raw: message + }; + } + + function isundef(scope, m, t, a) { + return JSHINT.undefs.push([scope, m, t, a]); + } + + function warning(m, t, a, b, c, d) { + var ch, l, w; + t = t || nexttoken; + if (t.id === "(end)") { // `~ + t = token; + } + l = t.line || 0; + ch = t.from || 0; + w = { + id: "(error)", + raw: m, + evidence: lines[l - 1] || "", + line: l, + character: ch, + a: a, + b: b, + c: c, + d: d + }; + w.reason = supplant(m, w); + JSHINT.errors.push(w); + if (option.passfail) { + quit("Stopping. ", l, ch); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit("Too many errors.", l, ch); + } + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + + + +// lexical analysis and token construction + + var lex = (function lex() { + var character, from, line, s; + +// Private lex methods + + function nextLine() { + var at, + tw; // trailing whitespace check + + if (line >= lines.length) + return false; + + character = 1; + s = lines[line]; + line += 1; + + // If smarttabs option is used check for spaces followed by tabs only. + // Otherwise check for any occurence of mixed tabs and spaces. + // Tabs and one space followed by block comment is allowed. + if (option.smarttabs) + at = s.search(/ \t/); + else + at = s.search(/ \t|\t [^\*]/); + + if (at >= 0) + warningAt("Mixed spaces and tabs.", line, at + 1); + + s = s.replace(/\t/g, tab); + at = s.search(cx); + + if (at >= 0) + warningAt("Unsafe character.", line, at); + + if (option.maxlen && option.maxlen < s.length) + warningAt("Line too long.", line, s.length); + + // Check for trailing whitespaces + tw = option.trailing && s.match(/^(.*?)\s+$/); + if (tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw[1].length + 1); + } + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var i, t; + + function checkName(name) { + if (!option.proto && name === "__proto__") { + warningAt("The '{a}' property is deprecated.", line, from, name); + return; + } + + if (!option.iterator && name === "__iterator__") { + warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name); + return; + } + + // Check for dangling underscores unless we're in Node + // environment and this identifier represents built-in + // Node globals with underscores. + + var hasDangling = /^(_+.*|.*_+)$/.test(name); + + if (option.nomen && hasDangling && name !== "_") { + if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name)) + return; + + warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name); + return; + } + + // Check for non-camelcase names. Names like MY_VAR and + // _myVar are okay though. + + if (option.camelcase) { + if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) { + warningAt("Identifier '{a}' is not in camel case.", line, from, value); + } + } + } + + if (type === "(color)" || type === "(range)") { + t = {type: type}; + } else if (type === "(punctuator)" || + (type === "(identifier)" && is_own(syntax, value))) { + t = syntax[value] || syntax["(error)"]; + } else { + t = syntax[type]; + } + + t = Object.create(t); + + if (type === "(string)" || type === "(range)") { + if (!option.scripturl && jx.test(value)) { + warningAt("Script URL.", line, from); + } + } + + if (type === "(identifier)") { + t.identifier = true; + checkName(value); + } + + t.value = value; + t.line = line; + t.character = character; + t.from = from; + i = t.id; + if (i !== "(endline)") { + prereg = i && + (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) || + i === "return" || + i === "case"); + } + return t; + } + + // Public lex methods + return { + init: function (source) { + if (typeof source === "string") { + lines = source + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n"); + } else { + lines = source; + } + + // If the first line is a shebang (#!), make it a blank and move on. + // Shebangs are used by Node scripts. + if (lines[0] && lines[0].substr(0, 2) === "#!") + lines[0] = ""; + + line = 0; + nextLine(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ""; + from = character; + if (s.charAt(0) !== begin) { + errorAt("Expected '{a}' and instead saw '{b}'.", + line, character, begin, s.charAt(0)); + } + for (;;) { + s = s.slice(1); + character += 1; + c = s.charAt(0); + switch (c) { + case "": + errorAt("Missing '{a}'.", line, character, c); + break; + case end: + s = s.slice(1); + character += 1; + return it("(range)", value); + case "\\": + warningAt("Unexpected '{a}'.", line, character, c); + } + value += c; + } + + }, + + + // token -- this is called by advance to get the next token + token: function () { + var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n; + + function match(x) { + var r = x.exec(s), r1; + if (r) { + l = r[0].length; + r1 = r[1]; + c = r1.charAt(0); + s = s.substr(l); + from = character + l - r1.length; + character += l; + return r1; + } + } + + function string(x) { + var c, j, r = "", allowNewLine = false; + + if (jsonmode && x !== "\"") { + warningAt("Strings must use doublequote.", + line, character); + } + + if (option.quotmark) { + if (option.quotmark === "single" && x !== "'") { + warningAt("Strings must use singlequote.", + line, character); + } else if (option.quotmark === "double" && x !== "\"") { + warningAt("Strings must use doublequote.", + line, character); + } else if (option.quotmark === true) { + quotmark = quotmark || x; + if (quotmark !== x) { + warningAt("Mixed double and single quotes.", + line, character); + } + } + } + + function esc(n) { + var i = parseInt(s.substr(j + 1, n), 16); + j += n; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warningAt("Unnecessary escapement.", line, character); + } + character += n; + c = String.fromCharCode(i); + } + j = 0; +unclosedString: for (;;) { + while (j >= s.length) { + j = 0; + + var cl = line, cf = from; + if (!nextLine()) { + errorAt("Unclosed string.", cl, cf); + break unclosedString; + } + + if (allowNewLine) { + allowNewLine = false; + } else { + warningAt("Unclosed string.", cl, cf); + } + } + c = s.charAt(j); + if (c === x) { + character += 1; + s = s.substr(j + 1); + return it("(string)", r, x); + } + if (c < " ") { + if (c === "\n" || c === "\r") { + break; + } + warningAt("Control character in string: {a}.", + line, character + j, s.slice(0, j)); + } else if (c === "\\") { + j += 1; + character += 1; + c = s.charAt(j); + n = s.charAt(j + 1); + switch (c) { + case "\\": + case "\"": + case "/": + break; + case "\'": + if (jsonmode) { + warningAt("Avoid \\'.", line, character); + } + break; + case "b": + c = "\b"; + break; + case "f": + c = "\f"; + break; + case "n": + c = "\n"; + break; + case "r": + c = "\r"; + break; + case "t": + c = "\t"; + break; + case "0": + c = "\0"; + // Octal literals fail in strict mode + // check if the number is between 00 and 07 + // where 'n' is the token next to 'c' + if (n >= 0 && n <= 7 && directive["use strict"]) { + warningAt( + "Octal literals are not allowed in strict mode.", + line, character); + } + break; + case "u": + esc(4); + break; + case "v": + if (jsonmode) { + warningAt("Avoid \\v.", line, character); + } + c = "\v"; + break; + case "x": + if (jsonmode) { + warningAt("Avoid \\x-.", line, character); + } + esc(2); + break; + case "": + // last character is escape character + // always allow new line if escaped, but show + // warning if option is not set + allowNewLine = true; + if (option.multistr) { + if (jsonmode) { + warningAt("Avoid EOL escapement.", line, character); + } + c = ""; + character -= 1; + break; + } + warningAt("Bad escapement of EOL. Use option multistr if needed.", + line, character); + break; + default: + warningAt("Bad escapement.", line, character); + } + } + r += c; + character += 1; + j += 1; + } + } + + for (;;) { + if (!s) { + return it(nextLine() ? "(endline)" : "(end)", ""); + } + t = match(tx); + if (!t) { + t = ""; + c = ""; + while (s && s < "!") { + s = s.substr(1); + } + if (s) { + errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); + s = ""; + } + } else { + + // identifier + + if (isAlpha(c) || c === "_" || c === "$") { + return it("(identifier)", t); + } + + // number + + if (isDigit(c)) { + if (!isFinite(Number(t))) { + warningAt("Bad number '{a}'.", + line, character, t); + } + if (isAlpha(s.substr(0, 1))) { + warningAt("Missing space after '{a}'.", + line, character, t); + } + if (c === "0") { + d = t.substr(1, 1); + if (isDigit(d)) { + if (token.id !== ".") { + warningAt("Don't use extra leading zeros '{a}'.", + line, character, t); + } + } else if (jsonmode && (d === "x" || d === "X")) { + warningAt("Avoid 0x-. '{a}'.", + line, character, t); + } + } + if (t.substr(t.length - 1) === ".") { + warningAt( +"A trailing decimal point can be confused with a dot '{a}'.", line, character, t); + } + return it("(number)", t); + } + switch (t) { + + // string + + case "\"": + case "'": + return string(t); + + // // comment + + case "//": + s = ""; + token.comment = true; + break; + + // /* comment + + case "/*": + for (;;) { + i = s.search(lx); + if (i >= 0) { + break; + } + if (!nextLine()) { + errorAt("Unclosed comment.", line, character); + } + } + character += i + 2; + if (s.substr(i, 1) === "/") { + errorAt("Nested comment.", line, character); + } + s = s.substr(i + 2); + token.comment = true; + break; + + // /*members /*jshint /*global + + case "/*members": + case "/*member": + case "/*jshint": + case "/*jslint": + case "/*global": + case "*/": + return { + value: t, + type: "special", + line: line, + character: character, + from: from + }; + + case "": + break; + // / + case "/": + if (token.id === "/=") { + errorAt("A regular expression literal can be confused with '/='.", + line, from); + } + if (prereg) { + depth = 0; + captures = 0; + l = 0; + for (;;) { + b = true; + c = s.charAt(l); + l += 1; + switch (c) { + case "": + errorAt("Unclosed regular expression.", line, from); + return quit("Stopping.", line, from); + case "/": + if (depth > 0) { + warningAt("{a} unterminated regular expression " + + "group(s).", line, from + l, depth); + } + c = s.substr(0, l - 1); + q = { + g: true, + i: true, + m: true + }; + while (q[s.charAt(l)] === true) { + q[s.charAt(l)] = false; + l += 1; + } + character += l; + s = s.substr(l); + q = s.charAt(0); + if (q === "/" || q === "*") { + errorAt("Confusing regular expression.", + line, from); + } + return it("(regexp)", c); + case "\\": + c = s.charAt(l); + if (c < " ") { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === "<") { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + break; + case "(": + depth += 1; + b = false; + if (s.charAt(l) === "?") { + l += 1; + switch (s.charAt(l)) { + case ":": + case "=": + case "!": + l += 1; + break; + default: + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l)); + } + } else { + captures += 1; + } + break; + case "|": + b = false; + break; + case ")": + if (depth === 0) { + warningAt("Unescaped '{a}'.", + line, from + l, ")"); + } else { + depth -= 1; + } + break; + case " ": + q = 1; + while (s.charAt(l) === " ") { + l += 1; + q += 1; + } + if (q > 1) { + warningAt( +"Spaces are hard to count. Use {{a}}.", line, from + l, q); + } + break; + case "[": + c = s.charAt(l); + if (c === "^") { + l += 1; + if (option.regexp) { + warningAt("Insecure '{a}'.", + line, from + l, c); + } else if (s.charAt(l) === "]") { + errorAt("Unescaped '{a}'.", + line, from + l, "^"); + } + } + if (c === "]") { + warningAt("Empty class.", line, + from + l - 1); + } + isLiteral = false; + isInRange = false; +klass: do { + c = s.charAt(l); + l += 1; + switch (c) { + case "[": + case "^": + warningAt("Unescaped '{a}'.", + line, from + l, c); + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "-": + if (isLiteral && !isInRange) { + isLiteral = false; + isInRange = true; + } else if (isInRange) { + isInRange = false; + } else if (s.charAt(l) === "]") { + isInRange = true; + } else { + if (option.regexdash !== (l === 2 || (l === 3 && + s.charAt(1) === "^"))) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, "-"); + } + isLiteral = true; + } + break; + case "]": + if (isInRange && !option.regexdash) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, "-"); + } + break klass; + case "\\": + c = s.charAt(l); + if (c < " ") { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === "<") { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + + // \w, \s and \d are never part of a character range + if (/[wsd]/i.test(c)) { + if (isInRange) { + warningAt("Unescaped '{a}'.", + line, from + l, "-"); + isInRange = false; + } + isLiteral = false; + } else if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "/": + warningAt("Unescaped '{a}'.", + line, from + l - 1, "/"); + + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "<": + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + default: + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + } + } while (c); + break; + case ".": + if (option.regexp) { + warningAt("Insecure '{a}'.", line, + from + l, c); + } + break; + case "]": + case "?": + case "{": + case "}": + case "+": + case "*": + warningAt("Unescaped '{a}'.", line, + from + l, c); + } + if (b) { + switch (s.charAt(l)) { + case "?": + case "+": + case "*": + l += 1; + if (s.charAt(l) === "?") { + l += 1; + } + break; + case "{": + l += 1; + c = s.charAt(l); + if (c < "0" || c > "9") { + warningAt( +"Expected a number and instead saw '{a}'.", line, from + l, c); + } + l += 1; + low = +c; + for (;;) { + c = s.charAt(l); + if (c < "0" || c > "9") { + break; + } + l += 1; + low = +c + (low * 10); + } + high = low; + if (c === ",") { + l += 1; + high = Infinity; + c = s.charAt(l); + if (c >= "0" && c <= "9") { + l += 1; + high = +c; + for (;;) { + c = s.charAt(l); + if (c < "0" || c > "9") { + break; + } + l += 1; + high = +c + (high * 10); + } + } + } + if (s.charAt(l) !== "}") { + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c); + } else { + l += 1; + } + if (s.charAt(l) === "?") { + l += 1; + } + if (low > high) { + warningAt( +"'{a}' should not be greater than '{b}'.", line, from + l, low, high); + } + } + } + } + c = s.substr(0, l - 1); + character += l; + s = s.substr(l); + return it("(regexp)", c); + } + return it("(punctuator)", t); + + // punctuator + + case "#": + return it("(punctuator)", t); + default: + return it("(punctuator)", t); + } + } + } + } + }; + }()); + + + function addlabel(t, type, token) { + + if (t === "hasOwnProperty") { + warning("'hasOwnProperty' is a really bad name."); + } + + // Define t in the current function in the current scope. + if (is_own(funct, t) && !funct["(global)"]) { + if (funct[t] === true) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + } else { + if (!option.shadow && type !== "exception") + warning("'{a}' is already defined.", nexttoken, t); + } + } + + funct[t] = type; + + if (token) { + funct["(tokens)"][t] = token; + } + + if (funct["(global)"]) { + global[t] = funct; + if (is_own(implied, t)) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + + + function doOption() { + var nt = nexttoken; + var o = nt.value; + var quotmarkValue = option.quotmark; + var predef = {}; + var b, obj, filter, t, tn, v; + + switch (o) { + case "*/": + error("Unbegun comment."); + break; + case "/*members": + case "/*member": + o = "/*members"; + if (!membersOnly) { + membersOnly = {}; + } + obj = membersOnly; + option.quotmark = false; + break; + case "/*jshint": + case "/*jslint": + obj = option; + filter = boolOptions; + break; + case "/*global": + obj = predef; + break; + default: + error("What?"); + } + + t = lex.token(); +loop: for (;;) { + for (;;) { + if (t.type === "special" && t.value === "*/") { + break loop; + } + if (t.id !== "(endline)" && t.id !== ",") { + break; + } + t = lex.token(); + } + if (t.type !== "(string)" && t.type !== "(identifier)" && + o !== "/*members") { + error("Bad option.", t); + } + + v = lex.token(); + if (v.id === ":") { + v = lex.token(); + + if (obj === membersOnly) { + error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":"); + } + + if (o === "/*jshint") { + checkOption(t.value, t); + } + + if (t.value === "indent" && (o === "/*jshint" || o === "/*jslint")) { + b = +v.value; + if (typeof b !== "number" || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.white = true; + obj.indent = b; + } else if (t.value === "maxerr" && (o === "/*jshint" || o === "/*jslint")) { + b = +v.value; + if (typeof b !== "number" || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxerr = b; + } else if (t.value === "maxlen" && (o === "/*jshint" || o === "/*jslint")) { + b = +v.value; + if (typeof b !== "number" || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxlen = b; + } else if (t.value === "validthis") { + if (funct["(global)"]) { + error("Option 'validthis' can't be used in a global scope."); + } else { + if (v.value === "true" || v.value === "false") + obj[t.value] = v.value === "true"; + else + error("Bad option value.", v); + } + } else if (t.value === "quotmark" && (o === "/*jshint")) { + switch (v.value) { + case "true": + obj.quotmark = true; + break; + case "false": + obj.quotmark = false; + break; + case "double": + case "single": + obj.quotmark = v.value; + break; + default: + error("Bad option value.", v); + } + } else if (v.value === "true" || v.value === "false") { + if (o === "/*jslint") { + tn = renamedOptions[t.value] || t.value; + obj[tn] = v.value === "true"; + if (invertedOptions[tn] !== undefined) { + obj[tn] = !obj[tn]; + } + } else { + obj[t.value] = v.value === "true"; + } + } else { + error("Bad option value.", v); + } + t = lex.token(); + } else { + if (o === "/*jshint" || o === "/*jslint") { + error("Missing option value.", t); + } + obj[t.value] = false; + t = v; + } + } + + if (o === "/*members") { + option.quotmark = quotmarkValue; + } + + combine(predefined, predef); + + for (var key in predef) { + if (is_own(predef, key)) { + declared[key] = nt; + } + } + + if (filter) { + assume(); + } + } + + +// We need a peek function. If it has an argument, it peeks that much farther +// ahead. It is used to distinguish +// for ( var i in ... +// from +// for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + + +// Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (token.id) { + case "(number)": + if (nexttoken.id === ".") { + warning("A dot following a number can be confused with a decimal point.", token); + } + break; + case "-": + if (nexttoken.id === "-" || nexttoken.id === "--") { + warning("Confusing minusses."); + } + break; + case "+": + if (nexttoken.id === "+" || nexttoken.id === "++") { + warning("Confusing plusses."); + } + break; + } + + if (token.type === "(string)" || token.identifier) { + anonname = token.value; + } + + if (id && nexttoken.id !== id) { + if (t) { + if (nexttoken.id === "(end)") { + warning("Unmatched '{a}'.", t, t.id); + } else { + warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + nexttoken, id, t.id, t.line, nexttoken.value); + } + } else if (nexttoken.type !== "(identifier)" || + nexttoken.value !== id) { + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, id, nexttoken.value); + } + } + + prevtoken = token; + token = nexttoken; + for (;;) { + nexttoken = lookahead.shift() || lex.token(); + if (nexttoken.id === "(end)" || nexttoken.id === "(error)") { + return; + } + if (nexttoken.type === "special") { + doOption(); + } else { + if (nexttoken.id !== "(endline)") { + break; + } + } + } + } + + +// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false, isObject = false; + + if (nexttoken.id === "(end)") + error("Unexpected early end of program.", token); + + advance(); + if (initial) { + anonname = "anonymous"; + funct["(verb)"] = token.value; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (nexttoken.type === "(number)" && token.id === ".") { + warning("A leading decimal point can be confused with a dot: '.{a}'.", + token, nexttoken.value); + advance(); + return token; + } else { + error("Expected an identifier and instead saw '{a}'.", + token, token.id); + } + } + while (rbp < nexttoken.lbp) { + isArray = token.value === "Array"; + isObject = token.value === "Object"; + + // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object() + // Line breaks in IfStatement heads exist to satisfy the checkJSHint + // "Line too long." error. + if (left && (left.value || (left.first && left.first.value))) { + // If the left.value is not "new", or the left.first.value is a "." + // then safely assume that this is not "new Array()" and possibly + // not "new Object()"... + if (left.value !== "new" || + (left.first && left.first.value && left.first.value === ".")) { + isArray = false; + // ...In the case of Object, if the left.value and token.value + // are not equal, then safely assume that this not "new Object()" + if (left.value !== token.value) { + isObject = false; + } + } + } + + advance(); + if (isArray && token.id === "(" && nexttoken.id === ")") + warning("Use the array literal notation [].", token); + if (isObject && token.id === "(" && nexttoken.id === ")") + warning("Use the object literal notation {}.", token); + if (token.led) { + left = token.led(left); + } else { + error("Expected an operator and instead saw '{a}'.", + token, token.id); + } + } + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white) { + if (left.character !== right.from && left.line === right.line) { + left.from += (left.character - left.from); + warning("Unexpected space after '{a}'.", left, left.value); + } + } + } + + function nobreak(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && (left.character !== right.from || left.line !== right.line)) { + warning("Unexpected space before '{a}'.", right, right.value); + } + } + + function nospace(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.value === ";" && right.value === ";") { + return; + } + if (left.line === right.line && left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (!option.laxbreak && left.line !== right.line) { + warning("Bad line breaking before '{a}'.", right, right.id); + } else if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function indentation(bias) { + var i; + if (option.white && nexttoken.id !== "(end)") { + i = indent + (bias || 0); + if (nexttoken.from !== i) { + warning( +"Expected '{a}' to have an indentation at {b} instead at {c}.", + nexttoken, nexttoken.value, i, nexttoken.from); + } + } + } + + function nolinebreak(t) { + t = t || token; + if (t.line !== nexttoken.line) { + warning("Line breaking error '{a}'.", t, t.value); + } + } + + + function comma() { + if (token.line !== nexttoken.line) { + if (!option.laxcomma) { + if (comma.first) { + warning("Comma warnings can be turned off with 'laxcomma'"); + comma.first = false; + } + warning("Bad line breaking before '{a}'.", token, nexttoken.id); + } + } else if (!token.comment && token.character !== nexttoken.from && option.white) { + token.from += (token.character - token.from); + warning("Unexpected space after '{a}'.", token, token.value); + } + advance(","); + nonadjacent(token, nexttoken); + } + + +// Functional constructors for making the symbols that will be inherited by +// tokens. + + function symbol(s, p) { + var x = syntax[s]; + if (!x || typeof x !== "object") { + syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + + function delim(s) { + return symbol(s, 0); + } + + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === "function") ? f : function () { + this.right = expression(150); + this.arity = "unary"; + if (this.id === "++" || this.id === "--") { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!this.right.identifier || this.right.reserved) && + this.right.id !== "." && this.right.id !== "[") { + warning("Bad operand.", this); + } + } + return this; + }; + return x; + } + + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + + function reserve(s, f) { + var x = type(s, f); + x.identifier = x.reserved = true; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === "function") { + v(this); + } + return this; + }); + } + + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.led = function (left) { + if (!w) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + } + if (s === "in" && left.id === "!") { + warning("Confusing use of '{a}'.", left, "!"); + } + if (typeof f === "function") { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function relation(s, f) { + var x = symbol(s, 100); + x.led = function (left) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + var right = expression(100); + if ((left && left.id === "NaN") || (right && right.id === "NaN")) { + warning("Use the isNaN function to compare with NaN.", this); + } else if (f) { + f.apply(this, [left, right]); + } + if (left.id === "!") { + warning("Confusing use of '{a}'.", left, "!"); + } + if (right.id === "!") { + warning("Confusing use of '{a}'.", right, "!"); + } + this.left = left; + this.right = right; + return this; + }; + return x; + } + + + function isPoorRelation(node) { + return node && + ((node.type === "(number)" && +node.value === 0) || + (node.type === "(string)" && node.value === "") || + (node.type === "null" && !option.eqnull) || + node.type === "true" || + node.type === "false" || + node.type === "undefined"); + } + + + function assignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + that.left = left; + if (predefined[left.value] === false && + scope[left.value]["(global)"] === true) { + warning("Read only.", left); + } else if (left["function"]) { + warning("'{a}' is a function.", left, left.value); + } + if (left) { + if (option.esnext && funct[left.value] === "const") { + warning("Attempting to override '{a}' which is a constant", left, left.value); + } + if (left.id === "." || left.id === "[") { + if (!left.left || left.left.value === "arguments") { + warning("Bad assignment.", that); + } + that.right = expression(19); + return that; + } else if (left.identifier && !left.reserved) { + if (funct[left.value] === "exception") { + warning("Do not assign to the exception parameter.", left); + } + that.right = expression(19); + return that; + } + if (left === syntax["function"]) { + warning( +"Expected an identifier in an assignment and instead saw a function invocation.", + token); + } + } + error("Bad assignment.", that); + }, 20); + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === "function") ? f : function (left) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", that, that.id); + } + nonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + if (left) { + if (left.id === "." || left.id === "[" || + (left.identifier && !left.reserved)) { + expression(19); + return that; + } + if (left === syntax["function"]) { + warning( +"Expected an identifier in an assignment, and instead saw a function invocation.", + token); + } + return that; + } + error("Bad assignment.", that); + }, 20); + } + + + function suffix(s) { + var x = symbol(s, 150); + x.led = function (left) { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!left.identifier || left.reserved) && + left.id !== "." && left.id !== "[") { + warning("Bad operand.", this); + } + this.left = left; + return this; + }; + return x; + } + + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + function optionalidentifier(fnparam) { + if (nexttoken.identifier) { + advance(); + if (token.reserved && !option.es5) { + // `undefined` as a function param is a common pattern to protect + // against the case when somebody does `undefined = true` and + // help with minification. More info: https://gist.github.com/315916 + if (!fnparam || token.value !== "undefined") { + warning("Expected an identifier and instead saw '{a}' (a reserved word).", + token, token.id); + } + } + return token.value; + } + } + + // fnparam means that this identifier is being defined as a function + // argument + function identifier(fnparam) { + var i = optionalidentifier(fnparam); + if (i) { + return i; + } + if (token.id === "function" && nexttoken.id === "(") { + warning("Missing name in function declaration."); + } else { + error("Expected an identifier and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (nexttoken.id !== ";" || noreach) { + return; + } + for (;;) { + t = peek(i); + if (t.reach) { + return; + } + if (t.id !== "(endline)") { + if (t.id === "function") { + if (!option.latedef) { + break; + } + warning( +"Inner functions should be listed at the top of the outer function.", t); + break; + } + warning("Unreachable '{a}' after '{b}'.", t, t.value, s); + break; + } + i += 1; + } + } + + + function statement(noindent) { + var i = indent, r, s = scope, t = nexttoken; + + if (t.id === ";") { + advance(";"); + return; + } + +// Is this a labelled statement? + + if (t.identifier && !t.reserved && peek().id === ":") { + advance(); + advance(":"); + scope = Object.create(s); + addlabel(t.value, "label"); + if (!nexttoken.labelled) { + warning("Label '{a}' on {b} statement.", + nexttoken, t.value, nexttoken.value); + } + if (jx.test(t.value + ":")) { + warning("Label '{a}' looks like a javascript url.", + t, t.value); + } + nexttoken.label = t.value; + t = nexttoken; + } + +// Parse the statement. + + if (!noindent) { + indentation(); + } + r = expression(0, true); + + // Look for the final semicolon. + if (!t.block) { + if (!option.expr && (!r || !r.exps)) { + warning("Expected an assignment or function call and instead saw an expression.", + token); + } else if (option.nonew && r.id === "(" && r.left.id === "new") { + warning("Do not use 'new' for side effects."); + } + + if (nexttoken.id === ",") { + return comma(); + } + + if (nexttoken.id !== ";") { + if (!option.asi) { + // If this is the last statement in a block that ends on + // the same line *and* option lastsemic is on, ignore the warning. + // Otherwise, complain about missing semicolon. + if (!option.lastsemic || nexttoken.id !== "}" || + nexttoken.line !== token.line) { + warningAt("Missing semicolon.", token.line, token.character); + } + } + } else { + adjacent(token, nexttoken); + advance(";"); + nonadjacent(token, nexttoken); + } + } + +// Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function statements(startLine) { + var a = [], p; + + while (!nexttoken.reach && nexttoken.id !== "(end)") { + if (nexttoken.id === ";") { + p = peek(); + if (!p || p.id !== "(") { + warning("Unnecessary semicolon."); + } + advance(";"); + } else { + a.push(statement(startLine === nexttoken.line)); + } + } + return a; + } + + + /* + * read all directives + * recognizes a simple form of asi, but always + * warns, if it is used + */ + function directives() { + var i, p, pn; + + for (;;) { + if (nexttoken.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i); + i = i + 1; + } while (pn.id === "(endline)"); + + if (pn.id !== ";") { + if (pn.id !== "(string)" && pn.id !== "(number)" && + pn.id !== "(regexp)" && pn.identifier !== true && + pn.id !== "}") { + break; + } + warning("Missing semicolon.", nexttoken); + } else { + p = pn; + } + } else if (p.id === "}") { + // directive with no other statements, warn about missing semicolon + warning("Missing semicolon.", p); + } else if (p.id !== ";") { + break; + } + + indentation(); + advance(); + if (directive[token.value]) { + warning("Unnecessary directive \"{a}\".", token, token.value); + } + + if (token.value === "use strict") { + option.newcap = true; + option.undef = true; + } + + // there's no directive negation, so always set to true + directive[token.value] = true; + + if (p.id === ";") { + advance(";"); + } + continue; + } + break; + } + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + * isfunc - true if block is a function body + */ + function block(ordinary, stmt, isfunc) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + if (!ordinary || !option.funcscope) scope = Object.create(scope); + nonadjacent(token, nexttoken); + t = nexttoken; + + if (nexttoken.id === "{") { + advance("{"); + line = token.line; + if (nexttoken.id !== "}") { + indent += option.indent; + while (!ordinary && nexttoken.from > indent) { + indent += option.indent; + } + + if (isfunc) { + m = {}; + for (d in directive) { + if (is_own(directive, d)) { + m[d] = directive[d]; + } + } + directives(); + + if (option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !directive["use strict"]) { + warning("Missing \"use strict\" statement."); + } + } + } + + a = statements(line); + + if (isfunc) { + directive = m; + } + + indent -= option.indent; + if (line !== nexttoken.line) { + indentation(); + } + } else if (line !== nexttoken.line) { + indentation(); + } + advance("}", t); + indent = old_indent; + } else if (!ordinary) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "{", nexttoken.value); + } else { + if (!stmt || option.curly) + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, "{", nexttoken.value); + + noreach = true; + indent += option.indent; + // test indentation only if statement is in new line + a = [statement(nexttoken.line === token.line)]; + indent -= option.indent; + noreach = false; + } + funct["(verb)"] = null; + if (!ordinary || !option.funcscope) scope = s; + inblock = b; + if (ordinary && option.noempty && (!a || a.length === 0)) { + warning("Empty block."); + } + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== "boolean") { + warning("Unexpected /*member '{a}'.", token, m); + } + if (typeof member[m] === "number") { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(token) { + var name = token.value, line = token.line, a = implied[name]; + if (typeof a === "function") { + a = false; + } + + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + + + // Build the syntax table by declaring the syntactic elements of the language. + + type("(number)", function () { + return this; + }); + + type("(string)", function () { + return this; + }); + + syntax["(identifier)"] = { + type: "(identifier)", + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + + if (typeof s === "function") { + // Protection against accidental inheritance. + s = undefined; + } else if (typeof s === "boolean") { + f = funct; + funct = functions[0]; + addlabel(v, "var"); + s = funct; + funct = f; + } + + // The name is in scope and defined in the current function. + if (funct === s) { + // Change 'unused' to 'var', and reject labels. + switch (funct[v]) { + case "unused": + funct[v] = "var"; + break; + case "unction": + funct[v] = "function"; + this["function"] = true; + break; + case "function": + this["function"] = true; + break; + case "label": + warning("'{a}' is a statement label.", token, v); + break; + } + } else if (funct["(global)"]) { + // The name is not defined in the function. If we are in the global + // scope, then we have an undefined variable. + // + // Operators typeof and delete do not raise runtime errors even if + // the base object of a reference is null so no need to display warning + // if we're inside of typeof or delete. + + if (option.undef && typeof predefined[v] !== "boolean") { + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === "typeof" || anonname === "delete") || + (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) { + + isundef(funct, "'{a}' is not defined.", token, v); + } + } + + note_implied(token); + } else { + // If the name is already defined in the current + // function, but not as outer, then there is a scope error. + + switch (funct[v]) { + case "closure": + case "function": + case "var": + case "unused": + warning("'{a}' used out of scope.", token, v); + break; + case "label": + warning("'{a}' is a statement label.", token, v); + break; + case "outer": + case "global": + break; + default: + // If the name is defined in an outer function, make an outer entry, + // and if it was unused, make it var. + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("'{a}' is not allowed.", token, v); + note_implied(token); + } else if (typeof s !== "object") { + // Operators typeof and delete do not raise runtime errors even + // if the base object of a reference is null so no need to + // display warning if we're inside of typeof or delete. + if (option.undef) { + // Attempting to subscript a null reference will throw an + // error, even within the typeof and delete operators + if (!(anonname === "typeof" || anonname === "delete") || + (nexttoken && + (nexttoken.value === "." || nexttoken.value === "["))) { + + isundef(funct, "'{a}' is not defined.", token, v); + } + } + funct[v] = true; + note_implied(token); + } else { + switch (s[v]) { + case "function": + case "unction": + this["function"] = true; + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "var": + case "unused": + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "label": + warning("'{a}' is a statement label.", token, v); + } + } + } + } + return this; + }, + led: function () { + error("Expected an operator and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + }; + + type("(regexp)", function () { + return this; + }); + + +// ECMAScript parser + + delim("(endline)"); + delim("(begin)"); + delim("(end)").reach = true; + delim(""); + delim("(error)").reach = true; + delim("}").reach = true; + delim(")"); + delim("]"); + delim("\"").reach = true; + delim("'").reach = true; + delim(";"); + delim(":").reach = true; + delim(","); + delim("#"); + delim("@"); + reserve("else"); + reserve("case").reach = true; + reserve("catch"); + reserve("default").reach = true; + reserve("finally"); + reservevar("arguments", function (x) { + if (directive["use strict"] && funct["(global)"]) { + warning("Strict violation.", x); + } + }); + reservevar("eval"); + reservevar("false"); + reservevar("Infinity"); + reservevar("NaN"); + reservevar("null"); + reservevar("this", function (x) { + if (directive["use strict"] && !option.validthis && ((funct["(statement)"] && + funct["(name)"].charAt(0) > "Z") || funct["(global)"])) { + warning("Possible strict violation.", x); + } + }); + reservevar("true"); + reservevar("undefined"); + assignop("=", "assign", 20); + assignop("+=", "assignadd", 20); + assignop("-=", "assignsub", 20); + assignop("*=", "assignmult", 20); + assignop("/=", "assigndiv", 20).nud = function () { + error("A regular expression literal can be confused with '/='."); + }; + assignop("%=", "assignmod", 20); + bitwiseassignop("&=", "assignbitand", 20); + bitwiseassignop("|=", "assignbitor", 20); + bitwiseassignop("^=", "assignbitxor", 20); + bitwiseassignop("<<=", "assignshiftleft", 20); + bitwiseassignop(">>=", "assignshiftright", 20); + bitwiseassignop(">>>=", "assignshiftrightunsigned", 20); + infix("?", function (left, that) { + that.left = left; + that.right = expression(10); + advance(":"); + that["else"] = expression(10); + return that; + }, 30); + + infix("||", "or", 40); + infix("&&", "and", 50); + bitwise("|", "bitor", 70); + bitwise("^", "bitxor", 80); + bitwise("&", "bitand", 90); + relation("==", function (left, right) { + var eqnull = option.eqnull && (left.value === "null" || right.value === "null"); + + if (!eqnull && option.eqeqeq) + warning("Expected '{a}' and instead saw '{b}'.", this, "===", "=="); + else if (isPoorRelation(left)) + warning("Use '{a}' to compare with '{b}'.", this, "===", left.value); + else if (isPoorRelation(right)) + warning("Use '{a}' to compare with '{b}'.", this, "===", right.value); + + return this; + }); + relation("==="); + relation("!=", function (left, right) { + var eqnull = option.eqnull && + (left.value === "null" || right.value === "null"); + + if (!eqnull && option.eqeqeq) { + warning("Expected '{a}' and instead saw '{b}'.", + this, "!==", "!="); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, "!==", left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + this, "!==", right.value); + } + return this; + }); + relation("!=="); + relation("<"); + relation(">"); + relation("<="); + relation(">="); + bitwise("<<", "shiftleft", 120); + bitwise(">>", "shiftright", 120); + bitwise(">>>", "shiftrightunsigned", 120); + infix("in", "in", 120); + infix("instanceof", "instanceof", 120); + infix("+", function (left, that) { + var right = expression(130); + if (left && right && left.id === "(string)" && right.id === "(string)") { + left.value += right.value; + left.character = right.character; + if (!option.scripturl && jx.test(left.value)) { + warning("JavaScript URL.", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix("+", "num"); + prefix("+++", function () { + warning("Confusing pluses."); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("+++", function (left) { + warning("Confusing pluses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { + warning("Confusing minuses."); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("---", function (left) { + warning("Confusing minuses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("*", "mult", 140); + infix("/", "div", 140); + infix("%", "mod", 140); + + suffix("++", "postinc"); + prefix("++", "preinc"); + syntax["++"].exps = true; + + suffix("--", "postdec"); + prefix("--", "predec"); + syntax["--"].exps = true; + prefix("delete", function () { + var p = expression(0); + if (!p || (p.id !== "." && p.id !== "[")) { + warning("Variables should not be deleted."); + } + this.first = p; + return this; + }).exps = true; + + prefix("~", function () { + if (option.bitwise) { + warning("Unexpected '{a}'.", this, "~"); + } + expression(150); + return this; + }); + + prefix("!", function () { + this.right = expression(150); + this.arity = "unary"; + if (bang[this.right.id] === true) { + warning("Confusing use of '{a}'.", this, "!"); + } + return this; + }); + prefix("typeof", "typeof"); + prefix("new", function () { + var c = expression(155), i; + if (c && c.id !== "function") { + if (c.identifier) { + c["new"] = true; + switch (c.value) { + case "Number": + case "String": + case "Boolean": + case "Math": + case "JSON": + warning("Do not use {a} as a constructor.", token, c.value); + break; + case "Function": + if (!option.evil) { + warning("The Function constructor is eval."); + } + break; + case "Date": + case "RegExp": + break; + default: + if (c.id !== "function") { + i = c.value.substr(0, 1); + if (option.newcap && (i < "A" || i > "Z")) { + warning("A constructor name should start with an uppercase letter.", + token); + } + } + } + } else { + if (c.id !== "." && c.id !== "[" && c.id !== "(") { + warning("Bad constructor.", token); + } + } + } else { + if (!option.supernew) + warning("Weird construction. Delete 'new'.", this); + } + adjacent(token, nexttoken); + if (nexttoken.id !== "(" && !option.supernew) { + warning("Missing '()' invoking a constructor.", + token, token.value); + } + this.first = c; + return this; + }); + syntax["new"].exps = true; + + prefix("void").exps = true; + + infix(".", function (left, that) { + adjacent(prevtoken, token); + nobreak(); + var m = identifier(); + if (typeof m === "string") { + countMember(m); + } + that.left = left; + that.right = m; + if (left && left.value === "arguments" && (m === "callee" || m === "caller")) { + if (option.noarg) + warning("Avoid arguments.{a}.", left, m); + else if (directive["use strict"]) + error("Strict violation."); + } else if (!option.evil && left && left.value === "document" && + (m === "write" || m === "writeln")) { + warning("document.write can be a form of eval.", left); + } + if (!option.evil && (m === "eval" || m === "execScript")) { + warning("eval is evil."); + } + return that; + }, 160, true); + + infix("(", function (left, that) { + if (prevtoken.id !== "}" && prevtoken.id !== ")") { + nobreak(prevtoken, token); + } + nospace(); + if (option.immed && !left.immed && left.id === "function") { + warning("Wrap an immediate function invocation in parentheses " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself."); + } + var n = 0, + p = []; + if (left) { + if (left.type === "(identifier)") { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if (left.value !== "Number" && left.value !== "String" && + left.value !== "Boolean" && + left.value !== "Date") { + if (left.value === "Math") { + warning("Math is not a function.", left); + } else if (option.newcap) { + warning( +"Missing 'new' prefix when invoking a constructor.", left); + } + } + } + } + } + if (nexttoken.id !== ")") { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + advance(")"); + nospace(prevtoken, token); + if (typeof left === "object") { + if (left.value === "parseInt" && n === 1) { + warning("Missing radix parameter.", left); + } + if (!option.evil) { + if (left.value === "eval" || left.value === "Function" || + left.value === "execScript") { + warning("eval is evil.", left); + } else if (p[0] && p[0].id === "(string)" && + (left.value === "setTimeout" || + left.value === "setInterval")) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + } + } + if (!left.identifier && left.id !== "." && left.id !== "[" && + left.id !== "(" && left.id !== "&&" && left.id !== "||" && + left.id !== "?") { + warning("Bad invocation.", left); + } + } + that.left = left; + return that; + }, 155, true).exps = true; + + prefix("(", function () { + nospace(); + if (nexttoken.id === "function") { + nexttoken.immed = true; + } + var v = expression(0); + advance(")", this); + nospace(prevtoken, token); + if (option.immed && v.id === "function") { + if (nexttoken.id === "(" || + (nexttoken.id === "." && (peek().value === "call" || peek().value === "apply"))) { + warning( +"Move the invocation into the parens that contain the function.", nexttoken); + } else { + warning( +"Do not wrap function literals in parens unless they are to be immediately invoked.", + this); + } + } + return v; + }); + + infix("[", function (left, that) { + nobreak(prevtoken, token); + nospace(); + var e = expression(0), s; + if (e && e.type === "(string)") { + if (!option.evil && (e.value === "eval" || e.value === "execScript")) { + warning("eval is evil.", that); + } + countMember(e.value); + if (!option.sub && ix.test(e.value)) { + s = syntax[e.value]; + if (!s || !s.reserved) { + warning("['{a}'] is better written in dot notation.", + e, e.value); + } + } + } + advance("]", that); + nospace(prevtoken, token); + that.left = left; + that.right = e; + return that; + }, 160, true); + + prefix("[", function () { + var b = token.line !== nexttoken.line; + this.first = []; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + while (nexttoken.id !== "(end)") { + while (nexttoken.id === ",") { + warning("Extra comma."); + advance(","); + } + if (nexttoken.id === "]") { + break; + } + if (b && token.line !== nexttoken.line) { + indentation(); + } + this.first.push(expression(10)); + if (nexttoken.id === ",") { + comma(); + if (nexttoken.id === "]" && !option.es5) { + warning("Extra comma.", token); + break; + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance("]", this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(true); + if (!id) { + if (nexttoken.id === "(string)") { + id = nexttoken.value; + advance(); + } else if (nexttoken.id === "(number)") { + id = nexttoken.value.toString(); + advance(); + } + } + return id; + } + + + function functionparams() { + var i, t = nexttoken, p = []; + advance("("); + nospace(); + if (nexttoken.id === ")") { + advance(")"); + return; + } + for (;;) { + i = identifier(true); + p.push(i); + addlabel(i, "unused", token); + if (nexttoken.id === ",") { + comma(); + } else { + advance(")", t); + nospace(prevtoken, token); + return p; + } + } + } + + + function doFunction(i, statement) { + var f, + oldOption = option, + oldScope = scope; + + option = Object.create(option); + scope = Object.create(scope); + + funct = { + "(name)" : i || "\"" + anonname + "\"", + "(line)" : nexttoken.line, + "(character)": nexttoken.character, + "(context)" : funct, + "(breakage)" : 0, + "(loopage)" : 0, + "(scope)" : scope, + "(statement)": statement, + "(tokens)" : {} + }; + f = funct; + token.funct = funct; + functions.push(funct); + if (i) { + addlabel(i, "function"); + } + funct["(params)"] = functionparams(); + + block(false, false, true); + scope = oldScope; + option = oldOption; + funct["(last)"] = token.line; + funct["(lastcharacter)"] = token.character; + funct = funct["(context)"]; + return f; + } + + + (function (x) { + x.nud = function () { + var b, f, i, p, t; + var props = {}; // All properties, including accessors + + function saveProperty(name, token) { + if (props[name] && is_own(props, name)) + warning("Duplicate member '{a}'.", nexttoken, i); + else + props[name] = {}; + + props[name].basic = true; + props[name].basicToken = token; + } + + function saveSetter(name, token) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].setter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].setter = true; + props[name].setterToken = token; + } + + function saveGetter(name) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].getter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].getter = true; + props[name].getterToken = token; + } + + b = token.line !== nexttoken.line; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + for (;;) { + if (nexttoken.id === "}") { + break; + } + if (b) { + indentation(); + } + if (nexttoken.value === "get" && peek().id !== ":") { + advance("get"); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveGetter(i); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f["(params)"]; + if (p) { + warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); + } + adjacent(token, nexttoken); + } else if (nexttoken.value === "set" && peek().id !== ":") { + advance("set"); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveSetter(i, nexttoken); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f["(params)"]; + if (!p || p.length !== 1) { + warning("Expected a single parameter in set {a} function.", t, i); + } + } else { + i = property_name(); + saveProperty(i, nexttoken); + if (typeof i !== "string") { + break; + } + advance(":"); + nonadjacent(token, nexttoken); + expression(10); + } + + countMember(i); + if (nexttoken.id === ",") { + comma(); + if (nexttoken.id === ",") { + warning("Extra comma.", token); + } else if (nexttoken.id === "}" && !option.es5) { + warning("Extra comma.", token); + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance("}", this); + + // Check for lonely setters if in the ES5 mode. + if (option.es5) { + for (var name in props) { + if (is_own(props, name) && props[name].setter && !props[name].getter) { + warning("Setter is defined without getter.", props[name].setterToken); + } + } + } + return this; + }; + x.fud = function () { + error("Expected to see a statement and instead saw a block.", token); + }; + }(delim("{"))); + +// This Function is called when esnext option is set to true +// it adds the `const` statement to JSHINT + + useESNextSyntax = function () { + var conststatement = stmt("const", function (prefix) { + var id, name, value; + + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct["(global)"] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, "const"); + if (prefix) { + break; + } + name = token; + this.first.push(token); + + if (nexttoken.id !== "=") { + warning("const " + + "'{a}' is initialized to 'undefined'.", token, id); + } + + if (nexttoken.id === "=") { + nonadjacent(token, nexttoken); + advance("="); + nonadjacent(token, nexttoken); + if (nexttoken.id === "undefined") { + warning("It is not necessary to initialize " + + "'{a}' to 'undefined'.", token, id); + } + if (peek(0).id === "=" && nexttoken.identifier) { + error("Constant {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + + if (nexttoken.id !== ",") { + break; + } + comma(); + } + return this; + }); + conststatement.exps = true; + }; + + var varstatement = stmt("var", function (prefix) { + // JavaScript does not have block scope. It only has function scope. So, + // declaring a variable in a block can have unexpected consequences. + var id, name, value; + + if (funct["(onevar)"] && option.onevar) { + warning("Too many var statements."); + } else if (!funct["(global)"]) { + funct["(onevar)"] = true; + } + + this.first = []; + + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + + if (option.esnext && funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + + if (funct["(global)"] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + + addlabel(id, "unused", token); + + if (prefix) { + break; + } + + name = token; + this.first.push(token); + + if (nexttoken.id === "=") { + nonadjacent(token, nexttoken); + advance("="); + nonadjacent(token, nexttoken); + if (nexttoken.id === "undefined") { + warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); + } + if (peek(0).id === "=" && nexttoken.identifier) { + error("Variable {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + if (nexttoken.id !== ",") { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + blockstmt("function", function () { + if (inblock) { + warning("Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", token); + + } + var i = identifier(); + if (option.esnext && funct[i] === "const") { + warning("const '" + i + "' has already been declared"); + } + adjacent(token, nexttoken); + addlabel(i, "unction", token); + + doFunction(i, true); + if (nexttoken.id === "(" && nexttoken.line === token.line) { + error( +"Function declarations are not invocable. Wrap the whole function invocation in parens."); + } + return this; + }); + + prefix("function", function () { + var i = optionalidentifier(); + if (i) { + adjacent(token, nexttoken); + } else { + nonadjacent(token, nexttoken); + } + doFunction(i); + if (!option.loopfunc && funct["(loopage)"]) { + warning("Don't make functions within a loop."); + } + return this; + }); + + blockstmt("if", function () { + var t = nexttoken; + advance("("); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + if (nexttoken.id === "else") { + nonadjacent(token, nexttoken); + advance("else"); + if (nexttoken.id === "if" || nexttoken.id === "switch") { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt("try", function () { + var b, e, s; + + block(false); + if (nexttoken.id === "catch") { + advance("catch"); + nonadjacent(token, nexttoken); + advance("("); + s = scope; + scope = Object.create(s); + e = nexttoken.value; + if (nexttoken.type !== "(identifier)") { + warning("Expected an identifier and instead saw '{a}'.", + nexttoken, e); + } else { + addlabel(e, "exception"); + } + advance(); + advance(")"); + block(false); + b = true; + scope = s; + } + if (nexttoken.id === "finally") { + advance("finally"); + block(false); + return; + } else if (!b) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "catch", nexttoken.value); + } + return this; + }); + + blockstmt("while", function () { + var t = nexttoken; + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + advance("("); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }).labelled = true; + + blockstmt("with", function () { + var t = nexttoken; + if (directive["use strict"]) { + error("'with' is not allowed in strict mode.", token); + } else if (!option.withstmt) { + warning("Don't use 'with'.", token); + } + + advance("("); + nonadjacent(this, t); + nospace(); + expression(0); + advance(")", t); + nospace(prevtoken, token); + block(true, true); + + return this; + }); + + blockstmt("switch", function () { + var t = nexttoken, + g = false; + funct["(breakage)"] += 1; + advance("("); + nonadjacent(this, t); + nospace(); + this.condition = expression(20); + advance(")", t); + nospace(prevtoken, token); + nonadjacent(token, nexttoken); + t = nexttoken; + advance("{"); + nonadjacent(token, nexttoken); + indent += option.indent; + this.cases = []; + for (;;) { + switch (nexttoken.id) { + case "case": + switch (funct["(verb)"]) { + case "break": + case "case": + case "continue": + case "return": + case "switch": + case "throw": + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'case'.", + token); + } + } + indentation(-option.indent); + advance("case"); + this.cases.push(expression(20)); + g = true; + advance(":"); + funct["(verb)"] = "case"; + break; + case "default": + switch (funct["(verb)"]) { + case "break": + case "continue": + case "return": + case "throw": + break; + default: + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'default'.", + token); + } + } + indentation(-option.indent); + advance("default"); + g = true; + advance(":"); + break; + case "}": + indent -= option.indent; + indentation(); + advance("}", t); + if (this.cases.length === 1 || this.condition.id === "true" || + this.condition.id === "false") { + if (!option.onecase) + warning("This 'switch' should be an 'if'.", this); + } + funct["(breakage)"] -= 1; + funct["(verb)"] = undefined; + return; + case "(end)": + error("Missing '{a}'.", nexttoken, "}"); + return; + default: + if (g) { + switch (token.id) { + case ",": + error("Each value should have its own case label."); + return; + case ":": + g = false; + statements(); + break; + default: + error("Missing ':' on a case clause.", token); + return; + } + } else { + if (token.id === ":") { + advance(":"); + error("Unexpected '{a}'.", token, ":"); + statements(); + } else { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "case", nexttoken.value); + return; + } + } + } + } + }).labelled = true; + + stmt("debugger", function () { + if (!option.debug) { + warning("All 'debugger' statements should be removed."); + } + return this; + }).exps = true; + + (function () { + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + this.first = block(true); + advance("while"); + var t = nexttoken; + nonadjacent(token, t); + advance("("); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt("for", function () { + var s, t = nexttoken; + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + advance("("); + nonadjacent(this, t); + nospace(); + if (peek(nexttoken.id === "var" ? 1 : 0).id === "in") { + if (nexttoken.id === "var") { + advance("var"); + varstatement.fud.call(varstatement, true); + } else { + switch (funct[nexttoken.value]) { + case "unused": + funct[nexttoken.value] = "var"; + break; + case "var": + break; + default: + warning("Bad for in variable '{a}'.", + nexttoken, nexttoken.value); + } + advance(); + } + advance("in"); + expression(20); + advance(")", t); + s = block(true, true); + if (option.forin && s && (s.length > 1 || typeof s[0] !== "object" || + s[0].value !== "if")) { + warning("The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", this); + } + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + } else { + if (nexttoken.id !== ";") { + if (nexttoken.id === "var") { + advance("var"); + varstatement.fud.call(varstatement); + } else { + for (;;) { + expression(0, "for"); + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + } + nolinebreak(token); + advance(";"); + if (nexttoken.id !== ";") { + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + } + nolinebreak(token); + advance(";"); + if (nexttoken.id === ";") { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, ")", ";"); + } + if (nexttoken.id !== ")") { + for (;;) { + expression(0, "for"); + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + } + }).labelled = true; + + + stmt("break", function () { + var v = nexttoken.value; + + if (funct["(breakage)"] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ";") { + if (token.line === nexttoken.line) { + if (funct[v] !== "label") { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } + reachable("break"); + return this; + }).exps = true; + + + stmt("continue", function () { + var v = nexttoken.value; + + if (funct["(breakage)"] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ";") { + if (token.line === nexttoken.line) { + if (funct[v] !== "label") { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } else if (!funct["(loopage)"]) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + reachable("continue"); + return this; + }).exps = true; + + + stmt("return", function () { + if (this.line === nexttoken.line) { + if (nexttoken.id === "(regexp)") + warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); + + if (nexttoken.id !== ";" && !nexttoken.reach) { + nonadjacent(token, nexttoken); + if (peek().value === "=" && !option.boss) { + warningAt("Did you mean to return a conditional instead of an assignment?", + token.line, token.character + 1); + } + this.first = expression(0); + } + } else if (!option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + reachable("return"); + return this; + }).exps = true; + + + stmt("throw", function () { + nolinebreak(this); + nonadjacent(token, nexttoken); + this.first = expression(20); + reachable("throw"); + return this; + }).exps = true; + +// Superfluous reserved words + + reserve("class"); + reserve("const"); + reserve("enum"); + reserve("export"); + reserve("extends"); + reserve("import"); + reserve("super"); + + reserve("let"); + reserve("yield"); + reserve("implements"); + reserve("interface"); + reserve("package"); + reserve("private"); + reserve("protected"); + reserve("public"); + reserve("static"); + + +// Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = nexttoken; + advance("{"); + if (nexttoken.id !== "}") { + for (;;) { + if (nexttoken.id === "(end)") { + error("Missing '}' to match '{' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === "}") { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ",") { + error("Unexpected comma.", nexttoken); + } else if (nexttoken.id !== "(string)") { + warning("Expected a string and instead saw {a}.", + nexttoken, nexttoken.value); + } + if (o[nexttoken.value] === true) { + warning("Duplicate key '{a}'.", + nexttoken, nexttoken.value); + } else if ((nexttoken.value === "__proto__" && + !option.proto) || (nexttoken.value === "__iterator__" && + !option.iterator)) { + warning("The '{a}' key may produce unexpected results.", + nexttoken, nexttoken.value); + } else { + o[nexttoken.value] = true; + } + advance(); + advance(":"); + jsonValue(); + if (nexttoken.id !== ",") { + break; + } + advance(","); + } + } + advance("}"); + } + + function jsonArray() { + var t = nexttoken; + advance("["); + if (nexttoken.id !== "]") { + for (;;) { + if (nexttoken.id === "(end)") { + error("Missing ']' to match '[' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === "]") { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ",") { + error("Unexpected comma.", nexttoken); + } + jsonValue(); + if (nexttoken.id !== ",") { + break; + } + advance(","); + } + } + advance("]"); + } + + switch (nexttoken.id) { + case "{": + jsonObject(); + break; + case "[": + jsonArray(); + break; + case "true": + case "false": + case "null": + case "(number)": + case "(string)": + advance(); + break; + case "-": + advance("-"); + if (token.character !== nexttoken.from) { + warning("Unexpected space after '-'.", token); + } + adjacent(token, nexttoken); + advance("(number)"); + break; + default: + error("Expected a JSON value.", nexttoken); + } + } + + + // The actual JSHINT function itself. + var itself = function (s, o, g) { + var a, i, k, x, + optionKeys, + newOptionObj = {}; + + JSHINT.errors = []; + JSHINT.undefs = []; + + predefined = Object.create(standard); + declared = Object.create(null); + combine(predefined, g || {}); + + if (!isString(s) && !Array.isArray(s)) { + errorAt("Input is neither a string nor an array of strings.", 0); + return false; + } + + if (isString(s) && /^\s*$/g.test(s)) { + errorAt("Input is an empty string.", 0); + return false; + } + + if (s.length === 0) { + errorAt("Input is an empty array.", 0); + return false; + } + + if (o) { + a = o.predef; + if (a) { + if (Array.isArray(a)) { + for (i = 0; i < a.length; i += 1) { + predefined[a[i]] = true; + } + } else if (typeof a === "object") { + k = Object.keys(a); + for (i = 0; i < k.length; i += 1) { + predefined[k[i]] = !!a[k[i]]; + } + } + } + optionKeys = Object.keys(o); + for (x = 0; x < optionKeys.length; x++) { + newOptionObj[optionKeys[x]] = o[optionKeys[x]]; + } + } + + option = newOptionObj; + + option.indent = option.indent || 4; + option.maxerr = option.maxerr || 50; + + tab = ""; + for (i = 0; i < option.indent; i += 1) { + tab += " "; + } + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + "(global)": true, + "(name)": "(global)", + "(scope)": scope, + "(breakage)": 0, + "(loopage)": 0, + "(tokens)": {} + }; + functions = [funct]; + urls = []; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + jsonmode = false; + warnings = 0; + lex.init(s); + prereg = true; + directive = {}; + + prevtoken = token = nexttoken = syntax["(begin)"]; + + // Check options + for (var name in o) { + if (is_own(o, name)) { + checkOption(name, token); + } + } + + assume(); + + // combine the passed globals after we've assumed all our options + combine(predefined, g || {}); + + //reset values + comma.first = true; + quotmark = undefined; + + try { + advance(); + switch (nexttoken.id) { + case "{": + case "[": + option.laxbreak = true; + jsonmode = true; + jsonValue(); + break; + default: + directives(); + if (directive["use strict"] && !option.globalstrict) { + warning("Use the function form of \"use strict\".", prevtoken); + } + + statements(); + } + advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined); + + var markDefined = function (name, context) { + do { + if (typeof context[name] === "string") { + // JSHINT marks unused variables as 'unused' and + // unused function declaration as 'unction'. This + // code changes such instances back 'var' and + // 'closure' so that the code in JSHINT.data() + // doesn't think they're unused. + + if (context[name] === "unused") + context[name] = "var"; + else if (context[name] === "unction") + context[name] = "closure"; + + return true; + } + + context = context["(context)"]; + } while (context); + + return false; + }; + + var clearImplied = function (name, line) { + if (!implied[name]) + return; + + var newImplied = []; + for (var i = 0; i < implied[name].length; i += 1) { + if (implied[name][i] !== line) + newImplied.push(implied[name][i]); + } + + if (newImplied.length === 0) + delete implied[name]; + else + implied[name] = newImplied; + }; + + var checkUnused = function (func, key) { + var type = func[key]; + var token = func["(tokens)"][key]; + + if (key.charAt(0) === "(") + return; + + // 'undefined' is a special case for (function (window, undefined) { ... })(); + // patterns. + + if (key === "undefined") + return; + + if (type !== "unused" && type !== "unction") + return; + + warningAt("'{a}' is defined but never used.", token.line, token.character, key); + }; + + // Check queued 'x is not defined' instances to see if they're still undefined. + for (i = 0; i < JSHINT.undefs.length; i += 1) { + k = JSHINT.undefs[i].slice(0); + + if (markDefined(k[2].value, k[0])) { + clearImplied(k[2].value, k[2].line); + } else { + warning.apply(warning, k.slice(1)); + } + } + + if (option.unused) { + functions.forEach(function (func) { + for (var key in func) { + if (is_own(func, key)) { + checkUnused(func, key); + } + } + }); + + for (var key in declared) { + if (is_own(declared, key)) { + if (!is_own(global, key)) { + warningAt("'{a}' is defined but never used.", + declared[key].line, declared[key].character, key); + } + } + } + } + } catch (e) { + if (e) { + var nt = nexttoken || {}; + JSHINT.errors.push({ + raw : e.raw, + reason : e.message, + line : e.line || nt.line, + character : e.character || nt.from + }, null); + } + } + + return JSHINT.errors.length === 0; + }; + + // Data summary. + itself.data = function () { + var data = { + functions: [], + options: option + }; + var implieds = []; + var members = []; + var unused = []; + var fu, f, i, j, n, v, globals; + + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (jsonmode) { + data.json = true; + } + + for (n in implied) { + if (is_own(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + + for (n in f) { + if (is_own(f, n) && n.charAt(0) !== "(") { + v = f[n]; + + if (v === "unction") { + v = "unused"; + } + + if (Array.isArray(fu[v])) { + fu[v].push(n); + + if (v === "unused") { + unused.push({ + name: n, + line: f["(line)"], + "function": f["(name)"] + }); + } + } + } + } + + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + + fu.name = f["(name)"]; + fu.param = f["(params)"]; + fu.line = f["(line)"]; + fu.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; + data.functions.push(fu); + } + + if (unused.length > 0) { + data.unused = unused; + } + + members = []; + for (n in member) { + if (typeof member[n] === "number") { + data.member = member; + break; + } + } + + return data; + }; + + itself.jshint = itself; + + return itself; +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports === "object" && exports) { + exports.JSHINT = JSHINT; +} diff --git a/EditorExtensions/Resources/Scripts/less-1.3.0.js b/EditorExtensions/Resources/Scripts/less-1.3.0.js new file mode 100644 index 000000000..aac4fea23 --- /dev/null +++ b/EditorExtensions/Resources/Scripts/less-1.3.0.js @@ -0,0 +1,9 @@ +// +// LESS - Leaner CSS v1.3.3 +// http://lesscss.org +// +// Copyright (c) 2009-2013, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,r,i){t&&S(t.toCSS(),r,i.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=t.contents||{},u=t.files||{},a=b(t.href,e.location.href),f=a.url,c=l&&l.getItem(f),h=l&&l.getItem(f+":timestamp"),p={css:c,timestamp:h},d;r.relativeUrls?r.rootpath?t.entryPath?d=b(r.rootpath+y(a.path,t.entryPath)).path:d=r.rootpath:d=a.path:r.rootpath?d=r.rootpath:t.entryPath?d=t.entryPath:d=a.path,x(f,t.type,function(e,l){v+=e.replace(/@import .+?;/ig,"");if(!i&&p&&l&&(new Date(l)).valueOf()===(new Date(p.timestamp)).valueOf())S(p.css,t),n(null,null,e,t,{local:!0,remaining:s},f);else try{o[f]=e,(new r.Parser({optimization:r.optimization,paths:[a.path],entryPath:t.entryPath||a.path,mime:t.type,filename:f,rootpath:d,relativeUrls:t.relativeUrls,contents:o,files:u,dumpLineNumbers:r.dumpLineNumbers})).parse(e,function(r,i){if(r)return k(r,f);try{n(r,i,e,t,{local:!1,lastModified:l,remaining:s},f),N(document.getElementById("less-error-message:"+E(f)))}catch(r){k(r,f)}})}catch(c){k(c,f)}},function(e,t){throw new Error("Couldn't load "+t+" ("+e+")")})}function E(e){return e.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r,i=t.href||"",s="less:"+(t.title||E(i));if((r=document.getElementById(s))===null){r=document.createElement("style"),r.type="text/css",t.media&&(r.media=t.media),r.id=s;var o=t&&t.nextSibling||null;(o||document.getElementsByTagName("head")[0]).parentNode.insertBefore(r,o)}if(r.styleSheet)try{r.styleSheet.cssText=e}catch(u){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(e){r.childNodes.length>0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&l){C("saving "+i+" to cache.");try{l.setItem(i,e),l.setItem(i+":timestamp",n)}catch(u){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,t){var n="less-error-message:"+E(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+(\?.*)?)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={}),t.rootpath=t.rootpath||"",t.files||(t.files={});var v=function(){},m=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r,s){i.queue.splice(i.queue.indexOf(e),1);var o=s in i.files;i.files[s]=r,t&&!i.error&&(i.error=t),n(t,r,o),i.queue.length===0&&v(i.error)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x,t);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e=x||e,e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/)||E(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)||E(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.rootpath)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=E(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},unicodeDescriptor:function(){var e;if(e=E(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a=[],f,l,c,h,p,d,v,m=o,b=s.charAt(o),w,S,C=!1;if(b!=="."&&b!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){p=[];while(c=E(this.expression)){h=null,S=c;if(c.value.length==1){var k=c.value[0];k instanceof i.Variable&&E(":")&&(p.length>0&&(d&&T("Cannot mix ; and , as delimiter types"),v=!0),S=x(this.expression),h=w=k.name)}p.push(S),a.push({name:h,value:S});if(E(","))continue;if(E(";")||d)v&&T("Cannot mix ; and , as delimiter types"),d=!0,p.length>1&&(S=new i.Value(p)),u.push({name:w,value:S}),w=null,p=[],v=!1}x(")")}f=d?u:a,E(this.important)&&(C=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,f,m,t.filename,C);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*\}/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{E(this.comment);if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0,t.push({variadic:!0});break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(",")||E(";"));E(")")||(l=o,y()),E(this.comment),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^()@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable)||E(this.selector))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),E(")")?new i.Selector([new i.Element("",e,o)]):null;while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n)},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,n,r=o;g();var s=E(/^@import(?:-(once))?\s+/);if(s&&(e=E(this.entities.quoted)||E(this.entities.url))){n=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,n,s[1]==="once",r,t.rootpath)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=E(this["import"])||E(this.media))return n;g(),e=E(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(E(/^[^{]+/)||"").trim());if(c){if(r=E(this.block))return new i.Directive(e,r)}else if((n=p?E(this.expression):E(this.entity))&&E(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=A(o,s,t)),d}y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/[*\/]/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),w({href:e,title:e,type:r.mime,contents:r.contents,files:r.files,rootpath:r.rootpath,entryPath:r.entryPath,relativeUrls:r.relativeUrls},function(e,i,s,o,u,a){e&&typeof r.errback=="function"?r.errback.call(null,a,t,n,r):n.call(null,e,i,a)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t,n){return t instanceof e.Dimension&&t.unit=="%"?parseFloat(t.value*n/100):r(t)}function r(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function i(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,i,s,o){var u=[t,i,s].map(function(e){return n(e,256)});return o=r(o),new e.Color(u,o)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=r(e)%360/360,t=r(t),n=r(n),i=r(i);var s=n<=.5?n*(t+1):n+t-n*t,o=n*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,i){e=r(e)%360/360*360,t=r(t),n=r(n),i=r(i);var s,o;s=Math.floor(e/60%6),o=e/60-s;var u=[n,n*(1-t),n*(1-o*t),n*(1-(1-o)*t)],a=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(u[a[s][0]]*255,u[a[s][1]]*255,u[a[s][2]]*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var r=e.toHSL();return r.s+=n.value/100,r.s=i(r.s),t(r)},desaturate:function(e,n){var r=e.toHSL();return r.s-=n.value/100,r.s=i(r.s),t(r)},lighten:function(e,n){var r=e.toHSL();return r.l+=n.value/100,r.l=i(r.l),t(r)},darken:function(e,n){var r=e.toHSL();return r.l-=n.value/100,r.l=i(r.l),t(r)},fadein:function(e,n){var r=e.toHSL();return r.a+=n.value/100,r.a=i(r.a),t(r)},fadeout:function(e,n){var r=e.toHSL();return r.a-=n.value/100,r.a=i(r.a),t(r)},fade:function(e,n){var r=e.toHSL();return r.a=n.value/100,r.a=i(r.a),t(r)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return e.rgb?(typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s,o){var u=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),this.rootpath=o,t instanceof e.Quoted?this.path=/(\.[a-z]*$)|([\?;].*)$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css([\?;].*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&u.once&&(u.skip=r),u.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?(typeof this._path.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(this._path.value)&&(this._path.value=this.rootpath+this._path.value),"@import "+this._path.toCSS()+t+";\n"):""},eval:function(t){var n,r=this.features&&this.features.eval(t);return this.skip?[]:this.css?this:(n=new e.Ruleset([],this.root.rules.slice(0)),n.evalImports(t),this.features?new e.Media(n.rules,this.features.value):n.rules)}}}(n("../tree")),function(e){e.JavaScript=function(e,t,n){this.escaped=n,this.expression=e,this.index=t},e.JavaScript.prototype={eval:function(t){var n,r=this,i={},s=this.expression.replace(/@\{([\w-]+)\}/g,function(n,i){return e.jsify((new e.Variable("@"+i,r.index)).eval(t))});try{s=new Function("return ("+s+")")}catch(o){throw{message:"JavaScript evaluation error: `"+s+"`",index:this.index}}for(var u in t.frames[0].variables())i[u.slice(1)]={value:t.frames[0].variables()[u].value,toJS:function(){return this.value.eval(t).toCSS()}};try{n=s.call(i)}catch(o){throw{message:"JavaScript evaluation error: '"+o.name+": "+o.message+"'",index:this.index}}return typeof n=="string"?new e.Quoted('"'+n+'"',n,this.escaped,this.index):Array.isArray(n)?new e.Anonymous(n.join(", ")):new e.Anonymous(n)}}}(n("../tree")),function(e){e.Keyword=function(e){this.value=e},e.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(t){return t instanceof e.Keyword?t.value===this.value?0:1:-1}},e.True=new e.Keyword("true"),e.False=new e.Keyword("false")}(n("../tree")),function(e){e.Media=function(t,n){var r=this.emptySelectors();this.features=new e.Value(n),this.ruleset=new e.Ruleset(r,t),this.ruleset.allowImports=!0},e.Media.prototype={toCSS:function(e,t){var n=this.features.toCSS(t);return this.ruleset.root=e.length===0||e[0].multiMedia,"@media "+n+(t.compress?"{":" {\n ")+this.ruleset.toCSS(e,t).trim().replace(/\n/g,"\n ")+(t.compress?"}":"\n}\n")},eval:function(t){t.mediaBlocks||(t.mediaBlocks=[],t.mediaPath=[]);var n=new e.Media([],[]);return this.debugInfo&&(this.ruleset.debugInfo=this.debugInfo,n.debugInfo=this.debugInfo),n.features=this.features.eval(t),t.mediaPath.push(n),t.mediaBlocks.push(n),t.frames.unshift(this.ruleset),n.ruleset=this.ruleset.eval(t),t.frames.shift(),t.mediaPath.pop(),t.mediaPath.length===0?n.evalTop(t):n.evalNested(t)},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)},emptySelectors:function(){var t=new e.Element("","&",0);return[new e.Selector([t])]},evalTop:function(t){var n=this;if(t.mediaBlocks.length>1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d + + + + + // vank: updated to LESS 1.3.1 + + diff --git a/EditorExtensions/Resources/alphabatize.png b/EditorExtensions/Resources/alphabatize.png new file mode 100644 index 0000000000000000000000000000000000000000..4435fd344b064b54e901f9d00211e9ce3a33bde1 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`M?GB}Lo7}wCrE@OoPX*4-%%p+ z&8M~1|Gk&#{hWWx^mqODO}+_b9-g1;*Rbi_tmIh3FkjWc*+9j?tntGn-D-mvM&{%C z_ZfDxtUhUM{^nPI4!4=9h3R3FT+1S<9BZ>yh4ki_j=S$2fE2?b$A=6?JTA)Zyn6Wu zeUCqlnXunc@9;{=6sr?yF>zg4bC~+f1o|@PG9FVf^Lu|mrXj{>;@brWT=-MiB7$0f z3QD)BrV6lav|Surpq^R7uuQV$V!Z literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/cross_browser.png b/EditorExtensions/Resources/cross_browser.png new file mode 100644 index 0000000000000000000000000000000000000000..fa736d87dc069ca982596c7d9409feb7fe049727 GIT binary patch literal 674 zcmV;T0$u%yP)?}w{K(R*?9gx0uW2-kEdGoS6{-2tT9QY$BJ-As&xoZ*LEoOa_;imw0-5 z!q41)inq45U^bhvzP^r=lM`gKS!lIdjE;_CW@ZL!YilT%%jgI&KR=Jb!9gr9FEjJS z#RUR^01O5LMn*<3Fff3=zCH{O599dw7~cRwp%6qO5vHc55RFE0baaG;g$2yb&B0_c z!DuwXVzDrYTrS7h*chIlpTF3pQYlm_757cdq@q|XGD{>9fz@iomDna?N zSgc)4a=N;@u)V#FLZN__l@;i8IvgGz;^5!_$z&1^hl7jH&d#v2v%~7VUT+(K676<7 z8%7HH`}@(|-HoB4A(m>h+4!9RDwPWE?(R@3l^C1>?(gpr3(j*}36@$i!U8g{?GZn#R6{ zQnu&3@6Q=Jr*pn~`}H;7v;3a-8O`l>qrbo3@ALV(1_lOfy}i9IkH_P(+wCrk#o{uV zOs=-JHg{7~Q%^%fLr-mOZBJ!or44{4qYV!a2Wo0+u)4bHdwqSSx3{-H=K1-V9v&X( z`udtqPEIHk3QA;ytueX z+1c6O1cQTv=9`-v@CT@_u2v*PMMV&00iT_nQ6LZ?woZF{do(*cOFEtIn}F|c5j7!M zUtdRgc{$S3(jc})S-@VemzbQkx3_6xVuG@=vc3trySuG%g0iwQ1x`pvz}?-QArgtu z!omV^KD4{LOW|;sHa0e3vq^@(37k%+Eq-UYBPTAZrn$K}aKIQE8j>x6T_|8jM+f*D zHI0pp(0EmL0Y{@z1(x&i@$tvl*ckqPE-o&>jxahpip$GOm6gVOcErK_0iB|l`T5WoC`F;Gt1D5a{r!CtZ^Y>L`xODZQ|J5pJIrP? zCMPFhG#XJ+QGtw%3~1ai_sh!*@&1+a%*>2uWo5#V>6lmI2Xk&zLMkB_VK@bD0+sj1MU+oC)_ zKTixI{tuXzmX=iFu~-beW;{JTDHjC=1?cSTgw<+AQc@C1m~0SXc-aLrF;q5)%_Y%kZxe0xpvRi3^9r0li+2y1F`)mX;zV yCFRq>{|LlIad9#7^76pWkeQjO?i?Qh%lraW#=?l!JxY)O0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0YgbdK~y+Tjg!4j z!!QuX^9H;EPk?v?lsywGYLL=MiUz`8-|gJ&A~ z>t`uGNL5vPUL`nR-!EkA@X|zX&(qtvy;e~acQt6c0U|QaNPc?zHi!8Kgc1}bNg`nw znlIO?K}QyX1Bb_tuPe?Ev$@1^EWO@|ES_J?mvx$^V%7K*U?W--MKT#rWSRZi$r`(= z3CID_H3ynZBoBud4QB;mXWyu2xK(fgqpOjXkF#C_djrre4-gKxPW}F%0qYD<*$Q;m z_6q+g_;~-cIdB2kHz~;4RZzf66@2YUw^3*6t$hH%+Xw4j8XZUHt?k53PgT{BFyCAF Y15}ePf)0cJrT_o{07*qoM6N<$g4gA-p#T5? literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/graph_atdir.png b/EditorExtensions/Resources/graph_atdir.png new file mode 100644 index 0000000000000000000000000000000000000000..d47ccfca483c28fd28bf7bcab9956dfefe96febf GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`8J;eVAr_~TfBgS%&#Wr3`oUIF z%m0oubeJ8a_^*0285*`dxZ<-$vBFe1mqByZ#l!6D8Gjg@5ol^;f0VqL(I-SfD4W4EPC>+*XG&T+!~07&-}Xht2m|e8@O1Ta JS?83{1OQQ4GxPue literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/graph_class.png b/EditorExtensions/Resources/graph_class.png new file mode 100644 index 0000000000000000000000000000000000000000..d06f787ce6ab31130b62bb4203d3d4e1d198bf53 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`;hrvzAr_~TfBgS%lafY-( z_VcIzKV_aiC~-vX7Q>8VEB4v`*S}lIc1*#{tocJ$OXp#p1de&k$1HdoG#$1}s`+hU sZ253N(xF5_Xz|1q8Ap~EN<3v{n8kLsd)JFnQJ@tJp00i_>zopr0Crq7h5!Hn literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/graph_id.png b/EditorExtensions/Resources/graph_id.png new file mode 100644 index 0000000000000000000000000000000000000000..3f133ebc1f76f136e540544c5cd0b877fd5868ff GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`(>z@qLo7}w|M>sko>_H9VuAFA z9jWjCi`@P9UtyLCvtQosZ~M>WzWXnk8vXD7{(me!%|8?ho7jBL-2AZrO6s})n}6s3 z`~TsevJ6Okf=wK=gI`{Mbl+8m2^Jpn7BHTd+xu_-uJ;OE;tn+vECSgMJzboA{yKW;eBsfSMURUHx3vIVCg! E0N_O+egFUf literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/no_skull.png b/EditorExtensions/Resources/no_skull.png new file mode 100644 index 0000000000000000000000000000000000000000..5bf4b6ae5cc40d1e3916fc7061d23dc694c86739 GIT binary patch literal 872 zcmV-u1DE`XP)6n7f*_Jb>f4q?r!tnZ| zB*ohwjYtqdB?6J63sJwiDAb=6x-UGv-^ocqAG~}Yhwpj5=Xu}fKxSqpgeom94Qgv^ zVQg$nJu@?7o1dQ#;J)Pd`#Ul+GPLl&RaI35<>lpEm6Vh~b91v|b#--VYisMr#>NJ_ zwzfv<$nADN;Pd&hK7i>i0P6{X)9D0%nL=0!rj8SS*&go}Qkcfk1$roSbB*r>EJ8i3!%lFu}jT zsV54ALLo#)M{}i6C?GL0vDIWUy-};xH?y;|?-dspziXiBrv&T;`0@{!tn~DB$ji$E zgTcV5C@d_j%g@h$T~t&QTU}j!t3fK=C*bP>K`=)maffgeMg2Jp4h}+ZZ!c#w*>-0CQZ{&T3Sk!f>Nmj=ho{fx*yh0R1LP7%Mt<(X z*D>NR5a8nRc=}VgbUGb`g@pmMw6w_l8qK5QkQ_L5y33e@ag6w@_V)ID+#e?;C2bZI z6x_$VR*%PXc4}(MXtUXB2oJHK>@XM(yJ-5T*KXg#6z*BA)+gAcar8(UE02hXsLajH zy@RUu@SoZD`FtNSBX3dBMJ@~YCk8T-lfR>+c?4DAr>Ib1$mq!IkCzJ5+Kslq;$6>4 y8gceI1eW2E4y7zqgg_#Z{F7cBsR=g)IsXQWG94Mv#q7xd0000;2}e>Y15`gR%l{{7FNi! z!cZ#|TA@gVLiJsqdWL5kc{S%w<^N%Y94i!Cq1*~SD~KqAPsLHJ;{3y_;X1H! z;~Adi9o{7lgCOFrRB4fBLyv)9J>hRF%&su)QD6Ec_gpoSrJoag+J4li1q8&*S88#V1;T5bn4V8@%i&- zk!~Q*-=g*&ubO&XiEQ%P));L|r_(xA+&z(CbzJLEN zG6j@{GAU9hW7AY8gCVMhMc9)kPei7IvZ;k;4P{P6A{wYwubk6YS67Qn2W2$YFO)qs z)-9ViZ~o27%qlW==+GhY_3KxWEugHFS&_2JTC@C??4AJ`8_3YnqenAJUPK~SD7zwM zJ#~^4GPZ2l(m?l&x>#^7}+GiBN6m!_Ei)2b&6VnS1||AhN*2VQ)0DFsfyc*Ug@T!IwX@9 zeQx3L+9pFwtnDdo zTKc3-z(aH}>?yHX9+hiOC04U^G%lqIK7IP6EsvKi-Cx64dIt^((v;~THdIzt>R!?# z7FV4c82i(~2A=Am4%OP^MpUYLoXJ9g|4)2B}tKYsiO`0d`k zdt%nCSz_?u!D7&$L1NORNir>+AO0sjdx#d)vD(SiI2K$Mo2h9#PK0C^;xZr!@c?Q9yv*Qrw{ z8JB&f{O`a2$~5iMc|Pal*D&MaI01jEb5)d$t%pe0WeonEJJD-CEqddDHK`*RNlTjvYISOP4M=CS=~c zd2%m@29-E}{`>$!XyHSK43U*U>({_$(Ys0Z zmEW^5v_ppuL5DFDq+3{6DAUz}^kRY1ZIy>3#22ciL`n!5K5*cGtQZPw62iDYapJ_F z@2*_AQcRsX)iEJp;J|@W2JkL%GnANwAaB~VX;VA2K@RG0aOB7l(XU@WzjTm4T1G&a zCIsS$SBD7`Cd5=v)HQV;%J$L74S{YFf*PcNoIQJ14p}DnjyQVs=us;t+#a&D>{7$l z@4(j=s*Hdw}DAq0#XHA>EI%mOiNj2}O~ zmJ}S!5XKM^$^kDFApj4LhYueH5OU$d1v!JV+jM5moGIqcoh$!ex^$_W>f*X%PM?v1 z@g#&{RuR%77$KYwB2PhZn-F?L^XAR{3iR>gM=@>MG}%)if$@3l*s)<9DZ&wA!X%`) zxLC}YGbiAg%a<=pqELxz8OL-vH#b-G>C;F4#souaEcl)D>>-vV0(Gqj$qPmZhqlNm zX(B;OeDvs%-&!JBV2Vp6F?;&ze9r&Qt0WhlBUxt3`PjY8`aLwJ;Wc>wIZa* zBP0z7@rJAv8?urj)Uz3N33b<|y|-`QmQ&PQw{FSLOf6A|Jbn5!;8}JYS*HZmsUi=i zdJhNQCm!MpHhtECXLjz~={KuFbrNiWtkboJXcyCUO?zEi7|xh6L#oA1RXPj7RjXD7 zJlns2f2mrjOGWN<4WfYxhC&Z()TU}MrsHveJ;buX zI8u>ELI}_Eo*57E(i61&vJ(Oke5W_FCV~*BCful<98k>B%4lsSF!u1hwoNm|M4O5Y z;?=8Hj#cDN3E}yYk`lk~sBq*L>DUQj=)~cI;Zr-7CxQ^CP7b&M{ftJiBP8h!_D!Lz z2e8O#+d9J)!xrv88ctN?!3ePjW=lM;E8YaQ7A?QbcW4;cMV?a+LF2NfWNaa^yGNy(!lWQ}pW^SFCRpuRF79Ctaz)TVHr+36(a@{ZvQuf9DY9yte_l_D5frK74 z?j6Qow-7fDhH;_G%D9~M9>JAI>%A+FeqDK#^t*F8 z7+CidTqCpXQZVHXDtkuCTx6`S%`3^`Yx7F1Aw2c2V>K_9G&kXA;-b&ESTes}DnqSP zvf=7gU&>#-YFp7~^5w+;rOoBU1}XKGLNcwd@5Z=fyS_U=?XK?*qPj2B7u;jYOqUDp z$!o@3a38|*c$vZ>5Giabx)_ls@}`8gP-|-vI@GS4}t|1fj&ZSC~R@1EQ4NR07*qoM6N<$fsz0&Y5%I#_{9N{~zrZKPYjety5XL=Q@MHx^?T= zl2Z)#uqjkCMhbHXKV>cP-C^*SS7DmJHM85{1ck#5GCT~<&+GO#$OO~_EoAU?^>bP0 Hl+XkKjCMOs literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/numbers.png b/EditorExtensions/Resources/numbers.png new file mode 100644 index 0000000000000000000000000000000000000000..e27ed1b19bdc29455ddfa2e1aa678bb0482eca35 GIT binary patch literal 415 zcmV;Q0bu@#P)AHIP0004INklvrpj(#=9Xw?1HhI%mlcGI+}3uj_IH z!W74ny{Pg95AWeC86D|KG7K6ts99rR4=gNwF|Y=XKn0YFBa1e2!+!);mVQ$UwUhWX z_%X26huZ?!0zbfw;(LMoZ0TPC2Vkanruf})5*>U4@TdVR9RSSbS=REI^3x0c2sjCX zsW;_qwUN&o0Es?!4LmrmfTl9w+LjA|Otb&lCjeJQ=}3A6kgKhU|yZFs*JMIbcC%Mo+1PQscQEgxU=+5)Mr-9Un`%7auIU{aK1gC zI?Vh6_y$IbN6PISZ^J)B}=H{B3%dMQc2y(y~HHf--kfAB4yxdg{EM@0<_5?;H~8zXH!cjVRR)du4|A zO3j*A32o6man}?@0-YqsaYvyfF2`0?^r6@7Ubvz~q2uTNoVbjQVvEZ)jELN!BuprFC+|e^Yh62-#V#`dQ z++a`jW^5U#ikEuj7Xe-ZK#Kr4vd=i-IgC?|Cd|3L#fW1eM%|MD5gG5AePHehMc0>; z?{79nCT<#N3z|jjxHSt)x(ZhKYY@T-utT~L>)Zo9trczb3JluCV>XD1nGRQU4lwZO zhZu@yDIbzME<|pc97{13Is{IE5;zHVP%B8@x544xKm@f4dh1HmQN`%vJK*`fU8o&o zA#chJ(zOyCZc=t{8rax4SqtPw16^1TdqF++2GqccTLKO<7pe4O6i~z{cP7xLXCiNe zK!8aG`fSn)nL?Is-9nbqu-_xNVZ}*!9b~=^Y`-h8by35Aj}qCmL}YSVD7#EW+INi3e%!BN#9jHaZk0gQ=_{UIr36!k&V`i94 zqZk@8!eB6>?v@@NsqSkeu6@SFq8*c|)76B<$0yXu* z>uwMPK~t;MRS(8_Tllj<9-4sX*?2ui7ev)0000IS1yvfHPFW8K$Tp-ln2cr_dA~&S@x)r6SHtP9hjy|70oi z@<+Q#BDK+vM2aAypeRwOKm97HAALRFR|{gja5#sL^FHr$&hvbvR;$Sq85tSW+S*F< z^Yh}>)m6RI>2x4(jf{+3&B@7;(*I6FLj%>+)NoN*SxG%TJ;L4H-7S~P_5I-BfZ5yI zW8>$*z`#R4KR<~VKzDaHb#--7XJ;pMbac?n%#6kDb~8IWJIwa>HWzHYv9ZCVrlwAN z0VtJ9%FWFsP~=8vYHC^^9UcAQa5$Kyr6p!%WrbN>Tx8nY+rNrLqT5~o0RaIN9UaYu zP$;C7loXRjqxm2fi)Zul^6pktR2<7>GFyCnyc_N9UI3YynN(O5rFH@28yn-s2n-A)fk1E>KzFd0 z!{+8@S9W%`U9Z=_M859t@2}?ZcmzO}DPbfco6SacyPaDg8aR-|#Kd!q7Il%`No;Jau&Ai$!QkNFv&qTHefZ-rAt6CF zG&Ce$UteE<^bDWRuVWdLTrQ{l{QR5s_4Q`}J2somU8rMl_y{ckuV}Se1*EJtnM_9* z?V_A*?oM#=NI%o8jC jeDIHZA*lvQ$kx9AsuvJ9qFdbs00000NkvXXu0mjfanGFC literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/sort.png b/EditorExtensions/Resources/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..0a9fcba4cd0f02e63b7e91c50544c12552f1f9a4 GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!KI!qjv*HQXD2!G9Wvly`Mj;BQM>;Y^MoIq z@lA4*vM);U-dd7*HBMlnj%r@np0Zh&;@3vKepGmC&XJcz-5q}~hI;LM{f^_p?niev zOchzeKH;>bzMOWs@BM2`m7VeDEuDT}oik;JU%&r-HU;*C%bZS}3>&VSi+}S=60>l4 zBe2~%OO=6Vb@_n;%}v%m?H8=ib0>URa<-W1<0<$5OW)f%?)j8?;5=)-`^TEAM-xsJ Q0v*iY>FVdQ&MBb@0JXSkLI3~& literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/vsgallery.png b/EditorExtensions/Resources/vsgallery.png new file mode 100644 index 0000000000000000000000000000000000000000..2750e25c9c482136f7b82df7bfc122b2086a29a5 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|j-D=#AsXkCcepAgFeIt-FibqG z<>$b>>E@LS4fns^FnzG8*M!%?w)Z}p&Ot9zUKMN3`D`(aUO7IK=a{Tm(x}3~pw>Ra Uq2Ju)Gte*wPgg&ebxsLQ0F1;WD*ylh literal 0 HcmV?d00001 diff --git a/EditorExtensions/Resources/warning.png b/EditorExtensions/Resources/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..7e24d3f83526e349c95f9516a3dc835b613d9795 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`xt=bLAr_~XPH^NpV8Frh+3f!V z=Gv7p&3@IYCumW8y}>~pLx=GIE%4# QKhR"); + + public Stream GetModuleStream(string name) + { + if (name.Contains("vendor") && BrowserStore.Browsers.Count > 0) + { + if (!BrowserStore.Browsers.Contains("IE") && name.Contains("-ms.")) + { + return new MemoryStream(_emptyModule); + } + + if (!BrowserStore.Browsers.Contains("FF") && name.Contains("-moz.")) + { + return new MemoryStream(_emptyModule); + } + + if (!BrowserStore.Browsers.Contains("O") && name.Contains("-o.")) + { + return new MemoryStream(_emptyModule); + } + + if (!BrowserStore.Browsers.Contains("C") && !BrowserStore.Browsers.Contains("S") && name.Contains("-webkit.")) + { + return new MemoryStream(_emptyModule); + } + } + + return null; + } + } +} diff --git a/EditorExtensions/Schemas/Browsers/BrowserSelector.xaml b/EditorExtensions/Schemas/Browsers/BrowserSelector.xaml new file mode 100644 index 000000000..f443e1b1a --- /dev/null +++ b/EditorExtensions/Schemas/Browsers/BrowserSelector.xaml @@ -0,0 +1,19 @@ + + + + +