Open chriselderer opened 1 year ago
Hi I was experiencing the same issue. My solution was just to create a function to strip the link syntax from any header names.
function removeBrackets(str) {
if (typeof str == 'string') {
return str.replace(/^[\[\]]+|[\[\]]+$/g, '');
}
}
Then in the if statement around line 214 where you see the final return for each line of the ToC, I called that function on the headings. Like so:
if (typeof previousLevelHeading == "undefined") {
return `${indent}${itemIndication} [[#${removeBrackets(heading.heading)}|${removeBrackets(heading.heading)}]]`;
} else {
return `${indent}${itemIndication} [[#${removeBrackets(previousLevelHeading.heading)}#${removeBrackets(heading.heading)}|${removeBrackets(heading.heading)}]]`;
}
You could also define strings with the stripped text use those, but make sure to initialize the one for previousLevelHeading within the if statement that checks if one exists.
@wimiam1 Would you want to submit a PR for that?
Yeah, headings with links continues to break this TOC extension. I ended up writing a more robust ToC script in python. Sorry, I don't know how to make an obsidian extension.
import re
import sys
import glob
def process_markdown_file(input_file_name):
# Extract page title from input file name
page_title = input_file_name.split('.')[0]
# Capture the file extension
extension = input_file_name.split('.')[-1]
# Initialize empty lists to store processed lines
link_parts = []
presentation_parts = []
heading_levels = []
# Initialize flag to track whether we're inside a code block
inside_code_block = False
# Read input file and process lines
with open(input_file_name, 'r') as input_file:
for line in input_file:
# Check if we're entering or exiting a code block
if line.strip().startswith('```'):
inside_code_block = not inside_code_block
continue
# Only process lines if we're not inside a code block
if not inside_code_block:
match = re.match(r'^(#+)\s+(.+)', line)
if match:
heading_level = len(match.group(1))
link_content = match.group(2).replace('[', '').replace(']', '')
if '|' in link_content or '#' in link_content:
# Process link content with pipe and/or hash
if '#' in link_content:
link_content = link_content.replace('#', '')
parts = [part.strip() for part in link_content.split('|')]
link_part = ' '.join(parts)
presentation_part = parts[-1]
else:
# Process link content without pipe and/or hash
link_part = link_content.strip()
presentation_part = link_content.strip()
link_parts.append(link_part)
presentation_parts.append(presentation_part)
heading_levels.append(heading_level)
# Build new lines
new_lines = []
for i, (link_part, presentation_part, heading_level) in enumerate(zip(link_parts, presentation_parts, heading_levels)):
new_line = '\t' * (heading_level - 1) + '- [[' + page_title + '#' + link_part + '|' + presentation_part + ']]'
new_lines.append(new_line)
# Write output file
output_file_name = input_file_name.replace('.' + extension, 'TOC.' + extension)
with open(output_file_name, 'w') as output_file:
output_file.write('\n'.join(new_lines))
# Print completion message
print(f'Output written to {output_file_name}')
if __name__ == '__main__':
if len(sys.argv) < 2:
print('Usage: python3 extractTOC.py <input_file_name> or python3 extractTOC.py <pattern>')
sys.exit(1)
input_files = []
for arg in sys.argv[1:]:
input_files.extend(glob.glob(arg))
if not input_files:
print('No files found matching the input pattern')
sys.exit(1)
for input_file_name in input_files:
process_markdown_file(input_file_name)
Maybe it's not perfect but it has worked great for everything that I've thrown at it so far.
currently # [[My Heading Link]] turns to [[#[[My Heading Link]]|[[My Heading Link]]]]
The Stripping the [[]] from the heading when you link it works just fine
should look like: # [[My Heading Link]] -> [[#My Heading Link|My Heading Link]]