From 2748c5e7c38e809ec1fe71cf96664f641bb2d420 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Fri, 22 May 2020 11:13:41 -0400 Subject: [PATCH 01/27] implementation: discrete headers Implements the feature requested in #140 by @tajmone --- markdowntoc/markdowntoc_insert.py | 207 ++++++++++++++++++------------ tests/levels.py | 28 +++- 2 files changed, 151 insertions(+), 84 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index d3d3b08..269e93f 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -1,31 +1,38 @@ import pprint import re -import sublime -import sublime_plugin import sys import webbrowser - from urllib.parse import quote +import sublime +import sublime_plugin + from .autorunner import AutoRunner from .base import Base -from .util import Util from .id import Id +from .util import Util # for debug pp = pprint.PrettyPrinter(indent=4) # [Heading][my-id] # Negative lookbehind -PT_REF_LINK = re.compile(r'(?') +PT_EX_ID = re.compile(r"\{#.+?\}$") +PT_TAG = re.compile(r"<.*?>") PT_ANCHOR = re.compile(r'\s*') +# +PT_DISCRETE = re.compile( + r"^", re.IGNORECASE +) + + class MarkdowntocInsert(sublime_plugin.TextCommand, Base): def run(self, edit): @@ -42,14 +49,14 @@ def run(self, edit): toc += "\n" self.view.insert(edit, sel.begin(), toc) - self.log('inserted TOC') + self.log("inserted TOC") # TODO: process to add another toc when tag exists def get_toc_open_tag(self): search_results = self.view.find_all( - r'^\n', - sublime.IGNORECASE) + r"^\n", sublime.IGNORECASE + ) search_results = self.remove_items_in_codeblock(search_results) toc_open_tags = [] @@ -74,7 +81,7 @@ def get_toc_open_tag(self): return toc_open_tags def get_toc_close_tag(self, start): - close_tags = self.view.find_all(r'\n') + close_tags = self.view.find_all(r"\n") close_tags = self.remove_items_in_codeblock(close_tags) for close_tag in close_tags: if start < close_tag.begin(): @@ -96,13 +103,13 @@ def find_tag_and_insert(self, edit): toc_start.end(), toc_close.begin()) if toc: self.view.replace(edit, tocRegion, "\n" + toc + "\n") - self.log('refresh TOC content') + self.log("refresh TOC content") return True else: self.view.replace(edit, tocRegion, "\n") - self.log('TOC is empty') + self.log("TOC is empty") return False - self.log('cannot find TOC tags') + self.log("cannot find TOC tags") return False def escape_brackets(self, _text): @@ -112,7 +119,7 @@ def do_escape(_text, _pattern, _open, _close): images = [] brackets = [] codes = [] - for m in re.compile(r'`[^`]*`').finditer(_text): + for m in re.compile(r"`[^`]*`").finditer(_text): codes.append([m.start(), m.end()]) def not_in_codeblock(target): @@ -120,6 +127,7 @@ def not_in_codeblock(target): def not_in_image(target): return not Util.within_ranges(target, images) + # Collect images not in codeblock for m in PT_IMAGE.finditer(_text): images.append([m.start(), m.end()]) @@ -137,10 +145,13 @@ def replace_brackets(m): return _open + m.group(1) + _close else: return m.group(0) + return re.sub(_pattern, replace_brackets, _text) - _text = do_escape(_text, re.compile(r'(? 1 and discrete: + return heading - 1, discrete + return heading, discrete + if len(headings) < 1: - return '' + return "" items = [] # [[headingNum, text, position, anchor_id], ...] + discrete_active = False for heading in headings: if begin < heading.end(): lines = self.view.lines(heading) + previous_line = self.view.substr( + self.view.line(lines[0].a - 1)) + if PT_DISCRETE.match(previous_line): + discrete_active = True + continue + if len(lines) == 1: # handle hash headings, ### chapter 1 - r = sublime.Region( - heading.end() - 1, self.view.line(heading).end()) - text = self.view.substr(r).strip().rstrip('#') - indent = heading.size() - 1 + r = sublime.Region(heading.end() - 1, + self.view.line(heading).end()) + text = self.view.substr(r).strip().rstrip("#") + # indent = heading.size() - 1 + indent, discrete_active = get_discrete_header( + discrete_active, heading.size() - 1 + ) + items.append([indent, text, heading.begin()]) elif len(lines) == 2: # handle = or - headings @@ -177,16 +206,18 @@ def get_toc(self, attrs, begin, edit): # ---- text = self.view.substr(lines[0]) if text.strip(): - indent = 1 if ( - self.view.substr(lines[1])[0] == '=') else 2 + heading_type = self.view.substr(lines[1])[0] + indent = 1 if heading_type == "=" else 2 + indent, discrete_active = get_discrete_header( + discrete_active, heading.size() - 1 + ) items.append([indent, text, heading.begin()]) if len(items) < 1: - return '' + return "" # Filtering by heading level ------------------ - accepted_levels = list( - map(lambda i: int(i), attrs['levels'])) + accepted_levels = list(map(lambda i: int(i), attrs["levels"])) items = list(filter((lambda j: j[0] in accepted_levels), items)) # Shape TOC ------------------ @@ -194,24 +225,26 @@ def get_toc(self, attrs, begin, edit): # TODO: Remove this block in the future release version # Depth limit ------------------ - if hasattr(attrs, 'depth'): + if hasattr(attrs, "depth"): # WARNING - url = 'https://github.com/naokazuterada/MarkdownTOC/releases/tag/3.0.0' - message = '[MarkdownTOC] OBSOLETE
Don\'t use \'depth\' any more, use \'levels\' instead.' + url = "https://github.com/naokazuterada/MarkdownTOC/releases/tag/3.0.0" + message = "[MarkdownTOC] OBSOLETE
Don't use 'depth' any more, use 'levels' instead." def open_link(v): webbrowser.open_new(url) + self.view.show_popup( - message + '
Instruction', on_navigate=open_link) - self.error(PT_TAG.sub('', message) + ' Instruction > ' + url) + message + "
Instruction", on_navigate=open_link + ) + self.error(PT_TAG.sub("", message) + " Instruction > " + url) # Create TOC ------------------ - toc = '' + toc = "" _ids = [] level_counters = [0] - remove_image = attrs['remove_image'] - link_prefix = attrs['link_prefix'] - bullets = attrs['bullets'] + remove_image = attrs["remove_image"] + link_prefix = attrs["link_prefix"] + bullets = attrs["bullets"] for item in items: _id = None @@ -221,11 +254,12 @@ def open_link(v): # Remove markdown image which not in codeblock images = [] codes = [] - for m in re.compile(r'`[^`]*`').finditer(_text): + for m in re.compile(r"`[^`]*`").finditer(_text): codes.append([m.start(), m.end()]) def not_in_codeblock(_target): return not Util.within_ranges(_target, codes) + # Collect images not in codeblock for m in PT_IMAGE.finditer(_text): images.append([m.start(), m.end()]) @@ -234,28 +268,29 @@ def not_in_codeblock(_target): def _replace(m): if m.start() in images: - return '' + return "" else: return m.group(0) + _text = re.sub(PT_IMAGE, _replace, _text) _list_bullet = bullets[_indent % len(bullets)] - _text = PT_TAG.sub('', _text) # remove html tags + _text = PT_TAG.sub("", _text) # remove html tags _text = _text.strip() # remove start and end spaces # Ignore links: e.g. '[link](http://sample.com/)' -> 'link' # this is [link](http://www.sample.com/) - link = re.compile(r'([^!])\[([^\]]+)\]\([^\)]+\)') - _text = link.sub('\\1\\2', _text) + link = re.compile(r"([^!])\[([^\]]+)\]\([^\)]+\)") + _text = link.sub("\\1\\2", _text) # [link](http://www.sample.com/) link in the beginning of line - beginning_link = re.compile(r'^\[([^\]]+)\]\([^\)]+\)') - _text = beginning_link.sub('\\1', _text) + beginning_link = re.compile(r"^\[([^\]]+)\]\([^\)]+\)") + _text = beginning_link.sub("\\1", _text) # Add indent for i in range(_indent): - _prefix = attrs['indent'] + _prefix = attrs["indent"] # Support escaped characters like '\t' - _prefix = _prefix.encode().decode('unicode-escape') + _prefix = _prefix.encode().decode("unicode-escape") toc += _prefix # ----------------- @@ -266,12 +301,15 @@ def filtering(ref_links, text): images = [] codes = [] valids = [] - for m in re.compile(r'`[^`]*`').finditer(text): + for m in re.compile(r"`[^`]*`").finditer(text): codes.append([m.start(), m.end()]) + def not_in_codeblock(target): return not Util.within_ranges(target, codes) + def not_in_image(target): return not Util.within_ranges(target, images) + # Collect images not in codeblock for m in PT_IMAGE.finditer(text): images.append([m.start(), m.end()]) @@ -294,30 +332,32 @@ def not_in_image(target): if len(ref_links): match = ref_links[-1] - _text = _text[0:match.start()].replace( - '[', '').replace(']', '').rstrip() - _id = match.group().replace('[', '').replace(']', '') + _text = ( + _text[0: match.start()].replace( + "[", "").replace("]", "").rstrip() + ) + _id = match.group().replace("[", "").replace("]", "") elif match_ex_id: - _text = _text[0:match_ex_id.start()].rstrip() - _id = match_ex_id.group().replace('{#', '').replace('}', '') - elif attrs['autolink']: + _text = _text[0: match_ex_id.start()].rstrip() + _id = match_ex_id.group().replace("{#", "").replace("}", "") + elif attrs["autolink"]: _id = Id( - self.settings('id_replacements'), - attrs['markdown_preview'], - str(attrs['lowercase']).lower() - ).heading_to_id(_text) - if attrs['uri_encoding']: + self.settings("id_replacements"), + attrs["markdown_preview"], + str(attrs["lowercase"]).lower(), + ).heading_to_id(_text) + if attrs["uri_encoding"]: _id = quote(_id) _ids.append(_id) n = _ids.count(_id) if 1 < n: - _id += '-' + str(n - 1) + _id += "-" + str(n - 1) - if attrs['style'] == 'unordered': - list_prefix = _list_bullet + ' ' - elif attrs['style'] == 'ordered': - list_prefix = '1. ' + if attrs["style"] == "unordered": + list_prefix = _list_bullet + " " + elif attrs["style"] == "ordered": + list_prefix = "1. " # escape brackets _text = self.escape_brackets(_text) @@ -326,15 +366,15 @@ def not_in_image(target): _id = link_prefix + _id if _id is None: - toc += list_prefix + _text + '\n' - elif attrs['bracket'] == 'round': - toc += list_prefix + '[' + _text + '](#' + _id + ')\n' + toc += list_prefix + _text + "\n" + elif attrs["bracket"] == "round": + toc += list_prefix + "[" + _text + "](#" + _id + ")\n" else: - toc += list_prefix + '[' + _text + '][' + _id + ']\n' + toc += list_prefix + "[" + _text + "][" + _id + "]\n" item.append(_id) - self.update_anchors(edit, items, attrs['autoanchor']) + self.update_anchors(edit, items, attrs["autoanchor"]) return toc @@ -348,7 +388,7 @@ def update_anchors(self, edit, items, autoanchor): if autoanchor: # if autolink=false then item[3] will be None, # so use raw heading valie(replaced whitespaces) then - _id = item[3] or re.sub(r'\s+', '-', item[1]) + _id = item[3] or re.sub(r"\s+", "-", item[1]) if is_update: new_anchor = ''.format(_id) v.replace(edit, anchor_region, new_anchor) @@ -360,20 +400,23 @@ def update_anchors(self, edit, items, autoanchor): if is_update: v.erase( edit, - sublime.Region( - anchor_region.begin(), - anchor_region.end() + 1)) + sublime.Region(anchor_region.begin(), + anchor_region.end() + 1), + ) def get_attributes_from(self, tag_str): """return dict of settings from tag_str""" pattern = re.compile( - r'\b(?P\w+)=((?P)|(\'(?P[^\']+)\')|("(?P[^"]+)")|(?P\S+))\s') + r'\b(?P\w+)=((?P)|(\'(?P[^\']+)\')|("(?P[^"]+)")|(?P\S+))\s' + ) attrs = dict( - (m.group('name'), - m.group('simple') or - m.group('dquoted') or - m.group('quoted') or - m.group('empty')) + ( + m.group("name"), + m.group("simple") + or m.group("dquoted") + or m.group("quoted") + or m.group("empty"), + ) for m in pattern.finditer(tag_str) ) @@ -381,7 +424,7 @@ def get_attributes_from(self, tag_str): defaults = self.defaults() for key in attrs: if type(defaults[key]) is list: - attrs[key] = attrs[key].split(',') + attrs[key] = attrs[key].split(",") elif type(defaults[key]) is bool: attrs[key] = Util.strtobool(attrs[key]) @@ -399,8 +442,6 @@ def remove_items_in_codeblock(self, items): codeblockAreas.append([area_begin, area_end]) i += 2 - items = [ - h for h in items if Util.is_out_of_areas( - h.begin(), - codeblockAreas)] + items = [h for h in items if Util.is_out_of_areas( + h.begin(), codeblockAreas)] return items diff --git a/tests/levels.py b/tests/levels.py index b2e8c63..d5c0f31 100644 --- a/tests/levels.py +++ b/tests/levels.py @@ -125,4 +125,30 @@ def test_levels_specific_levels(self): self.assert_NotIn('- heading 1', toc) self.assert_In('- heading 2', toc) self.assert_NotIn('- heading 5', toc) - self.assert_In('- heading 6', toc) \ No newline at end of file + self.assert_In('- heading 6', toc) + + + text_3 = """ + + + + + +# heading 1 + +## heading 2 + +### heading 3 + +#### heading 4 +###### heading 7 +""" + + def test_levels_discrete_levels(self): + """Default is no limit""" + toc = self.init_update(self.text_3)["toc"] + self.assert_In("- heading 1", toc) + self.assert_In("- heading 2", toc) + self.assert_In("- heading 3", toc) + self.assert_NotIn("- heading 4", toc) + self.assert_In("- heading 7", toc) \ No newline at end of file From d75ccdb45705f31b8362c8c97e196cf49d76ed1a Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Fri, 22 May 2020 11:28:00 -0400 Subject: [PATCH 02/27] fix changed quotes --- markdowntoc/markdowntoc_insert.py | 155 ++++++++++++++---------------- 1 file changed, 72 insertions(+), 83 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 269e93f..81c5366 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -17,19 +17,19 @@ # [Heading][my-id] # Negative lookbehind -PT_REF_LINK = re.compile(r"(?") +PT_EX_ID = re.compile(r'\{#.+?\}$') +PT_TAG = re.compile(r'<.*?>') PT_ANCHOR = re.compile(r'\s*') # PT_DISCRETE = re.compile( - r"^", re.IGNORECASE + r'^', re.IGNORECASE ) @@ -55,7 +55,7 @@ def run(self, edit): def get_toc_open_tag(self): search_results = self.view.find_all( - r"^\n", sublime.IGNORECASE + r'^\n', sublime.IGNORECASE ) search_results = self.remove_items_in_codeblock(search_results) @@ -81,7 +81,7 @@ def get_toc_open_tag(self): return toc_open_tags def get_toc_close_tag(self, start): - close_tags = self.view.find_all(r"\n") + close_tags = self.view.find_all(r'\n') close_tags = self.remove_items_in_codeblock(close_tags) for close_tag in close_tags: if start < close_tag.begin(): @@ -103,13 +103,13 @@ def find_tag_and_insert(self, edit): toc_start.end(), toc_close.begin()) if toc: self.view.replace(edit, tocRegion, "\n" + toc + "\n") - self.log("refresh TOC content") + self.log('refresh TOC content') return True else: self.view.replace(edit, tocRegion, "\n") - self.log("TOC is empty") + self.log('TOC is empty') return False - self.log("cannot find TOC tags") + self.log('cannot find TOC tags') return False def escape_brackets(self, _text): @@ -148,10 +148,8 @@ def replace_brackets(m): return re.sub(_pattern, replace_brackets, _text) - _text = do_escape(_text, re.compile( - r"(?OBSOLETE
Don't use 'depth' any more, use 'levels' instead." + url = 'https://github.com/naokazuterada/MarkdownTOC/releases/tag/3.0.0' + message = '[MarkdownTOC] OBSOLETE
Don\'t use \'depth\' any more, use \'levels\' instead.' def open_link(v): webbrowser.open_new(url) - self.view.show_popup( - message + "
Instruction", on_navigate=open_link - ) - self.error(PT_TAG.sub("", message) + " Instruction > " + url) + message + '
Instruction', on_navigate=open_link) + self.error(PT_TAG.sub('', message) + ' Instruction > ' + url) # Create TOC ------------------ - toc = "" + toc = '' _ids = [] level_counters = [0] - remove_image = attrs["remove_image"] - link_prefix = attrs["link_prefix"] - bullets = attrs["bullets"] + remove_image = attrs['remove_image'] + link_prefix = attrs['link_prefix'] + bullets = attrs['bullets'] for item in items: _id = None @@ -254,12 +251,11 @@ def open_link(v): # Remove markdown image which not in codeblock images = [] codes = [] - for m in re.compile(r"`[^`]*`").finditer(_text): + for m in re.compile(r'`[^`]*`').finditer(_text): codes.append([m.start(), m.end()]) def not_in_codeblock(_target): return not Util.within_ranges(_target, codes) - # Collect images not in codeblock for m in PT_IMAGE.finditer(_text): images.append([m.start(), m.end()]) @@ -268,29 +264,28 @@ def not_in_codeblock(_target): def _replace(m): if m.start() in images: - return "" + return '' else: return m.group(0) - _text = re.sub(PT_IMAGE, _replace, _text) _list_bullet = bullets[_indent % len(bullets)] - _text = PT_TAG.sub("", _text) # remove html tags + _text = PT_TAG.sub('', _text) # remove html tags _text = _text.strip() # remove start and end spaces # Ignore links: e.g. '[link](http://sample.com/)' -> 'link' # this is [link](http://www.sample.com/) - link = re.compile(r"([^!])\[([^\]]+)\]\([^\)]+\)") - _text = link.sub("\\1\\2", _text) + link = re.compile(r'([^!])\[([^\]]+)\]\([^\)]+\)') + _text = link.sub('\\1\\2', _text) # [link](http://www.sample.com/) link in the beginning of line - beginning_link = re.compile(r"^\[([^\]]+)\]\([^\)]+\)") - _text = beginning_link.sub("\\1", _text) + beginning_link = re.compile(r'^\[([^\]]+)\]\([^\)]+\)') + _text = beginning_link.sub('\\1', _text) # Add indent for i in range(_indent): - _prefix = attrs["indent"] + _prefix = attrs['indent'] # Support escaped characters like '\t' - _prefix = _prefix.encode().decode("unicode-escape") + _prefix = _prefix.encode().decode('unicode-escape') toc += _prefix # ----------------- @@ -301,15 +296,12 @@ def filtering(ref_links, text): images = [] codes = [] valids = [] - for m in re.compile(r"`[^`]*`").finditer(text): + for m in re.compile(r'`[^`]*`').finditer(text): codes.append([m.start(), m.end()]) - def not_in_codeblock(target): return not Util.within_ranges(target, codes) - def not_in_image(target): return not Util.within_ranges(target, images) - # Collect images not in codeblock for m in PT_IMAGE.finditer(text): images.append([m.start(), m.end()]) @@ -332,32 +324,30 @@ def not_in_image(target): if len(ref_links): match = ref_links[-1] - _text = ( - _text[0: match.start()].replace( - "[", "").replace("]", "").rstrip() - ) - _id = match.group().replace("[", "").replace("]", "") + _text = _text[0:match.start()].replace( + '[', '').replace(']', '').rstrip() + _id = match.group().replace('[', '').replace(']', '') elif match_ex_id: - _text = _text[0: match_ex_id.start()].rstrip() - _id = match_ex_id.group().replace("{#", "").replace("}", "") - elif attrs["autolink"]: + _text = _text[0:match_ex_id.start()].rstrip() + _id = match_ex_id.group().replace('{#', '').replace('}', '') + elif attrs['autolink']: _id = Id( - self.settings("id_replacements"), - attrs["markdown_preview"], - str(attrs["lowercase"]).lower(), - ).heading_to_id(_text) - if attrs["uri_encoding"]: + self.settings('id_replacements'), + attrs['markdown_preview'], + str(attrs['lowercase']).lower() + ).heading_to_id(_text) + if attrs['uri_encoding']: _id = quote(_id) _ids.append(_id) n = _ids.count(_id) if 1 < n: - _id += "-" + str(n - 1) + _id += '-' + str(n - 1) - if attrs["style"] == "unordered": - list_prefix = _list_bullet + " " - elif attrs["style"] == "ordered": - list_prefix = "1. " + if attrs['style'] == 'unordered': + list_prefix = _list_bullet + ' ' + elif attrs['style'] == 'ordered': + list_prefix = '1. ' # escape brackets _text = self.escape_brackets(_text) @@ -366,15 +356,15 @@ def not_in_image(target): _id = link_prefix + _id if _id is None: - toc += list_prefix + _text + "\n" - elif attrs["bracket"] == "round": - toc += list_prefix + "[" + _text + "](#" + _id + ")\n" + toc += list_prefix + _text + '\n' + elif attrs['bracket'] == 'round': + toc += list_prefix + '[' + _text + '](#' + _id + ')\n' else: - toc += list_prefix + "[" + _text + "][" + _id + "]\n" + toc += list_prefix + '[' + _text + '][' + _id + ']\n' item.append(_id) - self.update_anchors(edit, items, attrs["autoanchor"]) + self.update_anchors(edit, items, attrs['autoanchor']) return toc @@ -388,7 +378,7 @@ def update_anchors(self, edit, items, autoanchor): if autoanchor: # if autolink=false then item[3] will be None, # so use raw heading valie(replaced whitespaces) then - _id = item[3] or re.sub(r"\s+", "-", item[1]) + _id = item[3] or re.sub(r'\s+', '-', item[1]) if is_update: new_anchor = ''.format(_id) v.replace(edit, anchor_region, new_anchor) @@ -400,23 +390,20 @@ def update_anchors(self, edit, items, autoanchor): if is_update: v.erase( edit, - sublime.Region(anchor_region.begin(), - anchor_region.end() + 1), - ) + sublime.Region( + anchor_region.begin(), + anchor_region.end() + 1)) def get_attributes_from(self, tag_str): """return dict of settings from tag_str""" pattern = re.compile( - r'\b(?P\w+)=((?P)|(\'(?P[^\']+)\')|("(?P[^"]+)")|(?P\S+))\s' - ) + r'\b(?P\w+)=((?P)|(\'(?P[^\']+)\')|("(?P[^"]+)")|(?P\S+))\s') attrs = dict( - ( - m.group("name"), - m.group("simple") - or m.group("dquoted") - or m.group("quoted") - or m.group("empty"), - ) + (m.group('name'), + m.group('simple') or + m.group('dquoted') or + m.group('quoted') or + m.group('empty')) for m in pattern.finditer(tag_str) ) @@ -424,7 +411,7 @@ def get_attributes_from(self, tag_str): defaults = self.defaults() for key in attrs: if type(defaults[key]) is list: - attrs[key] = attrs[key].split(",") + attrs[key] = attrs[key].split(',') elif type(defaults[key]) is bool: attrs[key] = Util.strtobool(attrs[key]) @@ -442,6 +429,8 @@ def remove_items_in_codeblock(self, items): codeblockAreas.append([area_begin, area_end]) i += 2 - items = [h for h in items if Util.is_out_of_areas( - h.begin(), codeblockAreas)] - return items + items = [ + h for h in items if Util.is_out_of_areas( + h.begin(), + codeblockAreas)] + return items \ No newline at end of file From 050ffc12e6b5386bce2bf4fa4c9d39d6a48e6461 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Fri, 22 May 2020 15:28:29 -0400 Subject: [PATCH 03/27] fix: formatting, quotes --- markdowntoc/markdowntoc_insert.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 81c5366..322d957 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -1,16 +1,16 @@ import pprint import re +import sublime +import sublime_plugin import sys import webbrowser -from urllib.parse import quote -import sublime -import sublime_plugin +from urllib.parse import quote from .autorunner import AutoRunner from .base import Base -from .id import Id from .util import Util +from .id import Id # for debug pp = pprint.PrettyPrinter(indent=4) @@ -21,12 +21,12 @@ # ![alt](path/to/image.png) PT_IMAGE = re.compile(r'!\[([^\]]+)\]\([^\)]+\)') - # [Heading]{#my-id} PT_EX_ID = re.compile(r'\{#.+?\}$') PT_TAG = re.compile(r'<.*?>') PT_ANCHOR = re.compile(r'\s*') + # PT_DISCRETE = re.compile( r'^', re.IGNORECASE From c9ae8a07f65fddb6d018a73b18b483c540295d46 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Fri, 22 May 2020 15:31:12 -0400 Subject: [PATCH 04/27] revert: additional formatting issues --- markdowntoc/markdowntoc_insert.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 322d957..420aafa 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -55,8 +55,8 @@ def run(self, edit): def get_toc_open_tag(self): search_results = self.view.find_all( - r'^\n', sublime.IGNORECASE - ) + r'^\n', + sublime.IGNORECASE) search_results = self.remove_items_in_codeblock(search_results) toc_open_tags = [] @@ -127,7 +127,6 @@ def not_in_codeblock(target): def not_in_image(target): return not Util.within_ranges(target, images) - # Collect images not in codeblock for m in PT_IMAGE.finditer(_text): images.append([m.start(), m.end()]) @@ -190,7 +189,6 @@ def get_discrete_header(discrete, heading): r = sublime.Region(heading.end() - 1, self.view.line(heading).end()) text = self.view.substr(r).strip().rstrip("#") - # indent = heading.size() - 1 indent, discrete_active = get_discrete_header( discrete_active, heading.size() - 1 ) From 85290fc29cb25dfd36bd410c88c59a4cbbc37934 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Fri, 22 May 2020 16:41:15 -0400 Subject: [PATCH 05/27] fix quotes --- markdowntoc/markdowntoc_insert.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 420aafa..ce0a108 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -188,7 +188,7 @@ def get_discrete_header(discrete, heading): # handle hash headings, ### chapter 1 r = sublime.Region(heading.end() - 1, self.view.line(heading).end()) - text = self.view.substr(r).strip().rstrip("#") + text = self.view.substr(r).strip().rstrip('#') indent, discrete_active = get_discrete_header( discrete_active, heading.size() - 1 ) @@ -203,7 +203,7 @@ def get_discrete_header(discrete, heading): text = self.view.substr(lines[0]) if text.strip(): heading_type = self.view.substr(lines[1])[0] - indent = 1 if heading_type == "=" else 2 + indent = 1 if heading_type == '=' else 2 indent, discrete_active = get_discrete_header( discrete_active, heading.size() - 1 ) From 04f9b9b54d2f9671899ace04f2d301c0c9afe1ad Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 24 May 2020 20:13:10 +0900 Subject: [PATCH 06/27] Fix unit test FAIL: test_uniquify_id_2 (default.TestDefault) --- markdowntoc/markdowntoc_insert.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 7dde35b..498a76b 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -166,25 +166,16 @@ def get_toc(self, attrs, begin, edit): headings = self.remove_items_in_codeblock(headings) - def get_discrete_header(discrete, heading): - if discrete and heading == 1: - return 1, False - elif heading > 1 and discrete: - return heading - 1, discrete - return heading, discrete - if len(headings) < 1: return '' items = [] # [[headingNum, text, position, anchor_id], ...] - discrete_active = False for heading in headings: if begin < heading.end(): lines = self.view.lines(heading) previous_line = self.view.substr( self.view.line(lines[0].a - 1)) if PT_DISCRETE.match(previous_line): - discrete_active = True continue if len(lines) == 1: @@ -192,10 +183,7 @@ def get_discrete_header(discrete, heading): r = sublime.Region(heading.end() - 1, self.view.line(heading).end()) text = self.view.substr(r).strip().rstrip('#') - indent, discrete_active = get_discrete_header( - discrete_active, heading.size() - 1 - ) - + indent = heading.size() - 1 items.append([indent, text, heading.begin()]) elif len(lines) == 2: # handle = or - headings @@ -207,9 +195,6 @@ def get_discrete_header(discrete, heading): if text.strip(): heading_type = self.view.substr(lines[1])[0] indent = 1 if heading_type == '=' else 2 - indent, discrete_active = get_discrete_header( - discrete_active, heading.size() - 1 - ) items.append([indent, text, heading.begin()]) if len(items) < 1: From 2c07c51f9d6de4cb862f5017120fcdc81f0e066f Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 24 May 2020 20:32:00 +0900 Subject: [PATCH 07/27] - Move test to a file - Add level check test --- tests/discrete_heading.py | 68 +++++++++++++++++++++++++++++++++++++++ tests/levels.py | 26 --------------- 2 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 tests/discrete_heading.py diff --git a/tests/discrete_heading.py b/tests/discrete_heading.py new file mode 100644 index 0000000..290f2e1 --- /dev/null +++ b/tests/discrete_heading.py @@ -0,0 +1,68 @@ +# coding:utf-8 +from base import TestBase + +class TestDiscreteHeading(TestBase): + '''Ignore discrete heading''' + + # for debug + # def tearDown(self): + # pass + + text_1 = ''' + + + + + +# heading 1 + + +# heading 2 + +# heading 3 + +''' + + def test_discrete_heading(self): + '''Default is no limit''' + toc = self.init_update(self.text_1)['toc'] + self.assert_In('- heading 1', toc) + self.assert_NotIn('- heading 2', toc) + self.assert_In('- heading 3', toc) + + text_2 = ''' + + + + + +# level 1 + +## level 2 +### level 3 + +#### level 4 + +##### level 5 +###### level 6 + +''' + + def test_discrete_heading_level(self): + '''Level is correct''' + toc = self.init_update(self.text_2)['toc'] + # existence + self.assert_In('- level 1', toc) + self.assert_NotIn('- level 2', toc) + self.assert_In('- level 3', toc) + self.assert_NotIn('- level 4', toc) + self.assert_NotIn('- level 5', toc) + self.assert_In('- level 6', toc) + # level + self.assert_In('- level 1', toc) + self.assert_In(' - level 3', toc) + self.assert_In(' - level 6', toc) + + self.assert_NotIn(' - level 2', toc) + self.assert_NotIn(' - level 5', toc) + self.assert_NotIn(' - level 6', toc) \ No newline at end of file diff --git a/tests/levels.py b/tests/levels.py index b1ce83c..4c10b33 100644 --- a/tests/levels.py +++ b/tests/levels.py @@ -126,29 +126,3 @@ def test_levels_specific_levels(self): self.assert_In('- heading 2', toc) self.assert_NotIn('- heading 5', toc) self.assert_In('- heading 6', toc) - - - text_3 = """ - - - - - -# heading 1 - -## heading 2 - -### heading 3 - -#### heading 4 -###### heading 7 -""" - - def test_levels_discrete_levels(self): - """Default is no limit""" - toc = self.init_update(self.text_3)["toc"] - self.assert_In("- heading 1", toc) - self.assert_In("- heading 2", toc) - self.assert_In("- heading 3", toc) - self.assert_NotIn("- heading 4", toc) - self.assert_In("- heading 7", toc) \ No newline at end of file From 07c14b5eca8998cadd96e747040acdd5a554ff3b Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 24 May 2020 20:51:53 +0900 Subject: [PATCH 08/27] Cleanup --- tests/discrete_heading.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/discrete_heading.py b/tests/discrete_heading.py index 290f2e1..74c12eb 100644 --- a/tests/discrete_heading.py +++ b/tests/discrete_heading.py @@ -62,7 +62,6 @@ def test_discrete_heading_level(self): self.assert_In('- level 1', toc) self.assert_In(' - level 3', toc) self.assert_In(' - level 6', toc) - self.assert_NotIn(' - level 2', toc) self.assert_NotIn(' - level 5', toc) self.assert_NotIn(' - level 6', toc) \ No newline at end of file From 1fed2f7f537aff2caa08f2530f17f9ed0f4d1d57 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sun, 24 May 2020 08:08:15 -0400 Subject: [PATCH 09/27] =?UTF-8?q?rename:=20discrete=20=E2=86=92=20exclude?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- markdowntoc/markdowntoc_insert.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 498a76b..8bae828 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -28,9 +28,9 @@ -# -PT_DISCRETE = re.compile( - r'^', re.IGNORECASE +# +PT_EXCLUDE = re.compile( + r'^', re.IGNORECASE ) @@ -175,7 +175,7 @@ def get_toc(self, attrs, begin, edit): lines = self.view.lines(heading) previous_line = self.view.substr( self.view.line(lines[0].a - 1)) - if PT_DISCRETE.match(previous_line): + if PT_EXCLUDE.match(previous_line): continue if len(lines) == 1: From b9ec733cb3c3e1228891734970bb91cc0e5d9467 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sun, 24 May 2020 08:10:53 -0400 Subject: [PATCH 10/27] quotes --- markdowntoc/markdowntoc_insert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index 8bae828..ca39106 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -50,7 +50,7 @@ def run(self, edit): toc += '\n' self.view.insert(edit, sel.begin(), toc) - self.log("inserted TOC") + self.log('inserted TOC') # TODO: process to add another toc when tag exists From b47309b1cde99f1aa7e1f74f3f353af6dbf75e97 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sun, 24 May 2020 08:11:53 -0400 Subject: [PATCH 11/27] quote alignment --- markdowntoc/markdowntoc_insert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdowntoc/markdowntoc_insert.py b/markdowntoc/markdowntoc_insert.py index ca39106..b8a5446 100644 --- a/markdowntoc/markdowntoc_insert.py +++ b/markdowntoc/markdowntoc_insert.py @@ -120,7 +120,7 @@ def do_escape(_text, _pattern, _open, _close): images = [] brackets = [] codes = [] - for m in re.compile(r"`[^`]*`").finditer(_text): + for m in re.compile(r'`[^`]*`').finditer(_text): codes.append([m.start(), m.end()]) def not_in_codeblock(target): From d1b069275d84b4d7981d539fe5a5f28037c709c7 Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sun, 24 May 2020 08:17:08 -0400 Subject: [PATCH 12/27] unit tests fixed --- tests/discrete_heading.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/discrete_heading.py b/tests/discrete_heading.py index 74c12eb..5b16370 100644 --- a/tests/discrete_heading.py +++ b/tests/discrete_heading.py @@ -16,7 +16,7 @@ class TestDiscreteHeading(TestBase): # heading 1 - + # heading 2 # heading 3 @@ -37,12 +37,12 @@ def test_discrete_heading(self): # level 1 - + ## level 2 ### level 3 - + #### level 4 - + ##### level 5 ###### level 6 From 9e8522e172fd6a61abee44936e94654ccdeb992f Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sun, 24 May 2020 08:23:26 -0400 Subject: [PATCH 13/27] rename discrete to exclude, fix unittests --- tests/{discrete_heading.py => exclude_heading.py} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename tests/{discrete_heading.py => exclude_heading.py} (83%) diff --git a/tests/discrete_heading.py b/tests/exclude_heading.py similarity index 83% rename from tests/discrete_heading.py rename to tests/exclude_heading.py index 5b16370..5ba139c 100644 --- a/tests/discrete_heading.py +++ b/tests/exclude_heading.py @@ -1,8 +1,8 @@ # coding:utf-8 from base import TestBase -class TestDiscreteHeading(TestBase): - '''Ignore discrete heading''' +class TestExcludeHeading(TestBase): + '''Ignore exclude heading''' # for debug # def tearDown(self): @@ -23,7 +23,7 @@ class TestDiscreteHeading(TestBase): ''' - def test_discrete_heading(self): + def test_exclude_heading(self): '''Default is no limit''' toc = self.init_update(self.text_1)['toc'] self.assert_In('- heading 1', toc) @@ -48,7 +48,7 @@ def test_discrete_heading(self): ''' - def test_discrete_heading_level(self): + def test_exclude_heading_level(self): '''Level is correct''' toc = self.init_update(self.text_2)['toc'] # existence @@ -60,8 +60,8 @@ def test_discrete_heading_level(self): self.assert_In('- level 6', toc) # level self.assert_In('- level 1', toc) - self.assert_In(' - level 3', toc) - self.assert_In(' - level 6', toc) + self.assert_In(' - level 3', toc) + self.assert_In(' - level 6', toc) self.assert_NotIn(' - level 2', toc) self.assert_NotIn(' - level 5', toc) self.assert_NotIn(' - level 6', toc) \ No newline at end of file From dc3fed144659659d6bdd8d422bc3b6bf618c09b0 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sat, 30 May 2020 20:14:45 +0900 Subject: [PATCH 14/27] Suppress appveyor error? --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 0cda850..7175f81 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ test_script: # run tests with test coverage report - ps: .\appveyor.ps1 "run_tests" -coverage -verbose -after_test: +on_finish: - "SET PYTHON=C:\\Python33" - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - pip install codecov From f97f221dc267dfed2dba1e7cacea4253031f30f7 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sat, 30 May 2020 20:15:55 +0900 Subject: [PATCH 15/27] Fix Python version --- .python-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .python-version diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..a76ccff --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.7.1 From c15042c3ce283574c0350b9c4a27bb8957a08047 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sat, 30 May 2020 20:21:31 +0900 Subject: [PATCH 16/27] pip install pycodestyle --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cf4dc3d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pycodestyle==2.6.0 From ab2dd5a503d22e2389aa9a53b6f43f47a6c5ac02 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sat, 30 May 2020 20:35:52 +0900 Subject: [PATCH 17/27] pip install black --- requirements.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cf4dc3d..5f16e57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,8 @@ -pycodestyle==2.6.0 +appdirs==1.4.4 +attrs==19.3.0 +black==19.10b0 +click==7.1.2 +pathspec==0.8.0 +regex==2020.5.14 +toml==0.10.1 +typed-ast==1.4.1 From c95573cc0f45fd90c05c3b9bf4da36e610db77af Mon Sep 17 00:00:00 2001 From: TheSecEng Date: Sat, 30 May 2020 14:06:31 -0400 Subject: [PATCH 18/27] Fix unit tests --- tests/exclude_heading.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/exclude_heading.py b/tests/exclude_heading.py index 5ba139c..795214e 100644 --- a/tests/exclude_heading.py +++ b/tests/exclude_heading.py @@ -60,8 +60,8 @@ def test_exclude_heading_level(self): self.assert_In('- level 6', toc) # level self.assert_In('- level 1', toc) - self.assert_In(' - level 3', toc) - self.assert_In(' - level 6', toc) - self.assert_NotIn(' - level 2', toc) - self.assert_NotIn(' - level 5', toc) - self.assert_NotIn(' - level 6', toc) \ No newline at end of file + self.assert_In(' - level 3', toc) + self.assert_In(' - level 6', toc) + self.assert_NotIn(' - level 2', toc) + self.assert_NotIn(' - level 5', toc) + self.assert_NotIn(' - level 6', toc) From 2a75cb26e13761e43a787aa568b7e79cc73bc63a Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 12:39:54 +0900 Subject: [PATCH 19/27] Fix unit test --- tests/exclude_heading.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tests/exclude_heading.py b/tests/exclude_heading.py index 795214e..4d87a5c 100644 --- a/tests/exclude_heading.py +++ b/tests/exclude_heading.py @@ -49,19 +49,13 @@ def test_exclude_heading(self): ''' def test_exclude_heading_level(self): - '''Level is correct''' + '''Existence and level is correct''' toc = self.init_update(self.text_2)['toc'] # existence - self.assert_In('- level 1', toc) self.assert_NotIn('- level 2', toc) - self.assert_In('- level 3', toc) self.assert_NotIn('- level 4', toc) self.assert_NotIn('- level 5', toc) - self.assert_In('- level 6', toc) # level - self.assert_In('- level 1', toc) - self.assert_In(' - level 3', toc) - self.assert_In(' - level 6', toc) - self.assert_NotIn(' - level 2', toc) - self.assert_NotIn(' - level 5', toc) - self.assert_NotIn(' - level 6', toc) + self.assert_In('''- level 1 + - level 3 + - level 6''', toc) From 8d11343de1b1c2b5e0799df9dc46c5cbd3d35bd3 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 14:36:16 +0900 Subject: [PATCH 20/27] Add 'Excluded heading' into README --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 4cd3d7f..33a711c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown doc - [Customizable list bullets in TOC](#customizable-list-bullets-in-toc) - [Specify custom indentation prefix](#specify-custom-indentation-prefix) - [Preserve images in headings](#preserve-images-in-headings) + - [Excluded heading](#excluded-heading) - [Usage](#usage) - [Tips](#tips) - [How to remove anchors added by MarkdownTOC](#how-to-remove-anchors-added-by-markdowntoc) @@ -98,6 +99,7 @@ The **MarkdownTOC** plugin is rich on features and customization, useful for bot - [Customizable list bullets in TOC](#customizable-list-bullets-in-toc) - [Specify custom indentation prefix](#specify-custom-indentation-prefix) - [Preserve images in headings](#preserve-images-in-headings) +- [Excluded heading](#excluded-heading) ### Insertion of TOC based on headings in Markdown document @@ -722,6 +724,17 @@ Please note that the default for the [attribute](#attributes) is: `false`. You can change your default setting in your [configuration](#configuration) with the key `defaults.remove_image`. +### Excluded heading + +You can exclude certain headings in the TOC by adding a special comment to the line before the heading, as shown below. + +```markdown + +## This heading will excluded +``` + +You can change your default setting in your [configuration](#configuration) with the key `defaults.remove_image`. + ## Usage 1. Open your [Markdown] file From 42fe03090c3758fdf4e59cf2be80a29beb2090d3 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 14:36:38 +0900 Subject: [PATCH 21/27] Update TOC --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33a711c..d58b687 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown doc - [Supported file extensions](#supported-file-extensions) - [Customizing generation of TOC using attributes](#customizing-generation-of-toc-using-attributes) - [Auto anchoring when heading has anchor defined](#auto-anchoring-when-heading-has-anchor-defined) - - [Auto linking for _clickable_ TOC](#auto-linking-for-clickable-toc) + - [Auto linking for _clickable_ TOC](#auto-linking-for-_clickable_-toc) - [Lowercasing in ids](#lowercasing-in-ids) - [Preserve case](#preserve-case) - [Lowercase all characters](#lowercase-all-characters) @@ -46,6 +46,7 @@ Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown doc - [Tips](#tips) - [How to remove anchors added by MarkdownTOC](#how-to-remove-anchors-added-by-markdowntoc) - [Addressing issues with Github Pages](#addressing-issues-with-github-pages) + - [Using MarkdownTOC with Markdownlint](#using-markdowntoc-with-markdownlint) - [Limitations](#limitations) - [Headings in lists are not included in the auto-generated table of contents](#headings-in-lists-are-not-included-in-the-auto-generated-table-of-contents) - [Attributes](#attributes) From e9a3212a7200840fce5c33cfa780da1d151e5c68 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 14:49:13 +0900 Subject: [PATCH 22/27] Add message for 4.1.0 --- messages/4.1.0.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 messages/4.1.0.md diff --git a/messages/4.1.0.md b/messages/4.1.0.md new file mode 100644 index 0000000..d1329e9 --- /dev/null +++ b/messages/4.1.0.md @@ -0,0 +1,6 @@ +# MarkdownTOC - 4.1.0 + +## Changes + +- Add Excluded heading feature Ref: [#140](https://github.com/naokazuterada/MarkdownTOC/issues/140), [#149](https://github.com/naokazuterada/MarkdownTOC/pull/149) +- Update "Coding Style" in CONTRIBUTING.md From 4596bf7abc840a3d37db23270d418eb37444e33e Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 14:51:13 +0900 Subject: [PATCH 23/27] Fix sentence --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d58b687..cca828e 100644 --- a/README.md +++ b/README.md @@ -731,7 +731,7 @@ You can exclude certain headings in the TOC by adding a special comment to the l ```markdown -## This heading will excluded +## This heading will be excluded ``` You can change your default setting in your [configuration](#configuration) with the key `defaults.remove_image`. From 285a3177ac9b68f5a34983e02595c780f5259fa6 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 14:52:32 +0900 Subject: [PATCH 24/27] Delete wrong line --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index cca828e..2e34e1c 100644 --- a/README.md +++ b/README.md @@ -734,8 +734,6 @@ You can exclude certain headings in the TOC by adding a special comment to the l ## This heading will be excluded ``` -You can change your default setting in your [configuration](#configuration) with the key `defaults.remove_image`. - ## Usage 1. Open your [Markdown] file From 468fa806386c0eeecb0f77ea45080237bad64077 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 15:04:19 +0900 Subject: [PATCH 25/27] Cleanup: Removing extra white space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e34e1c..9d3be37 100644 --- a/README.md +++ b/README.md @@ -730,7 +730,7 @@ You can change your default setting in your [configuration](#configuration) with You can exclude certain headings in the TOC by adding a special comment to the line before the heading, as shown below. ```markdown - + ## This heading will be excluded ``` From 472f64822167cb65420f272cb08d4c8487cfaa26 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 15:51:34 +0900 Subject: [PATCH 26/27] Remove requirements.txt as it's not related to the feature itself --- requirements.txt | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5f16e57..0000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -appdirs==1.4.4 -attrs==19.3.0 -black==19.10b0 -click==7.1.2 -pathspec==0.8.0 -regex==2020.5.14 -toml==0.10.1 -typed-ast==1.4.1 From 47ee29cb4fa0931e2b7ef8b4462466655730f5e6 Mon Sep 17 00:00:00 2001 From: Naokazu Terada Date: Sun, 7 Jun 2020 17:52:13 +0900 Subject: [PATCH 27/27] Rewrite according to suggestions --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9d3be37..b669f58 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown doc - [Customizable list bullets in TOC](#customizable-list-bullets-in-toc) - [Specify custom indentation prefix](#specify-custom-indentation-prefix) - [Preserve images in headings](#preserve-images-in-headings) - - [Excluded heading](#excluded-heading) + - [Excluded headings](#excluded-headings) - [Usage](#usage) - [Tips](#tips) - [How to remove anchors added by MarkdownTOC](#how-to-remove-anchors-added-by-markdowntoc) @@ -100,7 +100,7 @@ The **MarkdownTOC** plugin is rich on features and customization, useful for bot - [Customizable list bullets in TOC](#customizable-list-bullets-in-toc) - [Specify custom indentation prefix](#specify-custom-indentation-prefix) - [Preserve images in headings](#preserve-images-in-headings) -- [Excluded heading](#excluded-heading) +- [Excluded headings](#excluded-heading) ### Insertion of TOC based on headings in Markdown document @@ -725,9 +725,9 @@ Please note that the default for the [attribute](#attributes) is: `false`. You can change your default setting in your [configuration](#configuration) with the key `defaults.remove_image`. -### Excluded heading +### Excluded headings -You can exclude certain headings in the TOC by adding a special comment to the line before the heading, as shown below. +You can exclude certain headings in the TOC by adding a special comment to the line above the line with the heading, as shown below. ```markdown