PlatyPS: PowerShell Help meets Markdown
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Vorobev, Sergei
PlatyPS solves a long standing pain of writing PowerShell external help xmls. Now you can write help in markdown and verify that it reflects the code. PlatyPS brings modern markdown-based workflows to the PowerShell help authoring. We will take a deep dive in the PowerShell help engine and platyPS. PlatyPS solves a long standing pain of writing PowerShell external help xmls.It provides a way to * Write PowerShell External Help in Markdown * Generate markdown help for your existing modules * Keep markdown help up-to-date with your code * Generate help artifacts (maml xmls and online help archives) from markdown and ship them with your modules Traditionally PowerShell external help files have been authored by hand or using complex tool chains and rendered as MAML XML for use as console help. MAML is cumbersome to edit by hand, and common tools and editors don't provide good support for working with it. Markdown is a very easy markup language which became a standard for writing documentation. We will take a look at existing big projects that are using it (like Azure and PowerShell-Docs) and some smaller projects (like PSReadLine). We will go through a (very easy!) bootstrap process for using platyPS in an existing project. We will also cover how to make sure that documentation is up to date and even add tests to your CI pipeline to make sure that documentation is always updated. In the second part of the talk, we will take a deep dive into platyPS internals. We will talk about markdown schema, quirks of PowerShell help engine and tool limitations. We will also cover advanced topics, like combining few different versions of your module help into a single markdown document. Every part of the talk will be accompanied by hands on live demos.
 Welcome to Platypus PowerShell Help Me Smart Down talk. Thank you for joining me today. We have a lot of great talk going on. So just quick introduction about myself. My name is Sergey. I work for a couple years on the PowerShell team. Currently I work at Dropbox as a software developer. And in PowerShell community I was working on a few projects. You may see in my avatar, it's PowerShell open source project itself. It's Platypus, which we will talk about today. And a couple of small pet projects. It's the location and sublime PowerShell grammar which is used by GitHub for syntax highlighting as well. So let's talk about GitHub. How many of you use GitHub? Okay, everybody, great. Yes, because GitHub is awesome commandlet that everybody learn when they learn PowerShell. It's probably one of the top three commandlets that people told you to start using. That's basically the way how we figure out how to use our commandlets. So that's how it looks like. You just get some nice structured output, name, syntax, aliases, remarks, parameters, and whatnot. But how actually you get this output? If you module after, you want to provide help with your module and you have a couple of options to do that. The first option is if you write in a script-based module, you can use a command-based help in the script. It looks like this. So you can have a structured command with sections like synopsis, description, and everything else. And it's very natural to read it. It's very natural to write it. And it's probably one of the most popular ways to provide documentation and help for your modules. The next option is somewhat specific to binary modules, basically the same thing, but for binary modules. Binary is modules you write in some.NET language, most likely C-sharp. They look very similar again. They use XML text instead of this.synopsis and.description. But again, it's maybe a little bit less readable by just the naked eye, but pretty self-explanatory. The third option is called MAML XML. So how many of you wrote MAML XMLs in your life? Okay, one hand. Half hand. Okay, so let's break it down. Great you've come to the talk. Glad to have you. I think we'll learn a lot of cool stuff today. So MAML stands for Microsoft Assistant Markup Language and XML stands for Extensible Markup Language. So we have Markup Language twice. And this is how it looks like. Oh, no, that's not how it looks like because it can't be load. Because MAML XML files are usually really gigantic files, many, many megabytes of text. Basically, imagine something like Azure PowerShell module which has hundreds and hundreds of commands. And all the help for all these commands is crumbled into one file. So it's a lot of content. And for example, this is a view on GitHub. GitHub cannot handle it. But I got it covered, so this is how it looks like if you open it in text editor. If you cannot read it, it's okay. I will just tell you what the colors mean here. So the red one is XML text. The white one is actual content that, you know, people wrote. And yellow and green is a key value pairs for a bunch of metadata. So let's have a good mix of all of them. This is, like imagine now writing it by hands. You know, it's pretty overwhelming task. And MAML XML is not very popular among the, like, you know, one-person projects. You need the special tooling to create it. And we will address it a little bit later, but just let's make a note that, you know, it's pretty hard to just, like, open the text editor and start writing MAML XML help. But it actually has an advantage over command-based help and our command-based help. The advantage is that it's a separate file. You ship it together with your module. MAML-based help also known as external help. It's external because it's outside of your code. So let's say if you are a big company like Microsoft or VMware, then you can hire a team of tech writers and then they can collaborate on the documentation without involving your source code. And so they don't actually mess up with development process and it's nice. It's also the only way to provide help that allows you to ship more than one language. If you have, like, requirements to have English version and German version, you basically have to use MAML-based help for that. Because in the code you can only have, you know, one language. And another type of help that I don't often talk about is websites. So when PowerShell was created ten years ago, it probably wasn't that hot. But now people don't like to read text in the command line that much. People like to just go to Google and find the help on the Internet. So websites is something that people build completely separate from GetHelp. And essentially if you want to have a good online presence, if you want to have a website, and you want to provide help for your module, what you do is, like, you build two different documentations. And now they can get out of date. You need to have, like, all kind of stories for consistency between them. And it's just a lot of additional work. I just want to point out, like, this is example from Google's Google Cloud commandlet. Get GCDisk. So they use nice tables for metadata. They use different syntax highlighting. They use hyperlinks. And you can't really get that stuff in your console. You really need the web technologies to surface it. So to recap, we have different types of help. Command-based help is very easy to write and intuitive, and it's very popular. It's easier than MAML. MAML has its own advantages if you have requirements for multiple languages, if you have requirements for update help. Update help basically allows you to host archives of a new version of the help on a website and bring them down with update help. But none of the existing solutions actively address the problem of creating websites that are not supported from the Get Help content itself. So with that, I would like to talk a little bit about my personal experience with PowerShell help. My first project when I joined PowerShell team was Azure DSC extension. So Azure DSC extension is an Azure marketplace application, I guess. It contains of two parts. The first part is a server. It lives in the virtual machine and users install it separately by checkbox or by running commandlet. And it has a client part in the form of few commandlets in Azure PowerShell module. So Azure PowerShell module is an open source hosted on GitHub by Microsoft. Probably one of the first big PowerShell related open source projects. So to implement this extension, what we did is we add a few commandlets into Azure PowerShell. It took a few months and we figured it all out, but then after some time we actually found that we forgot to add help. So it wasn't good and we need to fix it quickly. That's how I started to basically learn and think about what's the documentation story in PowerShell. The workflow was like the following. Azure PowerShell use MAML XML. So they have this one file that can be loaded on GitHub from a previous slide. There was no specified workflow anywhere in documentation repository. And basically you just need to figure out for yourself how you want to approach it. So as I mentioned, to edit this MAML XML we can pick up some tools. I know about three tools, maybe there are more. One of them is internal Microsoft tool. It's very nice. It can connect to a database and you can collaborate with other people by using the database as storage. But it was internal and it doesn't fit the build of working in the open with community. So the next tool is the Suncastle. Suncastle is a free project. Its name is actually not Suncastle. Its name is Suncastle Help File Builder, SHFB. But I will just say Suncastle for simplicity. The workflow looks like this and basically that's true for all the available tools. You import your module from maximal form into some internal representation inside the tool. Then you have nice UI with Windows where you can edit it. You can add new parameters and new commandlets. And then the last step is basically experts. So it was pretty painful expert for the following reasons. Internal representation of the XML basically forgot all the formatting. And all white spaces get replaced by tabs or vice versa. All the text formatting changed like indentations. And in one place this indentation was one way and now it was another way. In XML you can have commands. So commands wasn't preserved. And as a result of all that if you just take the diff and submit pull request to Azure PowerShell, they will have a really hard time reviewing it. Because you have a mix of from item changes, some good from item changes, some bad from item changes, and some actual content that you add. So that just puts a bunch of burden on the maintainers who needs to separate all these things and give you go and all go. On top of it they cannot use web interface because this file is so gigantic so they need to find a ways to review it locally and it's a whole nother story. Okay, so we have this problem of not preserving the formatting. Basically the best solution I found was to open original file in a text editor. Open new generated file in a text editor and find the corresponding block and like drag and drop selection and just copy it. That works but it's pretty error pruning and it's not fun unless you think it's fun. And I had a really hard time and a few times I actually had a problem that I forgot some tag in one place. So now XML became invalid and there is no good way to test it. It's valid or invalid until you load the help and get help and then you see that nothing displays. So that's pretty, like that's a lot of process around simple changes in documentation. Okay, I hope I convinced you that we need a better story for that. So let me introduce Platypus. It's a project that basically tries to solve all these problems I just outlined. So we have two parts of equation. We want something for the web and we want something that can be consumed by help engine. And ideally we basically just want one source for all the to avoid doing duplicated work or some synchronization. The help engine part, we basically have two options. We can provide command-based help or we can provide MAML XMLs. Because, okay, so one of the approaches to solve it would be to have some third format, not website, not the command-based help, but something separate from them which is easy, can be turned into the website and can be turned into the help engine help, consumable format. Okay, so with that motivation, it's probably no surprise that command-based help is out of the table because if you want to just generate something, it would be really hard to insert it into the code that already exists. So MAML XML fits the build perfectly. We basically just start to treat our MAML XMLs as kind of binary, if you wish, like DLL that you compile. And you just have this build step when you generate the help out of something like some third format. And this third format, because we want a website as well, it should be something very close to the web technologies. So people build websites for a long time and basically the amount of people who build websites is pretty big. It's bigger than PowerShell community. So they actually create a bunch of nice tools for doing that stuff. One of the problems with just writing raw HTML is that it's not very scalable. It's just cumbersome, so people actually don't write raw HTML by hands anymore. One of the approaches to create a static web content is to use a markup language. And one of the very popular markup language is markdown. Yes, so and then we come to a demo. So Platypus, okay, let's get back. Basically, Platypus allows you to take a markdown and turn it into MAML XML, which can be later consumed by the help engine. And because it's just a markdown, then the website story is already solved. You can just turn it into a website and there are plenty of existing tools to do that. So yes, now demo time. I will show you the markdown and the results in XML. Is font size okay? So we start with just importing Platypus into the session. And I wanted to show, I already prepared the markdown and this is how it looks like. And you can see that it basically loosely resembles the output of get help with some fancy block at the top. But let's ignore it for now. And then, like I guess, you know, if you're familiar with get help output, you can basically figure out how this structured. There are some fancy backticks here and there, some hyperlinks and all that stuff. But let's just take a look at how it will look like when you render it as HTML page. So Visual Studio Code has this nice feature, markdown preview. And basically that's what we will get if you just turn this markdown into HTML. So you get like headers, you get hyperlinks, you get code snippets and all that good stuff. So this is, you know, as far as I'm concerned, looks very good. You can put it on the Internet and people can consume it. It's maybe not as fancy as Google's version, which has tables, but it's pretty decent. So now, like I showed you first part of equation, let's take a look at the second part of it. How we take this markdown and turn it into get help. So I picked new external help markdown as example because we will basically use new external help on new external help to produce some output. So let's actually first take a look at all the commandlets that are available in Platypus module. So there are like about 10 of them and the core, like the heart of the whole module is this new external help. The turning markdown into the help XML is actually the hardest part and all that. So let's give it a try. So we can provide path to new markdown, a new external help MD and we can say output path out. We just need to give it a directory. It can exist. It may not exist. It will create it for us and we get an output. So let's take a look at this file. So this is XML you can see and it basically has all the content that we wanted. So we can just take this XML, ship it with our module and we are done. Oh, yeah. I forgot to show one more cool thing. So I just show the XML, but it would be really nice to know how this XML will look like when it's outputted by get help. So for that we have another commandlet in the toolbox, get help preview. Get help preview takes path parameter to a file and it outputs what the get help will output only like if you use this file as a help basically. So let's scroll it up a little bit and take a look at all this stuff. So the name synopsis looks good. Let's just, you know, kind of spot check that we have the same content here and in the original markdown. So I just use search. Okay, sure enough, basically output path looks like this here and it looks like this here. And that can be applied not only to a single commandlet and single file, but it can be applied at scale. Let's actually take a look at this guy. I have Platypus docs directory with basically like kind of docfooding all the documentation for Platypus itself. So let's turn all this documentation into XML file. So it thinks a little bit longer. And now it outputs just a single XML for all the help and it also outputs about topic which we'll talk about in a bit. Actually, I think, yeah, that's right. Time to talk about about. So how many of you wrote about topics in PowerShell? So they are less popular. Yeah, like we can see it's less popular than like traditional help. And I will just demystify them a little bit. Basically about topics. Let's take a look at this one and about TXT. So this is, I mean, the extension TXT is no joke. It's really text file. There is no formatting whatsoever. All this crazy XML I showed for the commandlet based help for the XML help. They're not applyable for the about topics. Basically about topic is just the text file. So it's pretty easy to just go and write it by hands, no problem. But as soon as we start to talk about the story of having a website, it would be nice to incorporate about topics in the structure of our website. We can have same formatting, same hyperlinks and everything, you know, cross reference topics from about into the commandlets and vice versa, and just have like a solid story for all types of PowerShell help. Yeah, by the way, about topics can be accessible if you do about help, about something like this, about platypus. For example, it basically just outputs with text file. And let's take a look at how platypus handles about topic creation. Oh, no, this demo is a little bit later. But that's fine. Let's do it now. It's pretty short demo, just one line. So to create a new about topic, what we do is we need to call new markdown about help, and we need to pass about name parameter. And in this case, I will use greeting. Okay, it will make sense after a second demo, why greeting. And let's take a look at what we output in about greeting markdown. So what we output is, you know, looks like markdown and there is just a bunch of placeholders that you need to fill up. But once you do it, you can use the same new external help commandlet to translate markdown into the text file that you can ship with your module. All right, so let's get back to presentation. So to talk about platypus, we first need to talk about markdown. How many of you use markdown? So almost everybody, most people. For let's give it 60 seconds refresher. So one of the beautiful things about markdown is that it's so natural and so easy to learn that you really need only like 60 seconds to pick it up. So here we go. This is the basics of markdown. We have a line, we have another line. If we have only one line break between them, they will form a paragraph. So line break kind of serves as a space. If you do two line breaks, you start a new paragraph. For headers, we use hash. So if you have one hash, it will be header level one. If you have two hashes, it will be header level two. For bullet point lists, we use dashes or also asterisks. And for number lists, we use one dot, one dot, one dot. You can also use one dot, two dot, three dot, but it's not necessary. It will automatically numerate it for you. For hyperlinks, we use this syntax with square brackets and brackets. And for codysnipids, we use a triple back tick. And there is a non-mandatory language specifier. So if you want to have a syntax highlighting in the snippet, you can actually say what language it is. So that's pretty much markdown for you. If you want to recap at home, there is a great resource. We've learned that in 60 seconds. It's a common mark.org help. They also have a 10-minute version of the same tutorial with more details. And now we can actually take a look at more demos. So now we know markdown. The natural question to ask is, OK, who will write all this markdown? Like so far, what I tell you is, hey, I came up with this format for help, and now everybody should start using it. But that's not how it works, because people already using some tools, they created documentation in command-based help in MAML. So just to ask everybody to start to use markdown for help is not a very clever thing, because it's a lot of work to create it. So to address this problem, we actually have helper functions to bootstrap all your markdown documentation. So here I just have a kind of hello-worthy function, very small. Let's go through it very quickly. We have parameter block. We have command-based bindings, which means that we have advanced function. So we have things like common parameters, out variable, and all that stuff. We have one parameter in parameter block with mandatory set to true and value from power plant set to true. The name of parameter is name, and it does a very useful process block here. So let's give it a shot and try it out. New, getting. Okay, so that works, and let's just test out the piping from piping. Just piping. It's not getting, it's new greetings. Okay, that also works. Cool, so let's say I want to create a help for this commandlet. All I need to do is use new markdown help commandlet and specify command name. So command should be in the PowerShell session already. And yeah, we have top completion here, which is pretty awesome. And we need to specify output folder, so let's use our output folder where we put all this stuff. And just output it with markdown. So let's take a look at what did it output for us. So we again have this metadata block, let's ignore it for now. And then we have a name of commandlet. We have synapses. And here we have a first placeholder, which tells us fill in the synapses. And let's actually just search for all the placeholders in this file. So in Platypus, we use double curlers for the placeholders, and there are like five of them. Unfortunately, like Platypus cannot read your mind, so it cannot fill up with text fields for you. But it's still much easier to just go and fill up five fields than to write a whole XML. So let's actually populate these placeholders. I will just copy paste some descriptions to avoid typing on the demo. So for example, we will use, we put the code here, and you can see that it has this triple-backticks power shell, which means that the whole thing would be syntax highlighting as power shell. I really like when people in the examples in the help put the output of the help as well as the command. That's very useful. So let's actually do it. It's just a good practice. I will just copy this output. And now I have two choices. If I just put it like this, the whole output would be highlighted as power shell, which is not exactly what we want because it can be some arbitrary text. So to avoid doing the highlighting on the second part, we can just break this code snippet into two code snippets, and then the first part would be treated as input and the second part as output. So we need to provide the description, for example. Okay, we have spell checker saved us. And the last placeholder we need to populate is name. Let's just double check that we don't have any more placeholders. And let's take a look at these parameters, at this parameter metadata block. So you remember that our name parameter was a required parameter, and it's already said required true. It also has a set pipeline input set to the proper value. So that all that stuff we get for free just by running new markdown help. We don't need to touch this metadata block by hands. All we need to do is just go and write the strings, create some valuable content that cannot be after generated for us. And we have this command parameters because it's advanced commandlet. Okay, so now let's see can we turn this markdown into external help. We are already familiar with new external help. We give it actually, yeah, that's fine. New external help, let's give it path out new greeting. And as output path, I will use NUS. So that way I will just put it in the default locale, and later PowerShell help system can pick it up from this NUS folder. So now what we need to do to see this help live from GetHelp, we just need to reload the module. So zero to greeting, and we need to use force for that. And now if I just say GetHelp new greeting, I should, let's use full. I should see all the content we just after it right here. We have the example, we have synopsis and everything else. Okay, so the next demo was about, which I already showed. And now let's take a look at doing the same thing, but at scale. So I just found this GetHelp issue. Can you tell me the password? I knew I forgot something. And that was a Wi-Fi for the demos. That was great. Let's try it one more time. Okay, cool. And this side is good. So this is just a PowerShell module for Atlassian that allows you to optimize GER. And basically they're talking about, hey, let's migrate our documentation to Markdown, let's migrate it to Placipus. And this issue was filed in July 2017. So let's see how long it takes to migrate the help. We have GERA, oops, GERA PS here. So let's import it. PSD1. So it's loaded everything. Let's take a look at all the commands in this module. The fair number of them. And now we can just say new Markdown help. And I will use another variant, not just a command, but the module. And we have type completion for modules as well. And as an output folder, let's use something like Out2. And it just starts to pop out all this Markdown for all these files. And it looks like 30 seconds to basically bootstrap help for this big module. Now let's take a look at the result of this bootstrapping. So because Atlation already had command-based help for these modules, Synapses, we don't need to populate it. It's already there. And the same goes for everything else. We already have examples. We already have parameters, descriptions here, and everything in between. So if you start to go through all this generated Markdown, what you will find very soon is that at some point there is no documentation. So we, again, get in the same placeholders. And this is basically a good way to make sure that you have all documentation. Like even if you're using command-based documentation, you can just run Platypus and then search for placeholders. And if there are no placeholders, then that means that you covered everything. And if not, then you can just go and add this help. Yep. So that was bootstrapping for Jura module. Now we already covered just plain Markdown. And I showed you how you can use Platypus to generate Markdown and how to use Platypus to generate help out of Markdown. And now we can talk about the Markdown that is specific to Platypus. So Markdown is, as I mentioned, a really great, easy-to-learn Markup language. But it has this unfortunate property that any text is basically a valid Markdown. So, you know, that kind of a problem because you cannot expect Platypus to just magically figure out what did you mean from some abstract Markdown document. You need to comply with a schema. And Markdown doesn't have schema built-in. Unlike things like JSON and XML where you can specify schema and validate against the schema, Markdown doesn't have such thing. But we need it because that's how the tool can, you know, know that this synopsis thing is, corresponds to synopsis. So the schema leaves in this, basically, the development of Platypus happens in this PowerShell Platypus repository on GitHub. And there is a top-level file, Platypus schema, MD, which kind of goes into all the, like, very subtle details that you may want to know one day. But now we're not going to go through it. What we will do instead, we will just look at examples. So, because, as I said, Platypus schema is modeled after the GetHelp output. So, basically, if you know GetHelp output, you should be able to just pick it up. The first thing is name. And for name, we use header level one. Pretty self-explanatory. For synopsis, we use a level header two for names, for the word synopsis. And then the text block that goes after it becomes the synopsis. Same goes for description. And here you can see an example of using bold, I didn't mention it on my 60-seconds intro about Markdown. But when you have double asterisks, it's bold in Markdown. And you can see example of using some rich formatting in the Markdown, which later just tips out during the translation. So, you know, again, to the common theme of having the same source for both GetHelp and the website, you don't need to compromise for that. And you can still use rich formatting. The next one is examples. So, examples is a section that contains subsections. Basically, how many examples you have, you just put them as a subsections, and they become header level three with three hashes at the beginning. So, the title becomes the title, and we automatically pad it with dashes, which is actually very nice, because it's one of the many inconsistencies in existing PowerShell documentation. These dashes, you don't get them for free from GetHelp, you actually need to write them down in your XML to get it look nicely. Then we have a code snippet block, fenced by triple-bactics. And as I mentioned, you can break it down into two pieces, you can break it into the code snippet and the code output. So, in this case, we actually didn't do that, we just put everything without syntax highlighting. And then the text after the block becomes the description of example. So, parameters is again contains of multiple subsections. Every parameter gets its own section, its name starts with dash, the same thing as in GetHelp output. And let's take a look at the metadata part. When I circled here, oh, you see it, cool. So, this metadata, it's actually, you can see it's break by new line break, and the second half is just completely the same as parameters metadata here. Then type string array in this case, it basically comes from the type string in parameter. And aliases is actually something that not shown by GetHelp for some reason, but it's good to have aliases for parameter. And the last one is parameter sets list. And you wouldn't find the direct correspondence into GetHelp output because GetHelp uses syntax block to provide information about the parameter sets names. But it was just easier to basically put everything into one place in parameters. And the syntax block actually brings us into taking a look at the syntax block in Platypus. So, the important thing that a lot of people miss is syntax block in Platypus is view only. It's kind of like read once and forget. So, it's not used as part of new external help generation. It's like all the metadata already present in parameters block. So, syntax block really exists only for the online, like for the website purpose there. So, you know, you like, you know, we need to edit it by hands. It will be always just after generated for you. The next field is input output. Again, very self-explanatory. You can have multiple of them. You can have multiple level three headers. And the last one is related links. So, the related links is usually at the bottom of your help. And you can see that just normal markdown links get translated into kind of key value pairs in PowerShell. And the PowerShell version has one additional link at the top, online version. So, this is not very well known, but when you run get help dash online, what happens is a help system looks into all the links you have and it opens the first one. So, we kind of decided that it's better to be more explicit about this. So, that's why we put online version in this top level metadata to make it more obvious how it works. And what is, like, let's talk about this top level metadata. Basically, in markdown there is a standard extension which allows you to put YAML, any arbitrary YAML file at the top for the metadata purposes. We kind of using poor man's version of it. We just use key value pairs. We don't support the full YAML. But that's enough for our goal. And it has four fields that Platypus understands. External help file, module name, online version and schema version. You can put more stuff there. It's basically just a back of key value properties. And the reason is people want to build, like Microsoft, for example, they want to create some workflows for the documentation and they need some inventory to reference the topics and they put some GUIts with some names and maybe language, moniker and whatnot. So, yeah, that part can be basically used for your own workflows, for your own customizations. Oops. Oh, I need something. Should I pick this? Mark, man. So, life cycle. Basically, let's say you write your module, you write your documentation once, and then six months later you actually want to edit it. And this is very common, basically. The modules are not static things you created once. It's a living, breathing being. So what kind of modifications do we usually see? People add new commandlets, people add parameters to existing commandlets, people add new functionality, and this functionality requires new examples in the docs. And, like, parameters get renamed and just some alias get added. So that would be great if we can have a good story about how you can update your module with, how you can update your help with your module. And now I will just show you just that. Okay, so this is actually a folder. Let's take a look at it. We have a PSM1 file, and it's basically our old friend, new greeting. Nothing unexpected here. But let's say that after some time I decided that it's a good idea to add a new parameter. And instead of just having hard-coded hello, I now want to have a greeting verb, I guess it's greeting noun. And now my process blog just becomes beautiful, concatenation of three things. So let's copy it into the greeting update. I will just show you git diff. So this is basically a diff of my change. And let's take a look at help for this command now. So I import in module update. So now let's verify that we have a new version of a module loaded. Greeting name and greeting one, two, three. Great greeting. So yeah, we have an updated version of a module loaded. But in our docs folder right here, we have an old version of documentation. So let's take a look at it. It's old because we in the parameters section, we only have name, but we don't have greeting. So this is a situation you will commonly find yourself in. All you need to do is simply run one command, update, markdown, help. And then you just pass path to a folder with all your documentation. And voila, we just get a new parameter here. And this green stripe at the left basically indicates that it's addition. And we also get the same thing into the syntax for free. So you never, like, you add parameter, you don't need to edit it. Just takes care of. All you need to do is now provide description. Now we can create external help out of it and load it into the module the same way I already showed. Why don't you change the type of existing brand name, change to string arrays instead? Yeah, that will be, let's actually try it. That's a great example. Like this, right? Okay, so that didn't work. Maybe it's actually a visual study code. Let's reload it just to make sure. Oh, I didn't reload. Yeah, that's a good catch. That should work. You know, if it doesn't work, it means we have bug and we have bugs sometimes. Yeah, so it did update. So essentially, you don't need to ever touch this metadata block. You know, it's already automated for you. There is one caveat, actually. I will give it up. You see how we have greeting equal hello. So we actually have default value for greeting. But there are some unfortunate help engine limitations and we didn't update default value. I'm not sure that it is possible. I think when I look into it, I found that we just don't have a right way to get this value out. So you actually need to edit, like maybe default value is like the only one that you need to edit by hands. Good question. Okay, so let's just really quickly. Let's import the module and let's get help. Okay, so now we have both parameters here. Let me double check that it's all I want to talk about here. Yep. Okay, so and now a bonus. Because we use Git for version control. This is how Diff looks like. Let me just create a temporary branch and make a commit. Demo. Now Diff should be empty. And we should be on branch demo. Okay, so let's run update help one more time. And run Git Diff one more time. Okay, so you see here we try to run update and we made sure that there is no Diff between the previous state and current state. What it means is now you have a very simple test to tell is your help out of data or not. Did you add any parameters or not? And you can basically take these simple couple lines and you can put it into your continuous integration pipeline. And it will basically enforce that the help is always up to date. And this is actually a theme of our next talk section. So, yeah, CI or continuous integration is great. You can leverage it like the common ways to use continuous integration to run tests and make sure all the tests are passing. But you can also use it in creative ways. For example, you can make sure that the commutation is up to date. And I just showed you example script. It's not like one liner, but it's maybe two lines to get it done. But the even better part about it is that once your help is in markdown, now you can leverage all this great work done by the web development people who created things like spell checking for markdown, created hyperlink checking. So hyperlink checking is very important. It's like my pet peeve because what happens is let's say you have like 100 markdown documents and you refactor them somehow, you like split or merge or rename something. And you have always hyperlinks rolling around and part of them became invalid and you don't know until you like, right, until somebody reports it to you. So you can easily automatically test it with some scripting. And spell check is also self-explanatory. And this is what I just did as a demo. I set it up repository pedantic CI demo. So it's probably one of the most pedantic projects because it will make sure that you have your grammar correctly, you have your hyperlinks correctly and that your help is up to date. So let's take a look at it. Let's start with the code. This is our well-known friend, new greeting. Sorry. Good catch. Yep. So this is, I just put up this docs pedantic CI demo repository. We have continuous integration bridge from Upware. So we will use Upware as a continuous integration system. Upware is, I mean, it's like Jenkins, but it's hosted. So you don't need to care about where you're going to host it. And it's also free for open source projects, which is awesome. And, you know, for like demos, especially, I highly recommend to use Upware. We'll take a look at it in a bit. But first, let's take a look at source code of our module. We have our beloved new greeting function in the old version. We've hardcoded hello. And we have documentation for it in docs. This is actually, yeah, I think it's the first time I'm showing you how the markdown, like rendered markdown looks on GitHub. So as far as I'm concerned, it looks pretty good. You can use some static website builder to make it, you know, to make styles as you see fit. You can build static website of markdown. But even as it is, even like simple act of putting your help on GitHub already gives you pretty nice experience for viewing. And as a bonus fact, it is also indexable by Google, so now people can actually find your help. So, like, I think it's good back for a buck. And let's take a look at this Upware YAML file, which is actually describes the continuous integration steps. So it's actually YAML files, so we have YAML syntax. We will be mostly interested in this test script section. But let's read it, the whole thing. So we just installing some modules, platypus, obviously, markdown link check, module to check the links. And we install some spell checker from NPM from Node because they have better, like, I didn't find the partial module for spell check. So had to use Node. That line just helpful for dealing with new lines. And because I am demoing on mark and I use Windows for the continuous integration, basically, just takes care of that. So we don't get empty divs. That contains just new lines. Build script, here, we don't build anything, we just import it in the session. And here is an interesting part, so the test script. We have two free steps. First, let's make sure that our help is up to date. We run update markdown help just as I did locally. We run get div. And then if give is non-empty, then we throw and we display what's the div in update markdown help. So this is, I just want to bring your attention to this part because it's, you know, a contributor coming and committing something in your repository. They should get some useful error messages, not just that everything failed. So please include as much information and error messages as you can. The second part is very fine hyperlinks. I didn't talk much about this hyperlinks module, but basically you can give it a folder and you can say broken only. And if there are any broken links, it will return them. And the last one is spell checker, so this is not PowerShell. So we just run some interesting command with a bunch of switches. And report basically makes it non-interactive, like by default it runs as interactive command. And report just generally, it's a general report. It uses last exit code for, it basically returns one if anything failed. Or maybe it's number of errors. Don't remember. So with that, let's actually take a look at pull requests now. So they're all from me, but imagine that somebody sent the first one. And this person had a brilliant idea to add greeting into your code, but they didn't do anything about the help. So what happens next? Next, they get in this gigantic red crosses. And if you click on details, you can open it. This is the up-wear interface. And you see the whole log of things that happen. And the last one is writing your face red error message. And it tells you run update markdown help and then some def. Well, it's not very well-formatted. It could be formatted better, but it's something. Okay, so now this person runs update markdown help and sends the second pull request. And this time they actually, let's take a look at the def. So we have the same def here. We have basically syntax updated by update help and greeting. And this person was really nice and specify the description and replace the placeholder, which people can often forget. And this person even specify default value. So he knows about this quirky box in Platypus. But he decided to be extra fancy and add related links section. And he made a mistake in referencing to read me. So now this link is actually broken. Let's take a look how the continuous integration system will handle it. Well, sure enough, we have found broken hyperlinks and it actually gives us all the information we need. It gives the file path URL and line and column. Okay, so now this person takes it one step further and fixes the hyperlink. So right here we have read me, but language is still misspelled. And sure enough, our continuous integration system can catch it. And this is not very helpful error message, but if you look up, you can see that it outputs the line. When you run it locally, it actually highlights the word language, up where it loses this highlighting. So not as good as it could be, but still something. And the final chord is when the person fixes the misspelled word. And let's actually take a look at up where I would put anyway. You can see it's all green, but just to make sure, yeah, it says build succeeded. So that's probably, for some projects, it's maybe overkill to have all this spell checking and whatnot. To be honest, to make the spell checking works, you need to add a huge exclusion list, like white list, for a lot of stuff. But the PowerShell repository uses this spell checking actually. You can come up with creative ways to verify that maybe you like your markdown to be after it in a certain way. You don't like long lines. I don't like long lines personally. It basically asks everybody to always break it into smaller pieces because it's easier for a view. You can express all these constraints now in the continuous integration system. So another bonus fact, another bonus of using continuous integration in conjunction with documentation is that you don't have to tell people to do what you want them to do. You can make robots do them, robots tell them what to do. And this is just a human nature. People really don't like to be told what to do, but if it's a machine, then they're more willing to collaborate. So the lesson, if you want to introduce a new workflow in your organization, don't be codenuts. Just make some automation that enforces it and introduce it this way. Okay, so recap. With Flattipoost now, you can put your help online. You make it available. If you use GitHub for hosting of your help, it's basically free hosting solution. It gives you a very nice interface. That way, you actually make it contributions friendly. And this is one point I want to talk about. Even if you don't do open source, let's say you're doing some preparatory software, there is no point of keeping your documentation closed. You can just create a separate repository, put it online. This is a chip hosting solution. You allow people contribute back. So if somebody spots a mistake or just a typo, they can contribute now. So, yeah, that's basically an approach that a lot of companies take. Up to date, so your help can be up to date. You can enforce any kind of rules and markdown you want. You can tailor it to your needs. Maybe, you know, again, the spell checker is every key for you, but links are great. And this is a list of projects that already use Flattipoost. Basically, the PowerShell docs is a core modules. Azure PowerShell is my personal favorite because that's how it all started. Basically, my whole motivation was to make Azure PowerShell collaboration work good. PSV line is the first adopter of Flattipoost, big kudos to Jason Sherk for being a brave adopter. I was searching in GitHub who uses Flattipoost by some keywords and I'm not sure what it is. The recent addition is Office PowerShell, which actually has thousands and thousands of commands. And they use all the same tool chain that I described, they use GitHub, they use Flattipoost, they also use DocFX for the nicer website version, which you can also use. And with that, I would like to ask you to join this list of great projects and give Flattipoost a try. We... So with that, I would like to talk a little bit about the future of PowerShell help documentation. So if you follow GitHub, you may see this issue created by Steve Lee, who is a team lead on PowerShell team. And it says, help system should consume markdown natively. And if you follow another repository, PowerShell RFC, you may see another issue created by Ditya, help system as a standalone PowerShell module. So I think you can see where it's all going. Basically, there is a desire to cut, man in the middle, cut this translation from markdown into external help, because you don't really need it. You can just display markdown. If you can render the same thing in console and then on the web, like why we have a whole transition story? So with that, it's basically... Flattipoost is not like a final destination in this journey. It's a stepping stone to basically provide a smooth transition to a better and more modern documentation tool chain for PowerShell. We can only do it if we all start to... If we all converge on it, basically. If we introduce it as a standard in the community and in Microsoft, then we can hope for a better documentation story. If it doesn't get traction, then it will be like the current state, which is also fine, but we can do much better in my opinion. So with that, thank you. We actually have a lot of time, so if you have any questions, that's a good time. Do you know what they transfer to markdown? Are they going to backport back to older versions of PowerShell? Yes, so let's take a look at the PowerShell docs. It's already backported. Oh, you mean... Like when they switch over from MAML, is it going to be compatible with old PowerShell markers? So let me answer it in two ways. So the question is, if we go and translate to markdown, would it be backported? So I will answer in two parts. The first one is it's already backported in the sense of content. So let's take a look at the PowerShell docs. This is core commandlet's modules, and it has obvious folder reference for everything. And then you can see the 3.0, for example. You have all the content right here. And the second kind of building on this question is, let's say that tomorrow we have some great way to display markdown in the console in PowerShell. It can totally be a separate module downloadable from the gallery. Good question. The update help? How does the version work? Where you can put out the source or where the download slides from? That's what's being in the MAML somewhere? Yeah, exactly. So I conveniently have it right here. This online version actually points... Okay, no, I not conveniently have it here. I conveniently have it right here. Okay, right here. So if you want to leverage updateable help, you can use what we call module help. Basically, it's a kind of table of content markdown file with description of the whole module, and then basically links to all the single commandlets. And in this document, you can specify download help link. And we basically try to make the flow of using updateable help as easy as possible. So we have a new external help cap, I guess. Yeah, new external help cap, which takes care of packing everything in the right format. You just need to put it on the right URL after that. Good question. When you have that module page, it sure is just... And you do that if you have a new project and you do external help on that, and use that switch with module page, you get a page very similar to that. And you still have to fill in the description for every command that you make. Oh, yeah, that could be better. We can pull up synopsis, right? That's not been done yet, but it could be better. Yeah, yeah, and that's a great question because what I would like to show you is a place for such questions, basically on GitHub, oh my... I think it does pull synopsis. There's synopsis in the library. I see. Yeah, maybe there exists an issue open for it. If not, then please open it. There are people in Microsoft who are working on it. There are people in community who are working on it. And I did most of the development, but I'm not actively working at the moment, but the project is still developed. And yeah, please... And if you want to join, that would be fantastic. Basically, there is a Jumpstart document in Contribute NMD. It walks you through how to set up everything, and it has a little bit of documentation about how development is done, how the data transformation works, and that sort of things. It could use a little bit of help, but yeah. So that's a beauty of open source. Please file in issues and feel free to contribute. That would be awesome. I continuously review in the public, and even when I don't do development activity myself, I'm merging good contributions. So in all of your examples here, you heard it, either from New Command, but... Well, you used the existing comment-based help to good-strap the markdown file. One of the reasons I asked is I heard last year that writing in XML, or writing in the markdown was better because your typos would potentially break the actual outputting of the help file. Do you... Once you start using Plot of those, do you move away from comment-based help? Yeah, great question. I should actually be more explicit about it, because it introduces a lot of confusion. So once you use bootstrap step, and once you generate the markdown, you really should start treating it as a source of truth. Like that way, you get the most value out of it. With that being said, I've seen people keep using comment-based help for the help part, and treating Plot of process just a way to create a nice website, and put it on GitHub Weekies or somewhere. So that is valid, and I was really pleased to find that people find creative ways to use the tool. But the intended scenario is once you convert it, once you made a bootstrap, you just delete all your comment-based help, and start using the Plot of PUS. Because I could see what people would want to have the help located alongside their code, but then at the same time, you're basically still doing it the old way, when you're editing and using the comment-based help as a source of truth, and you're just giving yourself more overhead. I could see arguments for both ways, but you hope that ultimately you move to the other paradigm where you started. Otherwise, you'd probably be duplicating your work, trying to come up with some way to generate comment-based help off of your markdown. Yeah, exactly. And that probably wouldn't work. Yeah, there are bonuses of both of them, but I think the right angle to look at it is you write your help not for convenience of yourself to look at it, you write it for customers. Is it a good experience to look at the help by reading the source code? I think if we go that way, we can just throw away the whole help framework and just add commands in the code, and that's good enough, right? So, like, naturally, you want to focus on consuming your help by other people. Okay, thanks. In the early days, I think there was this school where when it pointed to a module, it would tell you what's essentially missing the commentations, or if there are new parameters, and so on. And I guess one of the reasons for having an XML is that people essentially treated us data, and discovered these, and your proposal to discover what is missing the commentations is to do a div. See if there is a div. Yeah, it will tell you what's missing, but if, let's say, if div is more like a developer tool, and if I force a decryder to do that, I'm not sure if they will actually understand what's going on. Yeah. So, is there a way kind of to have the short truth as a markdown, and essentially have it converted into an object model so you could define it more? Yeah, totally. And we really spend a lot of time just making sure that we don't like asking for too much, and we have, like, good stories of backward compatibility. So, one way, I mean, there are a couple ways to approach it. One would be to use new external help, and it creates the XML for you, and then you can use actually get help preview to get the object model. This is, like, I didn't show it, but it returns the object, right? And it's the same object as get help return, so that's pretty neat, and you can div it. Another way to go about it would be to what we implemented for Microsoft writers, and in update markdown help, there is a log path, and you can actually give it, you know, some file name, and it will write to best its ability some trace of what happened exactly. So, you don't need to look at the git div. That way, you can just look at the log path, and from that, you can deduce what changed. Thank you for the question. All right, so I think we will just wrap up a little bit early, and I will be today at the summit. If you have questions you want to ask in person, hit me up. Thank you.
 Welcome to Platypus PowerShell Help Me Smart Down talk.  Thank you for joining me today.  We have a lot of great talk going on.  So just quick introduction about myself.  My name is Sergey.  I work for a couple years on the PowerShell team.  Currently I work at Dropbox as a software developer.  And in PowerShell community I was working on a few projects.  You may see in my avatar, it's PowerShell open source project itself.  It's Platypus, which we will talk about today.  And a couple of small pet projects.  It's the location and sublime PowerShell grammar which is used by GitHub for syntax highlighting as well.  So let's talk about GitHub.  How many of you use GitHub?  Okay, everybody, great.  Yes, because GitHub is awesome commandlet that everybody learn when they learn PowerShell.  It's probably one of the top three commandlets that people told you to start using.  That's basically the way how we figure out how to use our commandlets.  So that's how it looks like.  You just get some nice structured output, name, syntax, aliases, remarks, parameters, and whatnot.  But how actually you get this output?  If you module after, you want to provide help with your module and you have a couple of options to do that.  The first option is if you write in a script-based module, you can use a command-based help in the script.  It looks like this. So you can have a structured command with sections like synopsis, description, and everything else.  And it's very natural to read it.  It's very natural to write it.  And it's probably one of the most popular ways to provide documentation and help for your modules.  The next option is somewhat specific to binary modules, basically the same thing, but for binary modules.  Binary is modules you write in some.NET language, most likely C-sharp.  They look very similar again.  They use XML text instead of this.synopsis and.description.  But again, it's maybe a little bit less readable by just the naked eye, but pretty self-explanatory.  The third option is called MAML XML.  So how many of you wrote MAML XMLs in your life?  Okay, one hand.  Half hand.  Okay, so let's break it down.  Great you've come to the talk.  Glad to have you.  I think we'll learn a lot of cool stuff today.  So MAML stands for Microsoft Assistant Markup Language and XML stands for Extensible Markup Language.  So we have Markup Language twice.  And this is how it looks like.  Oh, no, that's not how it looks like because it can't be load.  Because MAML XML files are usually really gigantic files, many, many megabytes of text.  Basically, imagine something like Azure PowerShell module which has hundreds and hundreds of commands.  And all the help for all these commands is crumbled into one file.  So it's a lot of content.  And for example, this is a view on GitHub.  GitHub cannot handle it.  But I got it covered, so this is how it looks like if you open it in text editor.  If you cannot read it, it's okay.  I will just tell you what the colors mean here.  So the red one is XML text.  The white one is actual content that, you know, people wrote.  And yellow and green is a key value pairs for a bunch of metadata.  So let's have a good mix of all of them.  This is, like imagine now writing it by hands.  You know, it's pretty overwhelming task.  And MAML XML is not very popular among the, like, you know, one-person projects.  You need the special tooling to create it.  And we will address it a little bit later, but just let's make a note that, you know,  it's pretty hard to just, like, open the text editor and start writing MAML XML help.  But it actually has an advantage over command-based help and our command-based help.  The advantage is that it's a separate file.  You ship it together with your module.  MAML-based help also known as external help.  It's external because it's outside of your code.  So let's say if you are a big company like Microsoft or VMware,  then you can hire a team of tech writers and then they can collaborate on the documentation  without involving your source code.  And so they don't actually mess up with development process and it's nice.  It's also the only way to provide help that allows you to ship more than one language.  If you have, like, requirements to have English version and German version,  you basically have to use MAML-based help for that.  Because in the code you can only have, you know, one language.  And another type of help that I don't often talk about is websites.  So when PowerShell was created ten years ago, it probably wasn't that hot.  But now people don't like to read text in the command line that much.  People like to just go to Google and find the help on the Internet.  So websites is something that people build completely separate from GetHelp.  And essentially if you want to have a good online presence, if you want to have a website,  and you want to provide help for your module,  what you do is, like, you build two different documentations.  And now they can get out of date.  You need to have, like, all kind of stories for consistency between them.  And it's just a lot of additional work.  I just want to point out, like, this is example from Google's Google Cloud commandlet.  Get GCDisk.  So they use nice tables for metadata.  They use different syntax highlighting.  They use hyperlinks.  And you can't really get that stuff in your console.  You really need the web technologies to surface it.  So to recap, we have different types of help.  Command-based help is very easy to write and intuitive, and it's very popular.  It's easier than MAML.  MAML has its own advantages if you have requirements for multiple languages,  if you have requirements for update help.  Update help basically allows you to host archives of a new version of the help on a website  and bring them down with update help.  But none of the existing solutions actively address the problem of creating websites  that are not supported from the Get Help content itself.  So with that, I would like to talk a little bit about my personal experience with PowerShell help.  My first project when I joined PowerShell team was Azure DSC extension.  So Azure DSC extension is an Azure marketplace application, I guess.  It contains of two parts.  The first part is a server.  It lives in the virtual machine and users install it separately by checkbox or by running commandlet.  And it has a client part in the form of few commandlets in Azure PowerShell module.  So Azure PowerShell module is an open source hosted on GitHub by Microsoft.  Probably one of the first big PowerShell related open source projects.  So to implement this extension, what we did is we add a few commandlets into Azure PowerShell.  It took a few months and we figured it all out, but then after some time we actually found that we forgot to add help.  So it wasn't good and we need to fix it quickly.  That's how I started to basically learn and think about what's the documentation story in PowerShell.  The workflow was like the following.  Azure PowerShell use MAML XML.  So they have this one file that can be loaded on GitHub from a previous slide.  There was no specified workflow anywhere in documentation repository.  And basically you just need to figure out for yourself how you want to approach it.  So as I mentioned, to edit this MAML XML we can pick up some tools.  I know about three tools, maybe there are more.  One of them is internal Microsoft tool.  It's very nice. It can connect to a database and you can collaborate with other people by using the database as storage.  But it was internal and it doesn't fit the build of working in the open with community.  So the next tool is the Suncastle.  Suncastle is a free project.  Its name is actually not Suncastle.  Its name is Suncastle Help File Builder, SHFB.  But I will just say Suncastle for simplicity.  The workflow looks like this and basically that's true for all the available tools.  You import your module from maximal form into some internal representation inside the tool.  Then you have nice UI with Windows where you can edit it.  You can add new parameters and new commandlets.  And then the last step is basically experts.  So it was pretty painful expert for the following reasons.  Internal representation of the XML basically forgot all the formatting.  And all white spaces get replaced by tabs or vice versa.  All the text formatting changed like indentations.  And in one place this indentation was one way and now it was another way.  In XML you can have commands.  So commands wasn't preserved.  And as a result of all that if you just take the diff and submit pull request to Azure PowerShell,  they will have a really hard time reviewing it.  Because you have a mix of from item changes, some good from item changes, some bad from item changes,  and some actual content that you add.  So that just puts a bunch of burden on the maintainers who needs to separate all these things  and give you go and all go.  On top of it they cannot use web interface because this file is so gigantic  so they need to find a ways to review it locally and it's a whole nother story.  Okay, so we have this problem of not preserving the formatting.  Basically the best solution I found was to open original file in a text editor.  Open new generated file in a text editor and find the corresponding block  and like drag and drop selection and just copy it.  That works but it's pretty error pruning and it's not fun unless you think it's fun.  And I had a really hard time and a few times I actually had a problem that I forgot some tag in one place.  So now XML became invalid and there is no good way to test it.  It's valid or invalid until you load the help and get help and then you see that nothing displays.  So that's pretty, like that's a lot of process around simple changes in documentation.  Okay, I hope I convinced you that we need a better story for that.  So let me introduce Platypus.  It's a project that basically tries to solve all these problems I just outlined.  So we have two parts of equation.  We want something for the web and we want something that can be consumed by help engine.  And ideally we basically just want one source for all the to avoid doing duplicated work or some synchronization.  The help engine part, we basically have two options.  We can provide command-based help or we can provide MAML XMLs.  Because, okay, so one of the approaches to solve it would be to have some third format, not website, not the command-based help,  but something separate from them which is easy, can be turned into the website and can be turned into the help engine help, consumable format.  Okay, so with that motivation, it's probably no surprise that command-based help is out of the table  because if you want to just generate something, it would be really hard to insert it into the code that already exists.  So MAML XML fits the build perfectly.  We basically just start to treat our MAML XMLs as kind of binary, if you wish, like DLL that you compile.  And you just have this build step when you generate the help out of something like some third format.  And this third format, because we want a website as well, it should be something very close to the web technologies.  So people build websites for a long time and basically the amount of people who build websites is pretty big.  It's bigger than PowerShell community.  So they actually create a bunch of nice tools for doing that stuff.  One of the problems with just writing raw HTML is that it's not very scalable.  It's just cumbersome, so people actually don't write raw HTML by hands anymore.  One of the approaches to create a static web content is to use a markup language.  And one of the very popular markup language is markdown.  Yes, so and then we come to a demo.  So Platypus, okay, let's get back.  Basically, Platypus allows you to take a markdown and turn it into MAML XML, which can be later consumed by the help engine.  And because it's just a markdown, then the website story is already solved.  You can just turn it into a website and there are plenty of existing tools to do that.  So yes, now demo time.  I will show you the markdown and the results in XML.  Is font size okay?  So we start with just importing Platypus into the session.  And I wanted to show, I already prepared the markdown and this is how it looks like.  And you can see that it basically loosely resembles the output of get help with some fancy block at the top.  But let's ignore it for now.  And then, like I guess, you know, if you're familiar with get help output, you can basically figure out how this structured.  There are some fancy backticks here and there, some hyperlinks and all that stuff.  But let's just take a look at how it will look like when you render it as HTML page.  So Visual Studio Code has this nice feature, markdown preview.  And basically that's what we will get if you just turn this markdown into HTML.  So you get like headers, you get hyperlinks, you get code snippets and all that good stuff.  So this is, you know, as far as I'm concerned, looks very good.  You can put it on the Internet and people can consume it.  It's maybe not as fancy as Google's version, which has tables, but it's pretty decent.  So now, like I showed you first part of equation, let's take a look at the second part of it.  How we take this markdown and turn it into get help.  So I picked new external help markdown as example because we will basically use new external help on new external help to produce some output.  So let's actually first take a look at all the commandlets that are available in Platypus module.  So there are like about 10 of them and the core, like the heart of the whole module is this new external help.  The turning markdown into the help XML is actually the hardest part and all that.  So let's give it a try.  So we can provide path to new markdown, a new external help MD and we can say output path out.  We just need to give it a directory.  It can exist.  It may not exist.  It will create it for us and we get an output.  So let's take a look at this file.  So this is XML you can see and it basically has all the content that we wanted.  So we can just take this XML, ship it with our module and we are done.  Oh, yeah.  I forgot to show one more cool thing.  So I just show the XML, but it would be really nice to know how this XML will look like when it's outputted by get help.  So for that we have another commandlet in the toolbox, get help preview.  Get help preview takes path parameter to a file and it outputs what the get help will output only like if you use this file as a help basically.  So let's scroll it up a little bit and take a look at all this stuff.  So the name synopsis looks good.  Let's just, you know, kind of spot check that we have the same content here and in the original markdown.  So I just use search.  Okay, sure enough, basically output path looks like this here and it looks like this here.  And that can be applied not only to a single commandlet and single file, but it can be applied at scale.  Let's actually take a look at this guy.  I have Platypus docs directory with basically like kind of docfooding all the documentation for Platypus itself.  So let's turn all this documentation into XML file.  So it thinks a little bit longer.  And now it outputs just a single XML for all the help and it also outputs about topic which we'll talk about in a bit.  Actually, I think, yeah, that's right.  Time to talk about about.  So how many of you wrote about topics in PowerShell?  So they are less popular.  Yeah, like we can see it's less popular than like traditional help.  And I will just demystify them a little bit.  Basically about topics.  Let's take a look at this one and about TXT.  So this is, I mean, the extension TXT is no joke.  It's really text file.  There is no formatting whatsoever.  All this crazy XML I showed for the commandlet based help for the XML help.  They're not applyable for the about topics.  Basically about topic is just the text file.  So it's pretty easy to just go and write it by hands, no problem.  But as soon as we start to talk about the story of having a website, it would be nice to incorporate about topics in the structure of our website.  We can have same formatting, same hyperlinks and everything, you know,  cross reference topics from about into the commandlets and vice versa,  and just have like a solid story for all types of PowerShell help.  Yeah, by the way, about topics can be accessible if you do about help, about something like this, about platypus.  For example, it basically just outputs with text file.  And let's take a look at how platypus handles about topic creation.  Oh, no, this demo is a little bit later.  But that's fine.  Let's do it now.  It's pretty short demo, just one line.  So to create a new about topic, what we do is we need to call new markdown about help,  and we need to pass about name parameter.  And in this case, I will use greeting.  Okay, it will make sense after a second demo, why greeting.  And let's take a look at what we output in about greeting markdown.  So what we output is, you know, looks like markdown and there is just a bunch of placeholders that you need to fill up.  But once you do it, you can use the same new external help commandlet to translate markdown into the text file that you can ship with your module.  All right, so let's get back to presentation.  So to talk about platypus, we first need to talk about markdown.  How many of you use markdown?  So almost everybody, most people.  For let's give it 60 seconds refresher.  So one of the beautiful things about markdown is that it's so natural and so easy to learn that you really need only like 60 seconds to pick it up.  So here we go.  This is the basics of markdown.  We have a line, we have another line.  If we have only one line break between them, they will form a paragraph.  So line break kind of serves as a space.  If you do two line breaks, you start a new paragraph.  For headers, we use hash.  So if you have one hash, it will be header level one.  If you have two hashes, it will be header level two.  For bullet point lists, we use dashes or also asterisks.  And for number lists, we use one dot, one dot, one dot.  You can also use one dot, two dot, three dot, but it's not necessary.  It will automatically numerate it for you.  For hyperlinks, we use this syntax with square brackets and brackets.  And for codysnipids, we use a triple back tick.  And there is a non-mandatory language specifier.  So if you want to have a syntax highlighting in the snippet, you can actually say what language it is.  So that's pretty much markdown for you.  If you want to recap at home, there is a great resource.  We've learned that in 60 seconds.  It's a common mark.org help.  They also have a 10-minute version of the same tutorial with more details.  And now we can actually take a look at more demos.  So now we know markdown.  The natural question to ask is, OK, who will write all this markdown?  Like so far, what I tell you is, hey, I came up with this format for help, and now everybody should start using it.  But that's not how it works, because people already using some tools, they created documentation in command-based help in MAML.  So just to ask everybody to start to use markdown for help is not a very clever thing, because it's a lot of work to create it.  So to address this problem, we actually have helper functions to bootstrap all your markdown documentation.  So here I just have a kind of hello-worthy function, very small.  Let's go through it very quickly.  We have parameter block.  We have command-based bindings, which means that we have advanced function.  So we have things like common parameters, out variable, and all that stuff.  We have one parameter in parameter block with mandatory set to true and value from power plant set to true.  The name of parameter is name, and it does a very useful process block here.  So let's give it a shot and try it out.  New, getting.  Okay, so that works, and let's just test out the piping from piping.  Just piping.  It's not getting, it's new greetings.  Okay, that also works.  Cool, so let's say I want to create a help for this commandlet.  All I need to do is use new markdown help commandlet and specify command name.  So command should be in the PowerShell session already.  And yeah, we have top completion here, which is pretty awesome.  And we need to specify output folder, so let's use our output folder where we put all this stuff.  And just output it with markdown.  So let's take a look at what did it output for us.  So we again have this metadata block, let's ignore it for now.  And then we have a name of commandlet.  We have synapses.  And here we have a first placeholder, which tells us fill in the synapses.  And let's actually just search for all the placeholders in this file.  So in Platypus, we use double curlers for the placeholders, and there are like five of them.  Unfortunately, like Platypus cannot read your mind, so it cannot fill up with text fields for you.  But it's still much easier to just go and fill up five fields than to write a whole XML.  So let's actually populate these placeholders.  I will just copy paste some descriptions to avoid typing on the demo.  So for example, we will use, we put the code here, and you can see that it has this triple-backticks power shell,  which means that the whole thing would be syntax highlighting as power shell.  I really like when people in the examples in the help put the output of the help as well as the command.  That's very useful.  So let's actually do it.  It's just a good practice.  I will just copy this output.  And now I have two choices.  If I just put it like this, the whole output would be highlighted as power shell,  which is not exactly what we want because it can be some arbitrary text.  So to avoid doing the highlighting on the second part, we can just break this code snippet into two code snippets,  and then the first part would be treated as input and the second part as output.  So we need to provide the description, for example.  Okay, we have spell checker saved us.  And the last placeholder we need to populate is name.  Let's just double check that we don't have any more placeholders.  And let's take a look at these parameters, at this parameter metadata block.  So you remember that our name parameter was a required parameter, and it's already said required true.  It also has a set pipeline input set to the proper value.  So that all that stuff we get for free just by running new markdown help.  We don't need to touch this metadata block by hands.  All we need to do is just go and write the strings, create some valuable content that cannot be after generated for us.  And we have this command parameters because it's advanced commandlet.  Okay, so now let's see can we turn this markdown into external help.  We are already familiar with new external help.  We give it actually, yeah, that's fine.  New external help, let's give it path out new greeting.  And as output path, I will use NUS.  So that way I will just put it in the default locale, and later PowerShell help system can pick it up from this NUS folder.  So now what we need to do to see this help live from GetHelp, we just need to reload the module.  So zero to greeting, and we need to use force for that.  And now if I just say GetHelp new greeting, I should, let's use full.  I should see all the content we just after it right here.  We have the example, we have synopsis and everything else.  Okay, so the next demo was about, which I already showed.  And now let's take a look at doing the same thing, but at scale.  So I just found this GetHelp issue.  Can you tell me the password?  I knew I forgot something.  And that was a Wi-Fi for the demos.  That was great.  Let's try it one more time.  Okay, cool.  And this side is good.  So this is just a PowerShell module for Atlassian that allows you to optimize GER.  And basically they're talking about, hey, let's migrate our documentation to Markdown, let's migrate it to Placipus.  And this issue was filed in July 2017.  So let's see how long it takes to migrate the help.  We have GERA, oops, GERA PS here.  So let's import it.  PSD1.  So it's loaded everything.  Let's take a look at all the commands in this module.  The fair number of them.  And now we can just say new Markdown help.  And I will use another variant, not just a command, but the module.  And we have type completion for modules as well.  And as an output folder, let's use something like Out2.  And it just starts to pop out all this Markdown for all these files.  And it looks like 30 seconds to basically bootstrap help for this big module.  Now let's take a look at the result of this bootstrapping.  So because Atlation already had command-based help for these modules,  Synapses, we don't need to populate it.  It's already there.  And the same goes for everything else.  We already have examples.  We already have parameters, descriptions here, and everything in between.  So if you start to go through all this generated Markdown,  what you will find very soon is that at some point there is no documentation.  So we, again, get in the same placeholders.  And this is basically a good way to make sure that you have all documentation.  Like even if you're using command-based documentation,  you can just run Platypus and then search for placeholders.  And if there are no placeholders, then that means that you covered everything.  And if not, then you can just go and add this help.  Yep.  So that was bootstrapping for Jura module.  Now we already covered just plain Markdown.  And I showed you how you can use Platypus to generate Markdown  and how to use Platypus to generate help out of Markdown.  And now we can talk about the Markdown that is specific to Platypus.  So Markdown is, as I mentioned, a really great, easy-to-learn Markup language.  But it has this unfortunate property that any text is basically a valid Markdown.  So, you know, that kind of a problem because you cannot expect Platypus to just magically figure out  what did you mean from some abstract Markdown document.  You need to comply with a schema.  And Markdown doesn't have schema built-in.  Unlike things like JSON and XML where you can specify schema and validate against the schema,  Markdown doesn't have such thing.  But we need it because that's how the tool can, you know, know that this synopsis thing is,  corresponds to synopsis.  So the schema leaves in this, basically, the development of Platypus happens in this PowerShell Platypus repository on GitHub.  And there is a top-level file, Platypus schema, MD, which kind of goes into all the, like, very subtle details  that you may want to know one day.  But now we're not going to go through it.  What we will do instead, we will just look at examples.  So, because, as I said, Platypus schema is modeled after the GetHelp output.  So, basically, if you know GetHelp output, you should be able to just pick it up.  The first thing is name.  And for name, we use header level one.  Pretty self-explanatory.  For synopsis, we use a level header two for names, for the word synopsis.  And then the text block that goes after it becomes the synopsis.  Same goes for description.  And here you can see an example of using bold, I didn't mention it on my 60-seconds intro about Markdown.  But when you have double asterisks, it's bold in Markdown.  And you can see example of using some rich formatting in the Markdown,  which later just tips out during the translation.  So, you know, again, to the common theme of having the same source for both GetHelp and the website,  you don't need to compromise for that.  And you can still use rich formatting.  The next one is examples.  So, examples is a section that contains subsections.  Basically, how many examples you have, you just put them as a subsections,  and they become header level three with three hashes at the beginning.  So, the title becomes the title, and we automatically pad it with dashes,  which is actually very nice, because it's one of the many inconsistencies in existing PowerShell documentation.  These dashes, you don't get them for free from GetHelp,  you actually need to write them down in your XML to get it look nicely.  Then we have a code snippet block, fenced by triple-bactics.  And as I mentioned, you can break it down into two pieces,  you can break it into the code snippet and the code output.  So, in this case, we actually didn't do that, we just put everything without syntax highlighting.  And then the text after the block becomes the description of example.  So, parameters is again contains of multiple subsections.  Every parameter gets its own section, its name starts with dash,  the same thing as in GetHelp output.  And let's take a look at the metadata part.  When I circled here, oh, you see it, cool.  So, this metadata, it's actually, you can see it's break by new line break,  and the second half is just completely the same as parameters metadata here.  Then type string array in this case, it basically comes from the type string in parameter.  And aliases is actually something that not shown by GetHelp for some reason,  but it's good to have aliases for parameter.  And the last one is parameter sets list.  And you wouldn't find the direct correspondence into GetHelp output  because GetHelp uses syntax block to provide information about the parameter sets names.  But it was just easier to basically put everything into one place in parameters.  And the syntax block actually brings us into taking a look at the syntax block in Platypus.  So, the important thing that a lot of people miss is syntax block in Platypus is view only.  It's kind of like read once and forget.  So, it's not used as part of new external help generation.  It's like all the metadata already present in parameters block.  So, syntax block really exists only for the online, like for the website purpose there.  So, you know, you like, you know, we need to edit it by hands.  It will be always just after generated for you.  The next field is input output.  Again, very self-explanatory.  You can have multiple of them.  You can have multiple level three headers.  And the last one is related links.  So, the related links is usually at the bottom of your help.  And you can see that just normal markdown links get translated into kind of key value pairs in PowerShell.  And the PowerShell version has one additional link at the top, online version.  So, this is not very well known, but when you run get help dash online,  what happens is a help system looks into all the links you have and it opens the first one.  So, we kind of decided that it's better to be more explicit about this.  So, that's why we put online version in this top level metadata to make it more obvious how it works.  And what is, like, let's talk about this top level metadata.  Basically, in markdown there is a standard extension which allows you to put YAML,  any arbitrary YAML file at the top for the metadata purposes.  We kind of using poor man's version of it.  We just use key value pairs. We don't support the full YAML.  But that's enough for our goal.  And it has four fields that Platypus understands.  External help file, module name, online version and schema version.  You can put more stuff there.  It's basically just a back of key value properties.  And the reason is people want to build, like Microsoft, for example,  they want to create some workflows for the documentation and they need some inventory to reference the topics  and they put some GUIts with some names and maybe language, moniker and whatnot.  So, yeah, that part can be basically used for your own workflows, for your own customizations.  Oops.  Oh, I need something.  Should I pick this?  Mark, man.  So, life cycle.  Basically, let's say you write your module, you write your documentation once,  and then six months later you actually want to edit it.  And this is very common, basically.  The modules are not static things you created once.  It's a living, breathing being.  So what kind of modifications do we usually see?  People add new commandlets, people add parameters to existing commandlets,  people add new functionality, and this functionality requires new examples in the docs.  And, like, parameters get renamed and just some alias get added.  So that would be great if we can have a good story about how you can update your module with,  how you can update your help with your module.  And now I will just show you just that.  Okay, so this is actually a folder.  Let's take a look at it.  We have a PSM1 file, and it's basically our old friend, new greeting.  Nothing unexpected here.  But let's say that after some time I decided that it's a good idea to add a new parameter.  And instead of just having hard-coded hello, I now want to have a greeting verb, I guess it's greeting noun.  And now my process blog just becomes beautiful, concatenation of three things.  So let's copy it into the greeting update.  I will just show you git diff.  So this is basically a diff of my change.  And let's take a look at help for this command now.  So I import in module update.  So now let's verify that we have a new version of a module loaded.  Greeting name and greeting one, two, three.  Great greeting.  So yeah, we have an updated version of a module loaded.  But in our docs folder right here, we have an old version of documentation.  So let's take a look at it.  It's old because we in the parameters section, we only have name, but we don't have greeting.  So this is a situation you will commonly find yourself in.  All you need to do is simply run one command, update, markdown, help.  And then you just pass path to a folder with all your documentation.  And voila, we just get a new parameter here.  And this green stripe at the left basically indicates that it's addition.  And we also get the same thing into the syntax for free.  So you never, like, you add parameter, you don't need to edit it.  Just takes care of.  All you need to do is now provide description.  Now we can create external help out of it and load it into the module the same way I already showed.  Why don't you change the type of existing brand name, change to string arrays instead?  Yeah, that will be, let's actually try it.  That's a great example.  Like this, right?  Okay, so that didn't work.  Maybe it's actually a visual study code.  Let's reload it just to make sure.  Oh, I didn't reload.  Yeah, that's a good catch.  That should work.  You know, if it doesn't work, it means we have bug and we have bugs sometimes.  Yeah, so it did update.  So essentially, you don't need to ever touch this metadata block.  You know, it's already automated for you.  There is one caveat, actually.  I will give it up.  You see how we have greeting equal hello.  So we actually have default value for greeting.  But there are some unfortunate help engine limitations and we didn't update default value.  I'm not sure that it is possible.  I think when I look into it, I found that we just don't have a right way to get this value out.  So you actually need to edit, like maybe default value is like the only one that you need to edit by hands.  Good question.  Okay, so let's just really quickly.  Let's import the module and let's get help.  Okay, so now we have both parameters here.  Let me double check that it's all I want to talk about here.  Yep.  Okay, so and now a bonus.  Because we use Git for version control.  This is how Diff looks like.  Let me just create a temporary branch and make a commit.  Demo.  Now Diff should be empty.  And we should be on branch demo.  Okay, so let's run update help one more time.  And run Git Diff one more time.  Okay, so you see here we try to run update and we made sure that there is no Diff between the previous state and current state.  What it means is now you have a very simple test to tell is your help out of data or not.  Did you add any parameters or not?  And you can basically take these simple couple lines and you can put it into your continuous integration pipeline.  And it will basically enforce that the help is always up to date.  And this is actually a theme of our next talk section.  So, yeah, CI or continuous integration is great.  You can leverage it like the common ways to use continuous integration to run tests and make sure all the tests are passing.  But you can also use it in creative ways.  For example, you can make sure that the commutation is up to date.  And I just showed you example script.  It's not like one liner, but it's maybe two lines to get it done.  But the even better part about it is that once your help is in markdown, now you can leverage all this great work done by the web development people who created things like spell checking for markdown, created hyperlink checking.  So hyperlink checking is very important.  It's like my pet peeve because what happens is let's say you have like 100 markdown documents and you refactor them somehow, you like split or merge or rename something.  And you have always hyperlinks rolling around and part of them became invalid and you don't know until you like, right, until somebody reports it to you.  So you can easily automatically test it with some scripting.  And spell check is also self-explanatory.  And this is what I just did as a demo.  I set it up repository pedantic CI demo.  So it's probably one of the most pedantic projects because it will make sure that you have your grammar correctly, you have your hyperlinks correctly and that your help is up to date.  So let's take a look at it.  Let's start with the code.  This is our well-known friend, new greeting.  Sorry.  Good catch.  Yep.  So this is, I just put up this docs pedantic CI demo repository.  We have continuous integration bridge from Upware.  So we will use Upware as a continuous integration system.  Upware is, I mean, it's like Jenkins, but it's hosted.  So you don't need to care about where you're going to host it.  And it's also free for open source projects, which is awesome.  And, you know, for like demos, especially, I highly recommend to use Upware.  We'll take a look at it in a bit.  But first, let's take a look at source code of our module.  We have our beloved new greeting function in the old version.  We've hardcoded hello.  And we have documentation for it in docs.  This is actually, yeah, I think it's the first time I'm showing you how the markdown,  like rendered markdown looks on GitHub.  So as far as I'm concerned, it looks pretty good.  You can use some static website builder to make it, you know, to make styles as you see fit.  You can build static website of markdown.  But even as it is, even like simple act of putting your help on GitHub already gives you pretty nice experience for viewing.  And as a bonus fact, it is also indexable by Google, so now people can actually find your help.  So, like, I think it's good back for a buck.  And let's take a look at this Upware YAML file, which is actually describes the continuous integration steps.  So it's actually YAML files, so we have YAML syntax.  We will be mostly interested in this test script section.  But let's read it, the whole thing.  So we just installing some modules, platypus, obviously, markdown link check, module to check the links.  And we install some spell checker from NPM from Node because they have better, like, I didn't find the partial module for spell check.  So had to use Node.  That line just helpful for dealing with new lines.  And because I am demoing on mark and I use Windows for the continuous integration, basically, just takes care of that.  So we don't get empty divs.  That contains just new lines.  Build script, here, we don't build anything, we just import it in the session.  And here is an interesting part, so the test script.  We have two free steps.  First, let's make sure that our help is up to date.  We run update markdown help just as I did locally.  We run get div.  And then if give is non-empty, then we throw and we display what's the div in update markdown help.  So this is, I just want to bring your attention to this part because it's, you know, a contributor coming and committing something in your repository.  They should get some useful error messages, not just that everything failed.  So please include as much information and error messages as you can.  The second part is very fine hyperlinks.  I didn't talk much about this hyperlinks module, but basically you can give it a folder and you can say broken only.  And if there are any broken links, it will return them.  And the last one is spell checker, so this is not PowerShell.  So we just run some interesting command with a bunch of switches.  And report basically makes it non-interactive, like by default it runs as interactive command.  And report just generally, it's a general report.  It uses last exit code for, it basically returns one if anything failed.  Or maybe it's number of errors.  Don't remember.  So with that, let's actually take a look at pull requests now.  So they're all from me, but imagine that somebody sent the first one.  And this person had a brilliant idea to add greeting into your code, but they didn't do anything about the help.  So what happens next?  Next, they get in this gigantic red crosses.  And if you click on details, you can open it.  This is the up-wear interface.  And you see the whole log of things that happen.  And the last one is writing your face red error message.  And it tells you run update markdown help and then some def.  Well, it's not very well-formatted.  It could be formatted better, but it's something.  Okay, so now this person runs update markdown help and sends the second pull request.  And this time they actually, let's take a look at the def.  So we have the same def here.  We have basically syntax updated by update help and greeting.  And this person was really nice and specify the description and replace the placeholder,  which people can often forget.  And this person even specify default value.  So he knows about this quirky box in Platypus.  But he decided to be extra fancy and add related links section.  And he made a mistake in referencing to read me.  So now this link is actually broken.  Let's take a look how the continuous integration system will handle it.  Well, sure enough, we have found broken hyperlinks and it actually gives us all the information we need.  It gives the file path URL and line and column.  Okay, so now this person takes it one step further and fixes the hyperlink.  So right here we have read me, but language is still misspelled.  And sure enough, our continuous integration system can catch it.  And this is not very helpful error message, but if you look up, you can see that it outputs the line.  When you run it locally, it actually highlights the word language, up where it loses this highlighting.  So not as good as it could be, but still something.  And the final chord is when the person fixes the misspelled word.  And let's actually take a look at up where I would put anyway.  You can see it's all green, but just to make sure, yeah, it says build succeeded.  So that's probably, for some projects, it's maybe overkill to have all this spell checking and whatnot.  To be honest, to make the spell checking works, you need to add a huge exclusion list, like white list, for a lot of stuff.  But the PowerShell repository uses this spell checking actually.  You can come up with creative ways to verify that maybe you like your markdown to be after it in a certain way.  You don't like long lines. I don't like long lines personally.  It basically asks everybody to always break it into smaller pieces because it's easier for a view.  You can express all these constraints now in the continuous integration system.  So another bonus fact, another bonus of using continuous integration in conjunction with documentation is that you don't have to tell people to do what you want them to do.  You can make robots do them, robots tell them what to do.  And this is just a human nature.  People really don't like to be told what to do, but if it's a machine, then they're more willing to collaborate.  So the lesson, if you want to introduce a new workflow in your organization, don't be codenuts.  Just make some automation that enforces it and introduce it this way.  Okay, so recap. With Flattipoost now, you can put your help online.  You make it available.  If you use GitHub for hosting of your help, it's basically free hosting solution.  It gives you a very nice interface.  That way, you actually make it contributions friendly.  And this is one point I want to talk about.  Even if you don't do open source, let's say you're doing some preparatory software, there is no point of keeping your documentation closed.  You can just create a separate repository, put it online.  This is a chip hosting solution.  You allow people contribute back. So if somebody spots a mistake or just a typo, they can contribute now.  So, yeah, that's basically an approach that a lot of companies take.  Up to date, so your help can be up to date.  You can enforce any kind of rules and markdown you want.  You can tailor it to your needs.  Maybe, you know, again, the spell checker is every key for you, but links are great.  And this is a list of projects that already use Flattipoost.  Basically, the PowerShell docs is a core modules.  Azure PowerShell is my personal favorite because that's how it all started.  Basically, my whole motivation was to make Azure PowerShell collaboration work good.  PSV line is the first adopter of Flattipoost, big kudos to Jason Sherk for being a brave adopter.  I was searching in GitHub who uses Flattipoost by some keywords and I'm not sure what it is.  The recent addition is Office PowerShell, which actually has thousands and thousands of commands.  And they use all the same tool chain that I described, they use GitHub, they use Flattipoost, they also use DocFX for the nicer website version, which you can also use.  And with that, I would like to ask you to join this list of great projects and give Flattipoost a try.  We... So with that, I would like to talk a little bit about the future of PowerShell help documentation.  So if you follow GitHub, you may see this issue created by Steve Lee, who is a team lead on PowerShell team.  And it says, help system should consume markdown natively.  And if you follow another repository, PowerShell RFC, you may see another issue created by Ditya, help system as a standalone PowerShell module.  So I think you can see where it's all going.  Basically, there is a desire to cut, man in the middle, cut this translation from markdown into external help, because you don't really need it.  You can just display markdown.  If you can render the same thing in console and then on the web, like why we have a whole transition story?  So with that, it's basically... Flattipoost is not like a final destination in this journey.  It's a stepping stone to basically provide a smooth transition to a better and more modern documentation tool chain for PowerShell.  We can only do it if we all start to... If we all converge on it, basically.  If we introduce it as a standard in the community and in Microsoft, then we can hope for a better documentation story.  If it doesn't get traction, then it will be like the current state, which is also fine, but we can do much better in my opinion.  So with that, thank you.  We actually have a lot of time, so if you have any questions, that's a good time.  Do you know what they transfer to markdown? Are they going to backport back to older versions of PowerShell?  Yes, so let's take a look at the PowerShell docs. It's already backported.  Oh, you mean...  Like when they switch over from MAML, is it going to be compatible with old PowerShell markers?  So let me answer it in two ways.  So the question is, if we go and translate to markdown, would it be backported?  So I will answer in two parts. The first one is it's already backported in the sense of content.  So let's take a look at the PowerShell docs.  This is core commandlet's modules, and it has obvious folder reference for everything.  And then you can see the 3.0, for example. You have all the content right here.  And the second kind of building on this question is, let's say that tomorrow we have some great way to display markdown in the console in PowerShell.  It can totally be a separate module downloadable from the gallery.  Good question.  The update help? How does the version work? Where you can put out the source or where the download slides from?  That's what's being in the MAML somewhere?  Yeah, exactly. So I conveniently have it right here.  This online version actually points...  Okay, no, I not conveniently have it here. I conveniently have it right here.  Okay, right here.  So if you want to leverage updateable help, you can use what we call module help.  Basically, it's a kind of table of content markdown file with description of the whole module,  and then basically links to all the single commandlets.  And in this document, you can specify download help link.  And we basically try to make the flow of using updateable help as easy as possible.  So we have a new external help cap, I guess.  Yeah, new external help cap, which takes care of packing everything in the right format.  You just need to put it on the right URL after that.  Good question.  When you have that module page, it sure is just...  And you do that if you have a new project and you do external help on that,  and use that switch with module page, you get a page very similar to that.  And you still have to fill in the description for every command that you make.  Oh, yeah, that could be better. We can pull up synopsis, right?  That's not been done yet, but it could be better.  Yeah, yeah, and that's a great question because what I would like to show you is a place for such questions,  basically on GitHub, oh my...  I think it does pull synopsis.  There's synopsis in the library.  I see.  Yeah, maybe there exists an issue open for it.  If not, then please open it.  There are people in Microsoft who are working on it.  There are people in community who are working on it.  And I did most of the development, but I'm not actively working at the moment,  but the project is still developed.  And yeah, please...  And if you want to join, that would be fantastic.  Basically, there is a Jumpstart document in Contribute NMD.  It walks you through how to set up everything,  and it has a little bit of documentation about how development is done,  how the data transformation works, and that sort of things.  It could use a little bit of help, but yeah.  So that's a beauty of open source.  Please file in issues and feel free to contribute.  That would be awesome.  I continuously review in the public,  and even when I don't do development activity myself,  I'm merging good contributions.  So in all of your examples here, you heard it,  either from New Command, but...  Well, you used the existing comment-based help to good-strap the markdown file.  One of the reasons I asked is I heard last year that writing in XML,  or writing in the markdown was better because your typos would potentially break  the actual outputting of the help file.  Do you...  Once you start using Plot of those, do you move away from comment-based help?  Yeah, great question.  I should actually be more explicit about it,  because it introduces a lot of confusion.  So once you use bootstrap step, and once you generate the markdown,  you really should start treating it as a source of truth.  Like that way, you get the most value out of it.  With that being said, I've seen people keep using comment-based help for the help part,  and treating Plot of process just a way to create a nice website,  and put it on GitHub Weekies or somewhere.  So that is valid, and I was really pleased to find that people find creative ways to use the tool.  But the intended scenario is once you convert it,  once you made a bootstrap, you just delete all your comment-based help,  and start using the Plot of PUS.  Because I could see what people would want to have the help located alongside their code,  but then at the same time, you're basically still doing it the old way,  when you're editing and using the comment-based help as a source of truth,  and you're just giving yourself more overhead.  I could see arguments for both ways, but you hope that ultimately you move to the other paradigm where you started.  Otherwise, you'd probably be duplicating your work,  trying to come up with some way to generate comment-based help off of your markdown.  Yeah, exactly. And that probably wouldn't work.  Yeah, there are bonuses of both of them, but I think the right angle to look at it is  you write your help not for convenience of yourself to look at it, you write it for customers.  Is it a good experience to look at the help by reading the source code?  I think if we go that way, we can just throw away the whole help framework and just add commands in the code,  and that's good enough, right?  So, like, naturally, you want to focus on consuming your help by other people.  Okay, thanks.  In the early days, I think there was this school where when it pointed to a module,  it would tell you what's essentially missing the commentations,  or if there are new parameters, and so on.  And I guess one of the reasons for having an XML is that people essentially treated us data,  and discovered these, and your proposal to discover what is missing the commentations is to do a div.  See if there is a div.  Yeah, it will tell you what's missing, but if, let's say, if div is more like a developer tool,  and if I force a decryder to do that, I'm not sure if they will actually understand what's going on.  Yeah.  So, is there a way kind of to have the short truth as a markdown,  and essentially have it converted into an object model so you could define it more?  Yeah, totally.  And we really spend a lot of time just making sure that we don't like asking for too much,  and we have, like, good stories of backward compatibility.  So, one way, I mean, there are a couple ways to approach it.  One would be to use new external help, and it creates the XML for you,  and then you can use actually get help preview to get the object model.  This is, like, I didn't show it, but it returns the object, right?  And it's the same object as get help return, so that's pretty neat, and you can div it.  Another way to go about it would be to what we implemented for Microsoft writers,  and in update markdown help, there is a log path,  and you can actually give it, you know, some file name,  and it will write to best its ability some trace of what happened exactly.  So, you don't need to look at the git div.  That way, you can just look at the log path, and from that, you can deduce what changed.  Thank you for the question.  All right, so I think we will just wrap up a little bit early,  and I will be today at the summit.  If you have questions you want to ask in person, hit me up.  Thank you.
PlatyPS_0_59.png PlatyPS_60_131.png PlatyPS_132_539.png PlatyPS_540_9563.png PlatyPS_9564_27011.png PlatyPS_27012_27071.png PlatyPS_27072_27203.png PlatyPS_27204_27275.png PlatyPS_27276_27395.png PlatyPS_27396_27635.png PlatyPS_27636_27707.png PlatyPS_27708_27791.png PlatyPS_27792_27839.png PlatyPS_27840_28775.png PlatyPS_28776_29183.png PlatyPS_29184_30971.png PlatyPS_30972_32315.png PlatyPS_32316_32531.png PlatyPS_32532_33443.png PlatyPS_33444_34415.png PlatyPS_34416_34823.png PlatyPS_34824_35063.png PlatyPS_35064_35231.png PlatyPS_35232_35543.png PlatyPS_35544_36611.png PlatyPS_36612_38903.png PlatyPS_38904_39707.png PlatyPS_39708_39899.png PlatyPS_39900_40703.png PlatyPS_40704_40751.png PlatyPS_40752_41003.png PlatyPS_41004_41327.png PlatyPS_41328_41435.png PlatyPS_41436_45203.png PlatyPS_45204_45263.png PlatyPS_45264_46199.png PlatyPS_46200_46439.png PlatyPS_46440_47519.png PlatyPS_47520_47807.png PlatyPS_47808_48467.png PlatyPS_48468_49475.png PlatyPS_49476_49607.png PlatyPS_49608_52043.png PlatyPS_52044_52175.png PlatyPS_52176_53075.png PlatyPS_53076_55007.png PlatyPS_55008_55295.png PlatyPS_55296_55343.png PlatyPS_55344_55499.png PlatyPS_55500_56915.png PlatyPS_56916_56999.png PlatyPS_57000_57059.png PlatyPS_57060_57131.png PlatyPS_57132_57407.png PlatyPS_57408_57515.png PlatyPS_57516_57851.png PlatyPS_57852_59327.png PlatyPS_59328_60791.png PlatyPS_60792_60851.png PlatyPS_60852_60911.png PlatyPS_60912_60995.png PlatyPS_60996_63143.png PlatyPS_63144_63239.png PlatyPS_63240_63359.png PlatyPS_63360_63479.png PlatyPS_63480_78743.png PlatyPS_78744_78911.png PlatyPS_78912_79127.png PlatyPS_79128_79283.png PlatyPS_79284_79367.png PlatyPS_79368_79607.png PlatyPS_79608_79775.png PlatyPS_79776_80411.png PlatyPS_80412_80507.png PlatyPS_80508_80963.png PlatyPS_80964_81047.png PlatyPS_81048_81827.png PlatyPS_81828_82499.png PlatyPS_82500_82907.png PlatyPS_82908_83795.png PlatyPS_83796_84395.png PlatyPS_84396_84515.png PlatyPS_84516_84659.png PlatyPS_84660_84803.png PlatyPS_84804_84923.png PlatyPS_84924_85295.png PlatyPS_85296_85679.png PlatyPS_85680_86951.png PlatyPS_86952_87671.png PlatyPS_87672_87791.png PlatyPS_87792_88691.png PlatyPS_88692_90335.png PlatyPS_90336_90599.png PlatyPS_90600_94271.png PlatyPS_94272_95807.png PlatyPS_95808_95879.png PlatyPS_95880_99179.png PlatyPS_99180_102299.png PlatyPS_102300_102647.png PlatyPS_102648_103619.png PlatyPS_103620_103811.png PlatyPS_103812_103859.png PlatyPS_103860_104423.png PlatyPS_104424_104903.png PlatyPS_104904_105623.png PlatyPS_105624_106019.png PlatyPS_106020_106163.png PlatyPS_106164_107135.png PlatyPS_107136_107747.png PlatyPS_107748_108959.png PlatyPS_108960_116963.png PlatyPS_116964_117407.png PlatyPS_117408_118799.png PlatyPS_118800_119363.png PlatyPS_119364_121295.png PlatyPS_121296_121907.png PlatyPS_121908_122471.png PlatyPS_122472_124163.png PlatyPS_124164_124427.png PlatyPS_124428_130727.png PlatyPS_130728_133019.png PlatyPS_133020_133175.png PlatyPS_133176_133209.png