Package: yamdog
Overview of YAMDOGYet Another Markdown Only GeneratorWhat is YAMDOG?YAMDOG is toolkit for creating Markdown text using Python. Markdown is a light and relatively simple markup language.Table of ContentQuick start guideThe first stepsInstallImportUsing the packageMaking elementsHeadingExample headingParagraphTableCompact tableListingChecklistLinkCodeblockCodeAddressQuote blockCombining elements into a documentExample headingFurther readingAnnexesAnnex 1: README Python sourceQuick start guideHere's how you can start automatically generating Markdown documentsThe first stepsInstallInstall YAMDOG with pip. YAMDOG uses only Python standard library so it has no additional dependencies.pip install yamdogImportImport name is the same as install name, yamdog.importyamdogSince the package is accessed often, I use abbreviationmdfor MarkDown. The abbreviation is used throughout this document.importyamdogasmdUsing the packageThere are two main things to building a Markdown document using YAMDOGMaking elementsCombining elements into a documentYou can callstron the element directly to get the markdown sourcemarkdown_source=str(element)but most of the time you will compose the elements together into an documentmarkdown_source=str(document)Making elementsLet's start with an empty documentdocument=md.Document([])HeadingPython sourceheading=md.Heading('Example heading',4)Markdown source#### Example headingRendered resultExample headingbolded textsome italiced textstriken text==highlighted text====All styles combined==bold_text=md.Text('bolded text',{md.BOLD})italiced_text=md.Text('some italiced text',{md.ITALIC})strikethrough_text=md.Text('striken text',{md.STRIKETHROUGH})highlighted_text=md.Text('highlighted text',{md.HIGHLIGHT})all_together=md.Text('All styles combined',{md.BOLD,md.ITALIC,md.STRIKETHROUGH,md.HIGHLIGHT})ParagraphPython sourceparagraph=md.Paragraph(['Example paragraph containing ',md.Text('bolded text',{md.BOLD})])Markdown sourceExample paragraph containing**bolded text**Rendered resultExample paragraph containingbolded textTablePython sourcetable=md.Table([['a',1,'Python'],['b',2,'Markdown']],['First column','Second column','Third column'],[md.RIGHT,md.LEFT,md.CENTER])Markdown source| First column | Second column | Third column |
| -----------: | :------------ | :----------: |
|            a | 1             |    Python    |
|            b | 2             |   Markdown   |Rendered resultFirst columnSecond columnThird columna1Pythonb2MarkdownYou can select compact mode at the table object creationCompact tablePython sourcetable=md.Table([['a',1,'Python'],['b',2,'Markdown']],['First column','Second column','Third column'],[md.RIGHT,md.LEFT,md.CENTER],True)Markdown sourceFirst column|Second column|Third column
--:|:--|:-:
a|1|Python
b|2|MarkdownRendered resultFirst columnSecond columnThird columna1Pythonb2Markdownor later by changing the attributecompacttable.compact=TrueListingPython sourcelisting=md.Listing(['Just normal text',md.Text('some stylised text',{md.ITALIC}),md.Checkbox('Listings can include checkboxes',False),md.Checkbox('Checked and unchecked option available',True),('Sublist by using a tuple',md.Listing(['first','second'],md.ORDERED))],md.UNORDERED)Markdown source-Just normal text-*some stylised text*- [ ]Listings can include checkboxes- [x]Checked and unchecked option available-Sublist by using a tuple1.first2.secondRendered resultJust normal textsome stylised textListings can include checkboxesChecked and unchecked option availableSublist by using a tuplefirstsecondChecklistPython sourcechecklist=md.make_checklist([('unchecked box',False),('checked box',True),('done',True)])Markdown source- [ ]unchecked box- [x]checked box- [x]doneRendered resultunchecked boxchecked boxdoneLinkPython sourcelink=md.Link('https://www.markdownguide.org','Link to Markdown Guide')Markdown source[Link to Markdown Guide](https://www.markdownguide.org)Rendered resultLink to Markdown GuideCodeblockPython sourcecodeblock=md.CodeBlock('import yamdog as md\n\ndoc = md.Document([])','python')Markdown source```pythonimportyamdogasmddoc=md.Document([])```Rendered resultimportyamdogasmddoc=md.Document([])CodePython sourcecode=md.Code('python != markdown')Markdown source`python != markdown`Rendered resultpython != markdownAddressPython sourceaddress=md.Link('https://www.markdownguide.org')Markdown source<https://www.markdownguide.org>Rendered resulthttps://www.markdownguide.orgQuote blockPython sourcequoteblock=md.Quote('Quote block supports\nmultiple lines')Markdown source>Quote block supports>multiple linesRendered resultQuote block supports
multiple linesCombining elements into a documentInitialising Document with list of elementsdocument=md.Document([heading,link,paragraph,listing])adding elements into a documentdocument=md.Document([])document+=headingdocument+=linkdocument+=paragraphdocument+=listingadding elements together into a documentdocument=heading+link+paragraph+listingAdding two documents togetherdocument1=md.Document([heading,link])document2=md.Document([paragraph,listing])document=document1+document2Markdown source#### Example heading[Link to Markdown Guide](https://www.markdownguide.org)

Example paragraph containing**bolded text**-Just normal text-*some stylised text*- [ ]Listings can include checkboxes- [x]Checked and unchecked option available-Sublist by using a tuple1.first2.secondRendered resultExample headingLink to Markdown GuideExample paragraph containingbolded textJust normal textsome stylised textListings can include checkboxesChecked and unchecked option availableSublist by using a tuplefirstsecondChangelog0.5.0 2023-05-07Some API changesAdded Raw, PDF, Comment0.4.0 2023-01-23Much better type validationSome comparisons0.3.1 2023-01-23Preliminary type validationFull test coverageFurther readingbasic syntax guideextended syntax guideAnnexesAnnex 1: README Python sourceAnd here the full source code that wrote this README. This can serve as a more advanced example of what this is capable of.The python file can also be found hereimportdatetimeimportpathlibimportreimportyamdogasmdPATH_BASE=pathlib.Path(__file__).parentPATH_README=PATH_BASE/'README.md'PATH_CHANGELOG=PATH_BASE/'.changelog.md'PATH_PYPROJECT=PATH_BASE/'pyproject.toml'VERSION=md.__version__#=======================================================================defmake_examples(source:str)->md.Document:'''Examples are collected via source code introspection'''# First getting the example code blockspattern=re.compile('\n#%%')examples={}forblockinpattern.split(source)[1:]:name,rest=block.split('\n',1)# from the commentcode=rest.split('\n\n',1)[0].replace('\n','\n').strip()examples[name.strip()]=md.CodeBlock(code,'python')defget_example(title:str,element:md.Element)->md.Document:returnmd.Document([md.Heading(title.capitalize(),4),md.Text('Python source',{md.ITALIC}),examples[title],md.Text('Markdown source',{md.ITALIC}),md.CodeBlock(element,'markdown'),md.Text('Rendered result',{md.ITALIC}),element,md.HRule()])# Starting the actual docdoc=md.Document([md.Heading('Making elements',3),])#%% documentdocument=md.Document([])doc+="Let's start with an empty document"doc+=examples['document']#%% adding to document# document +=#%% headingheading=md.Heading('Example heading',4)doc+=get_example('heading',heading)#%% stylisedbold_text=md.Text('bolded text',{md.BOLD})italiced_text=md.Text('some italiced text',{md.ITALIC})strikethrough_text=md.Text('striken text',{md.STRIKETHROUGH})highlighted_text=md.Text('highlighted text',{md.HIGHLIGHT})all_together=md.Text('All styles combined',{md.BOLD,md.ITALIC,md.STRIKETHROUGH,md.HIGHLIGHT})doc+=bold_textdoc+=italiced_textdoc+=strikethrough_textdoc+=highlighted_textdoc+=all_togetherdoc+=examples['stylised']doc+=md.HRule()#%%  paragraphparagraph=md.Paragraph(['Example paragraph containing ',md.Text('bolded text',{md.BOLD})])doc+=get_example('paragraph',paragraph)#%% tabletable=md.Table([['a',1,'Python'],['b',2,'Markdown']],['First column','Second column','Third column'],[md.RIGHT,md.LEFT,md.CENTER])doc+=get_example('table',table)#%% compact tabletable=md.Table([['a',1,'Python'],['b',2,'Markdown']],['First column','Second column','Third column'],[md.RIGHT,md.LEFT,md.CENTER],True)doc+='You can select compact mode at the table object creation'doc+=get_example('compact table',table)#%% table compact attributetable.compact=Truedoc+=md.Paragraph(['or later by changing the attribute ',md.Code('compact')])doc+=examples['table compact attribute']#%% listinglisting=md.Listing(['Just normal text',md.Text('some stylised text',{md.ITALIC}),md.Checkbox('Listings can include checkboxes',False),md.Checkbox('Checked and unchecked option available',True),('Sublist by using a tuple',md.Listing(['first','second'],md.ORDERED))],md.UNORDERED)doc+=get_example('listing',listing)#%% checklistchecklist=md.make_checklist([('unchecked box',False),('checked box',True),('done',True)])doc+=get_example('checklist',checklist)#%% linklink=md.Link('https://www.markdownguide.org','Link to Markdown Guide')doc+=get_example('link',link)#%% codeblockcodeblock=md.CodeBlock('import yamdog as md\n\ndoc = md.Document([])','python')doc+=get_example('codeblock',codeblock)#%% codecode=md.Code('python != markdown')doc+=get_example('code',code)#%% Image# image = md.Image()#%% addressaddress=md.Link('https://www.markdownguide.org')doc+=get_example('address',address)#%% quote blockquoteblock=md.Quote('Quote block supports\nmultiple lines')doc+=get_example('quote block',quoteblock)doc+=md.Heading('Combining elements into a document',3)#%% calling documentdocument=md.Document([heading,link,paragraph,listing])doc+='Initialising Document with list of elements'doc+=examples['calling document']#%% from empty documentdocument=md.Document([])document+=headingdocument+=linkdocument+=paragraphdocument+=listingdoc+='adding elements into a document'doc+=examples['from empty document']#%% document by addingdocument=heading+link+paragraph+listingdoc+='adding elements together into a document'doc+=examples['document by adding']#%% document concatenationdocument1=md.Document([heading,link])document2=md.Document([paragraph,listing])document=document1+document2doc+='Adding two documents together'doc+=examples['document concatenation']doc+=md.Text('Markdown source',{md.ITALIC})doc+=md.CodeBlock(document,'markdown')doc+=md.Text('Rendered result',{md.ITALIC})doc+=documentreturndoc#=======================================================================defmake_quick_start_guide(name,pypiname,source):doc=md.Document([md.Heading('Quick start guide',1),"Here's how you can start automatically generating Markdown documents",md.Heading('The first steps',2),'',md.Heading('Install',3),f'''Install{name}with pip.{name}uses only Python standard library so it has no additional dependencies.''',md.CodeBlock(f'pip install{pypiname}'),md.Heading('Import',3),f'''Import name is the same as install name,{pypiname}.''',md.CodeBlock(f'import{pypiname}','python'),md.Paragraph(['Since the package is accessed often, I use abbreviation',md.Code('md'),' for MarkDown. The abbreviation is used throughout this document.']),md.CodeBlock(f'import{pypiname}as md','python'),md.Heading('Using the package',2),f'There are two main things to building a Markdown document using{name}',md.Listing(['Making elements','Combining elements into a document'],md.ORDERED),md.Paragraph(['You can call ',md.Code('str'),' on the element directly to get the markdown source']),md.CodeBlock('markdown_source = str(element)','python'),'''but most of the time you will compose the elements together into andocument''',md.CodeBlock('markdown_source = str(document)','python')])doc+=make_examples(source)returndoc#=======================================================================re_heading=re.compile(r'^#* .*$')defparse_md_element(text:str):ifmatch:=re_heading.match(text):hashes,content=match[0].split(' ',1)returnmd.Heading(content,len(hashes))else:returnmd.Raw(text)#-----------------------------------------------------------------------defparse_md(text:str):returnmd.Document([parse_md_element(item.strip())foritemintext.split('\n\n')])#-----------------------------------------------------------------------defmake_changelog(level:int):doc=md.Document([md.Heading('Changelog',level,in_TOC=False)])changelog=parse_md(PATH_CHANGELOG.read_text())ifchangelog:if(latest:=changelog.content[0]).content.split(' ',1)[0]==VERSION:latest.content=f'{VERSION}{datetime.date.today().isoformat()}'else:raiseValueError('Changelog not up to date')PATH_CHANGELOG.write_text(str(changelog)+'\n')foriteminchangelog:ifisinstance(item,md.Heading):item.level=level+1item.in_TOC=Falsedoc+=changelogreturndoc#=======================================================================defmake_further_reading():basic_syntax_link=md.Link('https://www.markdownguide.org/basic-syntax/','basic syntax guide','')extended_syntax_link=md.Link('https://www.markdownguide.org/basic-syntax/','extended syntax guide','')doc=md.Document([md.Heading('Further reading',1)])doc+=md.Listing([basic_syntax_link,extended_syntax_link],md.UNORDERED)returndoc#=======================================================================defmake_annexes(source):doc=md.Document([md.Heading('Annexes',1)])doc+=md.Heading('Annex 1: README Python source',2)doc+='''And here the full source code that wrote this README.This can serve as a more advanced example of what this iscapable of.'''doc+=md.Link('https://github.com/Limespy/YAMDOG/blob/main/readme.py','The python file can also be found here')doc+=md.CodeBlock(source,'python')returndoc#=======================================================================defmake(name,pypiname,source):# Setup for the badgesshields_url='https://img.shields.io/'pypi_project_url=f'https://pypi.org/project/{pypiname}'pypi_badge_info=(('v','PyPI Package latest release'),('wheel','PyPI Wheel'),('pyversions','Supported versions'),('implementation','Supported implementations'))pypi_badges=[md.Link(pypi_project_url,md.Image(f'{shields_url}pypi/{code}/{pypiname}.svg',desc),'')forcode,descinpypi_badge_info]# Starting the documentdoc=md.Document([md.Heading(f'Overview of{name}',1,in_TOC=False),md.Paragraph(pypi_badges,'\n'),'Yet Another Markdown Only Generator',md.Heading(f'What is{name}?',2,in_TOC=False),f'''{name}is toolkit for creating Markdown text using Python.Markdown is a light and relatively simple markup language.''',md.Heading('Table of Content',3,in_TOC=False),md.TOC()])source=pathlib.Path(__file__).read_text('utf8')doc+=make_quick_start_guide(name,pypiname,source)doc+=make_changelog(level=1)doc+=make_further_reading()doc+=md.HRule()doc+=make_annexes(source)returndoc#=======================================================================defmain():try:importtomllibexceptModuleNotFoundError:importtomliastomllib# type: ignorepyproject=tomllib.loads(PATH_PYPROJECT.read_text())master_info=pyproject['master-info']package_name=master_info["package_name"]full_name=master_info.get("full_name",package_name.replace('-',' ').capitalize())description=master_info['description']doc=make(full_name,package_name,description)PATH_README.write_text(str(doc)+'\n')#=======================================================================if__name__=='__main__':main()