예제 #1
0
        /// <summary>
        /// Add a "baseHref" property in .angular-cli.json.
        /// </summary>
        /// <param name="projectDirectory"></param>
        /// <returns></returns>
        private bool ModifyAngularCliJsonFile(string projectDirectory)
        {
            const string BaseHrefPropertyName = "baseHref";
            const string BaseHrefApi          = "/";
            const string BaseHrefMvc          = "/ng/";

            var projectIsMvc          = Directory.Exists(Path.Combine(projectDirectory, "Views"));
            var projectIsRazorPages   = Directory.Exists(Path.Combine(projectDirectory, "Pages"));
            var baseHrefPropertyValue = (projectIsMvc || projectIsRazorPages) ? BaseHrefMvc : BaseHrefApi;

            var filePath = Path.Combine(projectDirectory, NgWizardHelper.AngularCliJsonFileName);

            if (File.Exists(filePath))
            {
                var rootObj = JObject.Parse(File.ReadAllText(filePath));
                var apps    = (JArray)rootObj["apps"];
                if ((apps != null) && apps.Any())
                {
                    var app = (JObject)apps[0];
                    if (app[BaseHrefPropertyName] == null)
                    {
                        var knownProperty = app.Property("outDir") ?? app.Property("root");
                        if (knownProperty != null)
                        {
                            var baseHrefProperty = new JProperty(BaseHrefPropertyName, baseHrefPropertyValue);
                            knownProperty.AddAfterSelf(baseHrefProperty);

                            NgWizardHelper.RewriteFile(filePath, rootObj.ToString());
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #2
0
        /// <summary>
        /// Add a "baseHref" property in angular.json (ver.6)
        /// </summary>
        /// <param name="projectDirectory"></param>
        /// <param name="jsonFileName"></param>
        /// <param name="projectName"></param>
        /// <returns></returns>
        private bool ModifyAngularJsonFile(string projectDirectory, string jsonFileName, string projectName)
        {
            const string BaseHrefPropertyName = "baseHref";
            const string BaseHrefApi          = "/";
            const string BaseHrefMvc          = "/ng/";

            var projectIsMvc          = Directory.Exists(Path.Combine(projectDirectory, "Views"));
            var projectIsRazorPages   = Directory.Exists(Path.Combine(projectDirectory, "Pages"));
            var baseHrefPropertyValue = (projectIsMvc || projectIsRazorPages) ? BaseHrefMvc : BaseHrefApi;

            var filePath = Path.Combine(projectDirectory, jsonFileName);

            if (File.Exists(filePath))
            {
                var rootObj = JObject.Parse(File.ReadAllText(filePath));

                var parentObj = FindInsertPlace2(rootObj, projectName);
                if (parentObj != null)
                {
                    if (parentObj[BaseHrefPropertyName] == null)
                    {
                        var baseHrefProperty = new JProperty(BaseHrefPropertyName, baseHrefPropertyValue);
                        parentObj.Add(baseHrefProperty);

                        NgWizardHelper.RewriteFile(filePath, rootObj.ToString());
                        return(true);
                    }
                }
            }
            return(false);
        }
        public void RunStarted(object automationObject, Dictionary <string, string> replacementsDictionary,
                               WizardRunKind runKind, object[] customParams)
        {
            string destinationDirectory = null;
            string solutionDirectory    = null;

            try
            {
                replacementsDictionary.TryGetValue("$safeprojectname$", out string projectName);
                replacementsDictionary.TryGetValue("$destinationdirectory$", out destinationDirectory);
                replacementsDictionary.TryGetValue("$solutiondirectory$", out solutionDirectory);

                // Test if @angular/cli is installed globally.
                this.isNgFound = NgWizardHelper.IsNgFound(solutionDirectory);

                // Display the wizard to the user.
                var viewModel  = new NgProjectWizardViewModel(projectName, this.isNgFound);
                var mainWindow = new NgProjectWizardWindow(viewModel);
                var accepted   = mainWindow.ShowDialog().GetValueOrDefault();

                this.skipNpmInstall = viewModel.SkipNpmInstall;
                // If package.json is included in the project, the npm package manager automatically starts installing packages after project creation.
                replacementsDictionary.Add("$includepackagejson$", this.skipNpmInstall ? String.Empty : includePackageJsonElement);

                this.addRouting = viewModel.AddRouting;

                if (!accepted)
                {
                    throw new WizardCancelledException("The wizard has been cancelled by the user.");
                }
            }
            catch
            {
                DateTime projectDirCreationTime = DateTime.MinValue;
                if (Directory.Exists(destinationDirectory))
                {
                    projectDirCreationTime = Directory.GetCreationTimeUtc(destinationDirectory);
                    Directory.Delete(destinationDirectory, true);
                }
                if (Directory.Exists(solutionDirectory))
                {
                    // The solution could exist before the template started.
                    // This is a poor man's method of deciding whether the solution dir was created at about the same time as the project dir.
                    var solutionDirCreationTime = Directory.GetCreationTimeUtc(solutionDirectory);
                    if (Math.Abs((projectDirCreationTime - solutionDirCreationTime).TotalSeconds) < 5)
                    {
                        Directory.Delete(solutionDirectory, true);
                    }
                }
                throw;
            }
        }
예제 #4
0
        public void RunStarted(object automationObject, Dictionary <string, string> replacementsDictionary,
                               WizardRunKind runKind, object[] customParams)
        {
            replacementsDictionary.TryGetValue("$solutiondirectory$", out string solutionDirectory);

            var settings = new NgItemWizardViewModel.NgItemWizardSettings();

            // Test if @angular/cli is installed globally.
            this.isNgFound     = NgWizardHelper.IsNgFound(solutionDirectory);
            settings.IsNgFound = this.isNgFound;

            var dte            = (DTE)automationObject;
            var activeProjects = (Array)dte.ActiveSolutionProjects;

            if (activeProjects.Length > 0)
            {
                var project = (Project)activeProjects.GetValue(0);

                // The NuGet package needs netstandard2.0. We don't support ASP.NET Core 1.x projects.
                settings.IsAspNetCore2 = NgWizardHelper.IsAspNetCore2(project);
                // Look for an existing .angular-cli.json indicating there has been already an Angular CLI app created.
                settings.IsAngularCliJsonFound = NgWizardHelper.FindFileInRootDir(project, NgWizardHelper.AngularCliJsonFileName);
                // Test if a package.json exists.
                settings.IsOldPackageJsonFound = NgWizardHelper.FindFileInRootDir(project, NgWizardHelper.PackageJsonFileName, out string packageJsonFilePath);
                // Test if an entry for "@angular/core" exists in package.json.
                settings.IsNpmAngularFound = NgWizardHelper.IsNpmAngularFound(packageJsonFilePath);

                // Automatic installation is disabled if .gitignore or package.json or tsconfig.json or Startup.cs is opened in an editor window.
                settings.IsGitignoreOpened    = NgWizardHelper.IsFileOpened(project, NgWizardHelper.GitignoreFileName);
                settings.IsPackageJsonOpened  = NgWizardHelper.IsFileOpened(project, NgWizardHelper.PackageJsonFileName);
                settings.IsStartupCsOpened    = NgWizardHelper.IsFileOpened(project, NgWizardHelper.StartupCsFileName);
                settings.IsTsconfigJsonOpened = NgWizardHelper.IsFileOpened(project, NgWizardHelper.TsconfigJsonFileName);
            }

            // Display the wizard to the user.
            var viewModel  = new NgItemWizardViewModel(settings);
            var mainWindow = new NgItemWizardWindow(viewModel);
            var accepted   = mainWindow.ShowDialog().GetValueOrDefault();

            this.installAutomatically = viewModel.InstallAutomatically;

            if (!accepted)
            {
                throw new WizardCancelledException("The wizard has been cancelled by the user.");
            }
        }
예제 #5
0
        // This method is only called for item templates, not for project templates.
        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
            var project = projectItem.ContainingProject;

            if (this.installAutomatically && (project != null))
            {
                string ngNewOutput            = String.Empty;
                bool?  ngNewSucceeded         = null;
                bool?  mergedPackageJsonFiles = null;
                bool?  modifiedAngularCliJson = null;
                bool?  modifiedStartupSc      = null;
                bool?  mergedGitignoreFiles   = null;
                bool   renamedTsconfigJson    = false;

                var projectDirectory = Path.GetDirectoryName(project.FullName);
                if (Directory.Exists(projectDirectory))
                {
                    // Starting from ver.1.4, the CLI creates a ".gitignore" file even if the "--ignore-git" option is specified. So "ng new --ignore-git" fails if there is an existing .gitignore in the directory.
                    // +https://github.com/angular/angular-cli/issues/7686
                    RenameFileIfExists(projectDirectory, NgWizardHelper.GitignoreFileName, NgWizardHelper.GitignoreTempFileName);

                    RenameFileIfExists(projectDirectory, NgWizardHelper.PackageJsonFileName, NgWizardHelper.PackageJsonOldFileName);
                    renamedTsconfigJson = RenameFileIfExists(projectDirectory, NgWizardHelper.TsconfigJsonFileName, NgWizardHelper.TsconfigJsonOldFileName);

                    // Run "ng new"
                    ngNewOutput = NgWizardHelper.RunNgNew(projectDirectory, project.Name, true, this.isNgFound);

                    // Find the .angular-cli.json created by "ng new".
                    ngNewSucceeded = NgWizardHelper.FindFileInRootDir(project, NgWizardHelper.AngularCliJsonFileName);

                    if (ngNewSucceeded.Value)
                    {
                        mergedPackageJsonFiles = MergePackageJsonFiles(projectDirectory);
                        modifiedAngularCliJson = ModifyAngularCliJsonFile(projectDirectory);
                        modifiedStartupSc      = ModifyStartupCsFile(projectDirectory);
                        mergedGitignoreFiles   = MergeGitignoreFile(projectDirectory);
                    }
                    else
                    {
                        // Rallback renamed files.
                        RenameFileIfExists(projectDirectory, NgWizardHelper.GitignoreTempFileName, NgWizardHelper.GitignoreFileName);
                        RenameFileIfExists(projectDirectory, NgWizardHelper.PackageJsonOldFileName, NgWizardHelper.PackageJsonFileName);
                        renamedTsconfigJson = renamedTsconfigJson && !RenameFileIfExists(projectDirectory, NgWizardHelper.TsconfigJsonOldFileName, NgWizardHelper.TsconfigJsonFileName);
                    }
                }

                // Report success/failure of the steps.
                var ngNewReport = (ngNewSucceeded.GetValueOrDefault()
                    ? "An Angular CLI application was added to the project using the item template version " + NgWizardHelper.GetVersion().ToString()
                    : "Something went wrong with the creation of an Angular CLI application." +
                                   (this.isNgFound ? LineBreak + "  Error message: " + ngNewOutput : "")
                                   ) + LineBreak;
                var packageJsonReport = mergedPackageJsonFiles.HasValue
                   ? "Merging the package.json files: " + GetResultText(mergedPackageJsonFiles) + LineBreak
                   : String.Empty;
                var angularCliJsonReport = modifiedAngularCliJson.HasValue
                   ? "Modifying file .angular-cli.json: " + GetResultText(modifiedAngularCliJson) + LineBreak
                   : String.Empty;
                var startupCsReport = modifiedStartupSc.HasValue
                   ? "Modifying file Startup.cs: " + GetResultText(modifiedStartupSc) + LineBreak
                   : String.Empty;
                var gitignoreReport = mergedGitignoreFiles.HasValue
                   ? "Merging the .gitignore files: " + GetResultText(mergedGitignoreFiles) + LineBreak
                   : String.Empty;
                var tsconfigJsonReport = renamedTsconfigJson
                    ? "Renaming file tsconfig.json to tsconfig.json.old: " + GetResultText(renamedTsconfigJson) + LineBreak
                    : String.Empty;

                var messageText = ngNewReport + packageJsonReport + angularCliJsonReport + startupCsReport + gitignoreReport
                                  + tsconfigJsonReport + LineBreak;

                // Augment the item file with our message.
                if (projectItem.FileCount != 0)
                {
                    var fileName = projectItem.FileNames[1]; // 1-based array
                    if (File.Exists(fileName))
                    {
                        var oldText = File.ReadAllText(fileName);
                        var newText = messageText + oldText;
                        File.WriteAllText(fileName, newText);
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Try to merge and return the operation result.
        /// </summary>
        /// <param name="projectDirectory"></param>
        /// <returns>null/false/true = not-applicable/failure/success</returns>
        private static bool?MergePackageJsonFiles(string projectDirectory)
        {
            const string ScriptsName         = "scripts";
            const string DependenciesName    = "dependencies";
            const string DevDependenciesName = "devDependencies";
            const string OldNameSuffix       = "_old";

            var filePath    = Path.Combine(projectDirectory, NgWizardHelper.PackageJsonFileName);
            var oldFilePath = Path.Combine(projectDirectory, NgWizardHelper.PackageJsonOldFileName);

            if (File.Exists(oldFilePath))
            {
                if (!File.Exists(filePath))
                {
                    return(false);
                }
            }
            else
            {
                return((bool?)null);
            }

            try
            {
                var oldObj = JObject.Parse(File.ReadAllText(oldFilePath));
                var newObj = JObject.Parse(File.ReadAllText(filePath));

                // We will give a higher priority in the three main sections to Ng, but keep the metadata properties from the old file.
                var resultObj = new JObject(oldObj);
                // The argument's content (i.e. newObj) wins over the "this" file (i.e. result).
                resultObj.Merge(newObj);

                // Clone the old content and delete the three main sections. Leave the metadata properties intact.
                var oObj = new JObject(oldObj);

                var propScr = oObj.Property(ScriptsName);
                if (propScr != null)
                {
                    propScr.Remove();
                }
                var propDep = oObj.Property(DependenciesName);
                if (propDep != null)
                {
                    propDep.Remove();
                }
                var propDev = oObj.Property(DevDependenciesName);
                if (propDev != null)
                {
                    propDev.Remove();
                }

                // Restore the old metadata properties.
                resultObj.Merge(oObj);

                // Add the three main sections from the old file for reference.
                var oScr = oldObj[ScriptsName];
                var oDep = oldObj[DependenciesName];
                var oDev = oldObj[DevDependenciesName];

                resultObj.Property(ScriptsName).AddAfterSelf(new JProperty(ScriptsName + OldNameSuffix, oScr ?? new JObject()));
                resultObj.Property(DependenciesName).AddAfterSelf(new JProperty(DependenciesName + OldNameSuffix, oDep ?? new JObject()));
                resultObj.Property(DevDependenciesName).AddAfterSelf(new JProperty(DevDependenciesName + OldNameSuffix, oDev ?? new JObject()));

                NgWizardHelper.RewriteFile(filePath, resultObj.ToString());
                return(true);
            }
            catch (Exception)
            {
            }
            return(false);
        }
        public void ProjectFinishedGenerating(Project project)
        {
            this.project = project;

            string ngNewOutput      = String.Empty;
            string readmeMdFilePath = null;

            // We included empty README.md and package.json to make the files discoverable by the IDE from the very beginning.
            // If the files were marked in the Solution Explorer as missing, opening them would take more time (??? assumption not tested) and cause flicker.
            // Now we are going to replace them with the real ones.
            var projectDirectory = Path.GetDirectoryName(project.FullName);

            if (Directory.Exists(projectDirectory))
            {
                readmeMdFilePath = Path.Combine(projectDirectory, readmeMdFileName);
                if (File.Exists(readmeMdFilePath))
                {
                    File.Delete(readmeMdFilePath);
                }
                var packageJsonFilePath = Path.Combine(projectDirectory, packageJsonFileName);
                if (File.Exists(packageJsonFilePath))
                {
                    File.Delete(packageJsonFilePath);
                }
                // Starting from ver.1.4, the CLI creates a ".gitignore" file even if the "--ignore-git" option is specified. So "ng new --ignore-git" fails if there is an existing .gitignore in the directory.
                // +https://github.com/angular/angular-cli/issues/7686
                var gitignoreFilePath     = Path.Combine(projectDirectory, gitignoreFileName);
                var gitignoreTempFilePath = Path.Combine(projectDirectory, gitignoreTempFileName);
                if (File.Exists(gitignoreFilePath))
                {
                    File.Move(gitignoreFilePath, gitignoreTempFilePath);
                }

                var projectName = project.Name.Replace('.', '-').Replace('_', '-');
                // Run "ng new"
                // ngNewOutput = RunNgNew(projectDirectory, project.Name, this.addRouting);
                ngNewOutput = NgWizardHelper.RunNgNew(projectDirectory, projectName, this.addRouting, this.isNgFound);

                if (File.Exists(gitignoreTempFilePath))
                {
                    if (File.Exists(gitignoreFilePath))
                    {
                        File.Delete(gitignoreFilePath);
                    }
                    File.Move(gitignoreTempFilePath, gitignoreFilePath);
                }
            }

            // Find the file created by the "ng new".
            var ngNewSucceeded = File.Exists(readmeMdFilePath);

            var messageText = ngNewSucceeded
                ? String.Format(WizardResources.ReadmeSuccessMessage, project.Name, NgWizardHelper.GetVersion())
                : WizardResources.ReadmeFailureMessage + ngNewOutput;

            ;

            // The Resource returns backslashes escaped. We cannot use regular 'Shift+Enter' line breakes in the editor, besause they produce "\r\n", whereas Ng-generated text has "\n", and Visual Studio Editor displays a dialog asking to normalize line breakes.
            messageText = messageText.Replace("\\n", "\n");

            // Augment README.md with our message.
            if (ngNewSucceeded)
            {
                var oldText = File.ReadAllText(readmeMdFilePath);
                var newText = messageText + oldText;
                File.WriteAllText(readmeMdFilePath, newText);
            }
            else
            {
                // If the "ng new" failed, create a substitute file to display.
                if (readmeMdFilePath != null)
                {
                    File.WriteAllText(readmeMdFilePath, messageText);
                }
            }
        }