Skip to content

Commit

Permalink
v1.7 Numbered List Items
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinPacker committed Jan 9, 2021
1 parent 0b555a5 commit ae4b551
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 20 deletions.
101 changes: 82 additions & 19 deletions md2pptx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,39 @@ import copy
from lxml import etree


md2pptx_level = "1.6.3"
md2pptx_date = "2 January, 2021"
md2pptx_level = "1.7"
md2pptx_date = "9 January, 2021"

# Turn a paragraph into a numbered list item
def makeNumberedListItem(p):
if (
p._element.getchildren()[0].tag
== "{http://schemas.openxmlformats.org/drawingml/2006/main}pPr"
):
pPr = p._element.getchildren()[0]
if len(pPr.getchildren()) > 0:
# Remove Default Text Run Properties element - if present
x = pPr.getchildren()[0]
if x.tag == "{http://schemas.openxmlformats.org/drawingml/2006/main}defRPr":
pPr.remove(x)
else:
pPr = OxmlElement("a:pPr")
p._element.insert(0, pPr)
# indentMarL = 514350
# pPr.set("indent", str(-indentMarL))
# pPr.set("indent", str(-indentMarL * (p.level+1)))
# pPr.set("marL", str(indentMarL * (p.level +1)))

buFont = OxmlElement("a:buFont")
buFont.set("typeface", "+mj-lt")
pPr.append(buFont)

buAutoNum = OxmlElement("a:buAutoNum")
buAutoNum.set("type", "arabicPeriod")
pPr.append(buAutoNum)

# p.level = level


# Add a drop shadow to a shape
def createShadow(shape):
Expand Down Expand Up @@ -146,7 +177,7 @@ def set_highlight(run, color):
hl = OxmlElement("a:highlight")

# Create specify RGB Colour element with color specified
srgbClr = OxmlElement("a:srgbClr")
srgbClr = OxmlElement("a:srgbClr")
setattr(srgbClr, "val", color)

# Add colour specification to highlight element
Expand Down Expand Up @@ -313,6 +344,9 @@ def populateTextBlock(shape, bullets):

addFormattedText(p, bullet[1])

if bullet[2] == "numbered":
makeNumberedListItem(p)

bulletNumber = bulletNumber + 1

tf.auto_size = MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE
Expand Down Expand Up @@ -342,7 +376,7 @@ def formatTitle(presentation, title, titleText):
title.text_frame.paragraphs[0].font.size = Pt(pageTitleSize)
title.text_frame.vertical_anchor = MSO_ANCHOR.TOP

return title.top + title.height
return title.top + title.height + Inches(0.1)


# Parse the string after the e.g. ### for a displayable title and
Expand Down Expand Up @@ -1420,7 +1454,10 @@ def contentSlide(presentation, slideNumber, titleText, subtitleText, bullets):
# Card top and height
card_top = cardTitle_top + cardTitle_height
card_height = (
presentation.slide_height - cardTitle_top - Inches(0.5) - cardTitle_height
presentation.slide_height
- cardTitle_top
- Inches(0.5)
- cardTitle_height
)
else:
# No bullets so cards and their titles occupy whole height
Expand All @@ -1431,7 +1468,10 @@ def contentSlide(presentation, slideNumber, titleText, subtitleText, bullets):
# Card top and height
card_top = cardTitle_top + cardTitle_height
card_height = (
presentation.slide_height - cardTitle_top - Inches(0.25) + cardTitle_height
presentation.slide_height
- cardTitle_top
- Inches(0.25)
+ cardTitle_height
)
else:
bullets_shape.height = content_height
Expand All @@ -1446,7 +1486,7 @@ def contentSlide(presentation, slideNumber, titleText, subtitleText, bullets):
if cardLayout == "vertical":
cardPlusTitleHeight = int((card_height + Inches(0.75)) / card_count)
cardsTop = int(bullets_shape.bottom + Inches(0.25))

for c in range(card_count):
cardTitle_shape = cardTitle_shapes[c]
card_shape = card_shapes[c]
Expand All @@ -1456,7 +1496,9 @@ def contentSlide(presentation, slideNumber, titleText, subtitleText, bullets):

# Position card title
cardTitle_shape.top = cardTitle_top
cardTitle_shape.left = int(Inches(0.5) + c * (card_width + Inches(0.25)))
cardTitle_shape.left = int(
Inches(0.5) + c * (card_width + Inches(0.25))
)
cardTitle_shape.width = int(card_width)

# Position card
Expand Down Expand Up @@ -2542,7 +2584,8 @@ if len(input_file) == 0:

slideNumber = 1

bulletRegex = re.compile("^(\s)*\*(.*)")
bulletRegex = re.compile("^(\s)*(\*)(.*)")
numberRegex = re.compile("^(\s)*(\d+)\.(.*)")
metadataRegex = re.compile("^(.+):(.+)")
graphicRegex = re.compile("^!\[(.*)\]\((.+)\)")
clickableGraphicRegex = re.compile("^\[!\[(.*)\]\((.+)\)\]\((.+)\)")
Expand Down Expand Up @@ -2836,20 +2879,20 @@ for line in metadata_lines:
pres_cardPercent = cardPercent

elif name == "cardlayout":
if value in ["horizontal","vertical"]:
if value in ["horizontal", "vertical"]:
cardLayout = value
pres_cardLayout = value
else:
print(f"CardLayout value '{value}' unsupported.")

elif name == "cardtitlealign":
val1l = value[:1].lower()
if val1l in ["l","r","c"]:
if val1l in ["l", "r", "c"]:
cardTitleAlign = val1l
pres_cardTitleAlign = cardTitleAlign
else:
print(f"CardAlign value '{value}' unsupported.")

elif name == "taskslides":
taskSlides = value
elif name == "tasksperpage":
Expand Down Expand Up @@ -2961,7 +3004,7 @@ for line in after_metadata_and_HTML:

else:
# Previous line was not blank and nor is this one so consider concatenation
if line.lstrip()[0] not in "*#\|":
if line.lstrip()[0] not in "*#\|0123456789":
if previous_line[0:2] != "# ":
# Previous line was not Heading Level 1 so concatenate
lines_after_concatenation[-1] = (
Expand Down Expand Up @@ -3110,7 +3153,7 @@ for line in lines_after_concatenation:

else:
cardLayout = metadataValue

elif metadataKey == "basetextsize":
# Base text size
if metadataValue == "default":
Expand Down Expand Up @@ -3318,22 +3361,42 @@ for line in lines_after_concatenation:
text_frame.text = notes_text

notes_text = ""

elif bulletRegex.match(line):
# Bulleted list
bulletPos = line.index("*") + 1
bulletLine = line[bulletPos:].lstrip()
bulletLevel = (bulletPos + 1) / 2
match = bulletRegex.match(line)
bulletLine = match.group(3).lstrip()
bulletLevel = int(match.start(2) / 2) + 1
bulletType = "bulleted"
if in_card:
cardBullets.append([bulletLevel, bulletLine])
cardBullets.append([bulletLevel, bulletLine, bulletType])
cardsLength = len(cards)
if len(cards[cardsLength - 1]) == 1:
cards[cardsLength - 1].append(cardBullets)
else:
cards[cardsLength - 1][1] = cardBullets
else:
bullets.append([bulletLevel, bulletLine])
bullets.append([bulletLevel, bulletLine, bulletType])
in_list = True
in_table = False

elif numberRegex.match(line):
match = numberRegex.match(line)
bulletLine = match.group(3).lstrip()
bulletLevel = int(match.start(2) / 2) + 1
bulletType = "numbered"
if in_card:
cardBullets.append([bulletLevel, bulletLine, bulletType])
cardsLength = len(cards)
if len(cards[cardsLength - 1]) == 1:
cards[cardsLength - 1].append(cardBullets)
else:
cards[cardsLength - 1][1] = cardBullets
else:
bullets.append([bulletLevel, bulletLine, bulletType])
in_list = True
in_table = False

else:
# Must be a slide note line
slide_subtitle = slide_subtitle + "\n" + line
Expand Down
28 changes: 27 additions & 1 deletion user-guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,10 @@ <h3 id="table-of-contents">Table Of Contents<a class="headerlink" href="#table-o
<li><a href="#creating-slides">Creating Slides</a><ul>
<li><a href="#presentation-title-slides">Presentation Title Slides</a></li>
<li><a href="#presentation-section-slides">Presentation Section Slides</a></li>
<li><a href="#bullet-slides">Bullet Slides</a></li>
<li><a href="#bullet-slides">Bullet Slides</a><ul>
<li><a href="#numbered-list-items">Numbered List Items</a></li>
</ul>
</li>
<li><a href="#graphics-slides">Graphics Slides</a><ul>
<li><a href="#clickable-pictures">Clickable Pictures</a></li>
<li><a href="#graphics-file-references">Graphics File References</a></li>
Expand Down Expand Up @@ -1134,6 +1137,7 @@ <h2 id="how-do-you-use-md2pptx">How Do You Use md2pptx?<a class="headerlink" hre
<li>Install python-pptx using the command <code>pip3 install python-pptx</code>. (You might have to install pip firsst.)</li>
<li>Invoke it.</li>
</ol>
<p><strong>NOTE:</strong> A future release of md2pptx will require at least Python 3.8. This will bring an improvement in efficiency.</p>
<p>The following instructions are for Unix-like systems. (It&rsquo;s developed and used by the developer on Mac OS but should also have identical syntax on Linux.) Windows users will need a slightly different form, but the principle is the same.</p>
<p>Here is a sample invocation:</p>
<div class="codehilite"><pre>md2pptx powerpoint-filename &lt; markdown-filename
Expand Down Expand Up @@ -1186,6 +1190,11 @@ <h2 id="change-log">Change Log<a class="headerlink" href="#change-log" title="Pe
</thead>
<tbody>
<tr>
<td align="left">1.7</td>
<td align="left">9 January 2021</td>
<td align="left">Added support for numbered list items</td>
</tr>
<tr>
<td align="left">1.6.3</td>
<td align="left">2 January 2021</td>
<td align="left">Added support for vertical cards. Also new <code>CardTitleAlign</code> and <code>CardLayout</code> metadata&comma; plus <code>basetextsize</code> and <code>basetextdecrement</code> Dynamic Metadata items.</td>
Expand Down Expand Up @@ -1405,6 +1414,23 @@ <h3 id="bullet-slides">Bullet Slides<a class="headerlink" href="#bullet-slides"
<p><strong>NOTE:</strong> Some dialects of Markdown allow other bullet markers but md2pptx doesn&rsquo;t. You can be sure by coding <code>*</code> you have valid Markdown that md2pptx can also process correctly. For an explanation of why you have to stick to <code>*</code> see <a href="#task-list-slides">here</a>.</p>
<p>To nest bullets use a tab character or 4 spaces to indent the sub-bullets. md2pptx doesn&rsquo;t have a limit on the level of nesting but Powerpoint probably does.</p>
<p>Terminate the bulleted list slide with a blank line.</p>
<h4 id="numbered-list-items">Numbered List Items<a class="headerlink" href="#numbered-list-items" title="Permanent link"></a></h4>
<p><a id="numbered-items"></a></p>
<p>Within a bullet slide you can have numbered items. Here is an example of a slide with mixed numbers and bullets:</p>
<div class="codehilite"><pre>### This Is A Mixed Numbers And Bullets Slide

* Bullet One
1. Numbered sub-bullet A
1. Numbered sub-bullet B
* Bullet Two
* Bullet Three
</pre></div>


<p>Numbered list items are introduced with an integer, followed by a full stop.</p>
<p>Markdown takes care of the numbering. In the above example there are two numbered items. While the first will indeed be numbered &ldquo;1&rdquo; the second will be numbered &ldquo;2&rdquo;, despite the <code>1.</code> coding.</p>
<p>Numbering with <code>1.</code> is actually a useful practice - as it makes it easier to reorder a numbered list (by moving the lines around).</p>
<p><strong>Note:</strong> You can mix numbered and bulleted items in a list.</p>
<h3 id="graphics-slides">Graphics Slides<a class="headerlink" href="#graphics-slides" title="Permanent link"></a></h3>
<p><a id="graphics-slides"></a></p>
<p>As with <a href="#bullet-slides">bullet slides</a>, code the slide title as a Markdown Heading Level 3. Specify the graphic to embed with the standard Markdown image reference:</p>
Expand Down
93 changes: 93 additions & 0 deletions user-guide.log
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,100 @@
mdpre Markdown Preprocessor v0.4.6 (4 November, 2020)
=====================================================
- opened <stdout> for writing
Def mdpre_date = 4 November, 2020
Def mdpre_level = 0.4.6
Def userid = martinpacker
Def time = 19&colon;22
Def date = 9 January&comma; 2021
Def TOC = Table Of Contents
Def md = Markdown
Def pp = Powerpoint
Markdown To Powerpoint User Guide
Table Of Contents - spec '2 * Table Of Contents'
2 4 Table Of Contents
..... Why md2pptx?
..... ..... A Real World Use Case
..... How Do You Use md2pptx?
..... python-pptx license
..... Change Log
CSV Start
CSV Stop
..... Creating Slides
..... ..... Presentation Title Slides
..... ..... Presentation Section Slides
..... ..... Bullet Slides
..... ..... ..... Numbered List Items
..... ..... Graphics Slides
..... ..... ..... Clickable Pictures
..... ..... ..... Graphics File References
..... ..... Table Slides
..... ..... ..... Special Case: Two Graphics Side By Side
..... ..... ..... Special Case: Two By Two Grid Of Graphics
..... ..... ..... Special Case: Three Graphics On A Slide
..... ..... ..... Special Case: One Graphic Above Another
..... ..... Card Slides
..... ..... Code Slides
..... ..... Task List Slides
..... Hyperlinks
..... ..... Coding A Heading Reference On A Target Slide
..... ..... Coding A Hyperlink To Another Slide
..... HTML Comments
..... Special Text Formatting
CSV Start
CSV Stop
..... ..... Using HTML `<style>` Elements To Specify Text Colours And Underlining
..... ..... HTML Entity References
CSV Start
CSV Stop
..... ..... Numeric Character References
..... ..... Escaped Characters
..... ..... CriticMarkup
..... Creating A Glossary Of Terms
..... Creating Footnotes
..... ..... Creating A Footnote
..... ..... Referring To A Footnote
..... Controlling The Presentation With Metadata
..... ..... Specifying Metadata
..... ..... Metadata Keys
..... ..... ..... Slide Numbers - `numbers`
..... ..... ..... Page Title Size - `pageTitleSize`
..... ..... ..... Section Title Size - `sectionTitleSize`
..... ..... ..... Section Subtitle Size - `sectionSubtitleSize`
..... ..... ..... Monospace Font - `monoFont`
..... ..... ..... Margin size - `marginBase` and `tableMargin`
..... ..... ..... Associating A Class Name with A Background Colour With `style.bgcolor`
..... ..... ..... Associating A Class Name with A Foreground Colour With `style.fgcolor`
..... ..... ..... Associating A Class Name With Text Emphasis With `style.emphasis`
..... ..... ..... Template Presentation - `template`
..... ..... ..... "Chevron Style" Table Of Contents - `tocStyle` And `tocTitle`
..... ..... ..... Specifying An Abstract Slide With `abstractTitle`
..... ..... ..... Specifying Text Size With `baseTextSize` And `baseTextDecrement`
..... ..... ..... Specifying Bold And Italic Text Colour With `BoldColour` And `ItalicColour`
..... ..... ..... Specifying Bold And Italic Text Effects With `BoldBold` And `ItalicItalic`
..... ..... ..... Shrinking Tables With `compactTables`
..... ..... ..... Controlling Task Slide Production With `taskSlides` and `tasksPerSlide`
..... ..... ..... Controlling Glossary Slide Production With `glossaryTitle`, `glossaryTerm`, `glossaryMeaning`,`glossaryMeaningWidth`, and `glossaryTermsPerPage`
..... ..... ..... Card Background Colour - `CardColour`
..... ..... ..... Card Border Colour - `CardBorderColour`
..... ..... ..... Card Border Width - `CardBorderWidth`
..... ..... ..... Card Title Size - `CardTitleSize`
..... ..... ..... Card Shadow - `CardShadow`
..... ..... ..... Controlling Card Size With `CardPercent`
..... ..... ..... Controlling Card Layout Direction With `CardLayout`
..... ..... ..... Controlling Card Title Alignment With `CardTitleAlign`
..... ..... Dynamic Metadata
..... ..... ..... `CompactTables`
..... ..... ..... `CardPercent`
..... ..... ..... `CardLayout`
..... ..... ..... `CardTitleAlign`
..... ..... ..... `PageTitleSize`
..... ..... ..... `BaseTextSize`
..... ..... ..... `BaseTextDecrement`
..... Modifying The Slide Template
..... ..... Basics
..... ..... Slide Template Sequence
CSV Start
CSV Stop
-----------------------------------------------------
- Processing completed.
-----------------------------------------------------
Expand Down

0 comments on commit ae4b551

Please sign in to comment.