/markdown/extensions/headerid.py

https://gitlab.com/Haritiana/Python-Markdown · Python · 97 lines · 62 code · 14 blank · 21 comment · 12 complexity · cede76c50a1e0a5826e3e10c8f8c0f67 MD5 · raw file

  1. """
  2. HeaderID Extension for Python-Markdown
  3. ======================================
  4. Auto-generate id attributes for HTML headers.
  5. See <https://pythonhosted.org/Markdown/extensions/header_id.html>
  6. for documentation.
  7. Original code Copyright 2007-2011 [Waylan Limberg](http://achinghead.com/).
  8. All changes Copyright 2011-2014 The Python Markdown Project
  9. License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
  10. """
  11. from __future__ import absolute_import
  12. from __future__ import unicode_literals
  13. from . import Extension
  14. from ..treeprocessors import Treeprocessor
  15. from ..util import parseBoolValue
  16. from .toc import slugify, unique, stashedHTML2text
  17. import warnings
  18. class HeaderIdTreeprocessor(Treeprocessor):
  19. """ Assign IDs to headers. """
  20. IDs = set()
  21. def run(self, doc):
  22. start_level, force_id = self._get_meta()
  23. slugify = self.config['slugify']
  24. sep = self.config['separator']
  25. for elem in doc:
  26. if elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']:
  27. if force_id:
  28. if "id" in elem.attrib:
  29. id = elem.get('id')
  30. else:
  31. id = stashedHTML2text(''.join(elem.itertext()), self.md)
  32. id = slugify(id, sep)
  33. elem.set('id', unique(id, self.IDs))
  34. if start_level:
  35. level = int(elem.tag[-1]) + start_level
  36. if level > 6:
  37. level = 6
  38. elem.tag = 'h%d' % level
  39. def _get_meta(self):
  40. """ Return meta data suported by this ext as a tuple """
  41. level = int(self.config['level']) - 1
  42. force = parseBoolValue(self.config['forceid'])
  43. if hasattr(self.md, 'Meta'):
  44. if 'header_level' in self.md.Meta:
  45. level = int(self.md.Meta['header_level'][0]) - 1
  46. if 'header_forceid' in self.md.Meta:
  47. force = parseBoolValue(self.md.Meta['header_forceid'][0])
  48. return level, force
  49. class HeaderIdExtension(Extension):
  50. def __init__(self, *args, **kwargs):
  51. # set defaults
  52. self.config = {
  53. 'level': ['1', 'Base level for headers.'],
  54. 'forceid': ['True', 'Force all headers to have an id.'],
  55. 'separator': ['-', 'Word separator.'],
  56. 'slugify': [slugify, 'Callable to generate anchors']
  57. }
  58. super(HeaderIdExtension, self).__init__(*args, **kwargs)
  59. warnings.warn(
  60. 'The HeaderId Extension is pending deprecation. Use the TOC Extension instead.',
  61. PendingDeprecationWarning
  62. )
  63. def extendMarkdown(self, md, md_globals):
  64. md.registerExtension(self)
  65. self.processor = HeaderIdTreeprocessor()
  66. self.processor.md = md
  67. self.processor.config = self.getConfigs()
  68. if 'attr_list' in md.treeprocessors.keys():
  69. # insert after attr_list treeprocessor
  70. md.treeprocessors.add('headerid', self.processor, '>attr_list')
  71. else:
  72. # insert after 'prettify' treeprocessor.
  73. md.treeprocessors.add('headerid', self.processor, '>prettify')
  74. def reset(self):
  75. self.processor.IDs = set()
  76. def makeExtension(*args, **kwargs):
  77. return HeaderIdExtension(*args, **kwargs)