Skip to content

Conversation

Sampy
Copy link
Contributor

@Sampy Sampy commented Jun 12, 2017

This code is to support using platyPS as part of the process for getting the documentation of Microsoft Powershell modules up on Docs.Microsoft.com.

There are two main features:

  1. Create a new New-YamlHelp cmdlet which, similar to New-ExternalHelp, reads platyPS Markdown and converts it into a set of YAML files. These files are much easier for external systems to parse and allow platyPS to convert the easy to edit Markdown files into easy to process data structures rather than having external tools attempt to parse the Markdown schema themselves.
  2. Add the "Module Name" metadata to each cmdlet Markdown file. This makes it easier for external tools to know the source of each cmdlet which is useful when rendering a cmdlet document page.

The biggest changes include the new cmdlet, a new renderer and supporting models, and the addition of YamlDotNet as a dependency to handle the Yaml processing. Unit tests have been added for the new renderer.

@msftclas
Copy link

@Sampy,
Thanks for your contribution as a Microsoft full-time employee or intern. You do not need to sign a CLA.
Thanks,
Microsoft Pull Request Bot

@vors
Copy link
Collaborator

vors commented Jun 12, 2017

Thank you @Sampy ! Love that you are contributing to platyPS!

Add the "Module Name" metadata to each cmdlet Markdown file.

There is a little bit overlap with ModulePage concept which @jongeller designed.
Example https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/6/Microsoft.PowerShell.Core/Microsoft.PowerShell.Core.md

I'd like to better understand the scenario that you are envision. Can you, elaborate, please?

@Sampy
Copy link
Contributor Author

Sampy commented Jun 12, 2017

Happy to explain! For reference, here is a sample of the page we generate for a cmdlet today: Add-AzureAnalysisServicesAccount

The idea is that when we take the structure data about a cmdlet to generate a page, we'd like to, if possible, read all the information we need to make a page from a single file. Under the name of the cmdlet, we put a link to the module page. By adding the module name to the Markdown file, it's easy to use this piece of metadata to generate the Yaml file in call cases (passing a full directory as well as a single .md file to New-YamlHelp).

Copy link
Collaborator

@vors vors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Files under src/Markdown.MAML/Model/YAML looks very similar to files under src/Markdown.MAML/Model/MAML. Does it worth to have 2 hierarchies of very similar classes? Can you simply re-use existing ones maybe?

@@ -70,6 +70,7 @@ FunctionsToExport = @(
'New-MarkdownHelp',
'Get-MarkdownMetadata',
'New-ExternalHelp',
'New-YamlHelp',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use spaces, not tabs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -456,6 +459,7 @@ function Update-MarkdownHelp
$metadata = Get-MarkdownMetadata $filePath
$metadata["external help file"] = GetHelpFileName $command
$reflectionModel = GetMamlObject -Cmdlet $name
$metadata[$script:MODULE_PAGE_MODULE_NAME] = $reflectionModel.ModuleName
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 spaces for indentation, please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -200,10 +200,13 @@ function New-MarkdownHelp

$helpFileName = GetHelpFileName (Get-Command @a)
}

Write-Verbose "Maml things module is: $($mamlObject.ModuleName)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same : 4 spaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="YamlDotNet" version="4.2.1" targetFramework="net45" />
</packages>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nuget config, right?
Can you, consolidate it with .nuget/* files?
I don't know much about modern way of managing dependencies with nuget. We have this checked-in nuget.exe which doesn't seem like a good idea.
Maybe we can use adding new dependency as an oportunity to streamline this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each project needs it's own packages.config for the things it depends on (just like the test project has the xunit libraries). You can get rid of the .nuget/* files if your project is running on .Net Core in VS 2017 since NuGet is built in to the new tool chain but this is still the proper way to do things for .Net Framework projects

@@ -31,6 +31,8 @@ public List<MamlParameter> Parameters

public bool SupportCommonParameters { get; set; }

public string ModuleName { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are cases when it's null.
I.e. when the function is dynamically defined, we should handle this cases gracefully.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From looking at the code where we read this property, null is an acceptable value.

}
$mamlModel = $mamlModels[0]
$markdownMetadata = Get-MarkdownMetadata -Path $MarkdownFile.FullName
$mamlModel.ModuleName = $markdownMetadata[$script:MODULE_PAGE_MODULE_NAME]
Copy link
Collaborator

@vors vors Jun 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clunky: ModuleName becomes this only mutable part of $mamlModel that we have to set from PS.
It would be cleaner to pass it as a parameter to MamlModelTransformer.

UPD: Actually, it could be even more clunkier, because of the burden of passing a parameter thru all the function... Not sure, maybe it's fine as is. If you think it's fine as is, please add a comment about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment explaining why added. I think a long term fix could include having this piece of data read by the markdown parser but it skips the Yaml header at the moment.

@@ -599,6 +603,70 @@ function New-MarkdownAboutHelp
}
}

function New-YamlHelp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include markdown docs for the new function in the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

end
{
$MarkdownFiles | ForEach-Object {
Write-Verbose "[New-ExternalHelp] Input markdown file $_"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix verbose messages to use the right cmdlet name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

foreach($markdownFile in $MarkdownFiles)
{
$mamlModels = GetMamlModelImpl $markdownFile.FullName -Encoding $Encoding
if($mamlModels.Count -ne 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if is not needed anymore actually, you can remove it completely

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this block of code to handle a scenario where GetMamlModelImpl returns me more than one cmdlet

[string[]]$Path,

[Parameter(Mandatory=$true)]
[string]$OutputPath,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want ot use $OutputPath and not $OutputFolder, please add handling for both paths and folders cases. For example, see how New-ExternalHelp allows to pass both dir and *.xml file as $OutputPath parameter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this to use OutputFolder as the parameter name since that is the convention

@vors
Copy link
Collaborator

vors commented Jun 15, 2017

Can you, please, include a sample of generated yaml?

@vors
Copy link
Collaborator

vors commented Jun 15, 2017

@Sampy you would likely need to get a Microsoft legal team approval to include a new dependency into this OSS project (the YamlDotNet dll). It's an internal procedure, @joeyaiello or @SteveL-MSFT should be able to work with you on that.

@Sampy
Copy link
Contributor Author

Sampy commented Jun 16, 2017

I will check and see what sort of legal approval we need to distribute YamlDotNet and figure out what to do there.

Would you like me to check a sample Yaml file into the repo somewhere? I don't see a really good place for it but I'm happy to include it where ever makes sense.

@Sampy
Copy link
Contributor Author

Sampy commented Jun 16, 2017

As far as re-using the MAML model classes, the big reason I didn't want to reuse them was to allow these two different models to grow independently. As time goes on, more data may be added to either of the two structures that the other may or may not need. By keeping the YAML model isolated, I was thinking that we could keep it as clean as possible as to which data is needed in each case.

@joeyaiello
Copy link
Contributor

@vors Thanks for pointing that out, I'm getting all the legal approval taken care of from our side. I'll ping back here when that's done (hopefully super soon).

Copy link
Collaborator

@vors vors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the documentation you wrote!

  • Include cmdlet pester tests for New-YamlHelp to the platyPS.Tests.ps1

^^^ sorry, missed that the first time


$yaml = [Markdown.MAML.Renderer.YamlRenderer]::MamlModelToString($mamlModel)
$outputFilePath = Join-Path $OutputFolder ($mamlModel.Name + ".yml")
Write-Verbose "Writing external help to $outputFilePath"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Writing yaml help..."

@vors
Copy link
Collaborator

vors commented Jun 17, 2017

@Sampy no need to commit it to the repo, you can create a gist and link it here in the PR. I just want to take a look at it.

@vors vors self-assigned this Jun 18, 2017
@Sampy
Copy link
Contributor Author

Sampy commented Jun 19, 2017

Here is the gist for a sample Yaml file: https://gist.github.com/Sampy/77ff4d6ddad5bb555b36d5f793f3d73b

Copy link
Collaborator

@vors vors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sampy please remove yaml files and folder
@joeyaiello this PR is on hold until the legal team approval.

LGTM

$yamlModel.OptionalParameters[1].Name | Should Be 'Force'
}

It 'throws for OutputFolder that is a file'{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: space before {

@@ -0,0 +1,78 @@
examples:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to include this yaml folder into PR. We only should keep the sources under the source control. These files are purely the artifacts from the markdown, similar to maml xmls.

@vors vors assigned joeyaiello and unassigned vors Jun 21, 2017
@vors
Copy link
Collaborator

vors commented Jun 21, 2017

Assigning to Joey for follow-up

@adityapatwardhan adityapatwardhan merged commit b89efd8 into PowerShell:master Aug 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants