squidfunk / mkdocs-material

Documentation that simply works

Home Page:https://squidfunk.github.io/mkdocs-material/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature Suggestion: Reference parts of source files in code blocks

001ben opened this issue · comments

Contribution guidelines

I want to suggest an idea and checked that ...

  • ... to my best knowledge, my idea wouldn't break something for other users
  • ... the documentation does not mention anything about my idea
  • ... there are no open or closed issues that are related to my idea

Description

The mkdocs framework is incredibly useful, especially to add documents to technical projects where we may refer to parts of an existing codebase as we're documenting.

Github supports references to regions of source files where where it provides a link to the file, and shows the snippet of code in issues/PR's like so:

# Project information
site_name: Material for MkDocs
site_url: https://squidfunk.github.io/mkdocs-material/

Referencing code in a similar way would be an incredible value add for technical documentation, currently i don't think it's straightforward to achieve this.

Code blocks + snippets currently would let you include an entire external file inside a highlighted code block like so:

```python title="src/some_file.py"
--8<-- "src/some_file.py"
```

From my limited knowledge I believe the following functionality is missing:

  • hyperlinking from the title of a fenced code block
  • limiting the output from the snippet to only include a subset of lines from the file
  • bonus: the additional fancy output which displays the line numbers and commit SHA

There have been a number of previous issues/discussions around this sort of functionality, including:

Previous discussions note that some of this functionality is more related to markdown processing, but potentially there is some functionality - i.e. potentially title hyperlinking/formatting, which might need to live here?

Use Cases

This feature would assist documenting and explaining source code within technical projects

Screenshots / Mockups

No response

Thanks for suggesting. As you already said, this is in large parts beyond the scope of this project, but besides the simple solutions involving Snippets, there's also mkdocstrings by @pawamoy, with which I'm working closely. We're planning to improve interop between mkdocstrings and Material for MkDocs in the future, but we're currently still in ideation phase. The things you mentioned are largely already supported by mkdocstrings, though. I invite you to check out the project and deepen the discussion over at their repository!

I'm closing this issue, as there are no actionables for us.

Ah fantastic! thank you for the heads up :D

I've build a small workaround to implement this using mkdocs-simple-hooks package:

import re
import urllib.request

def replacer(match):
  filename = f'{match.group(3)}.{match.group(4)}'
  url = f'https://raw.githubusercontent.com/{match.group(1)}/{match.group(2)}/{filename}'
  code = urllib.request.urlopen(url).read().decode('utf-8')
  return '\n'.join(
    [f'``` {match.group(4)} title="{filename}"'] +
    code.split('\n')[int(match.group(5)) - 1:int(match.group(6))] +
    ['```', f'View at [GitHub]({match.group(0)})']
  )

def page_markdown(markdown, **kwargs):
  return re.sub(
    re.compile(
      r'^https://github.com/([\w/\-]+)/blob/([0-9a-f]+)/([\w\d\-/\.]+)\.(\w+)#L(\d+)-L(\d+)$',
      re.MULTILINE,
    ),
    replacer,
    markdown,
  )

It is applied in aeternity/aepp-sdk-js#1617

I've build a small workaround to implement this using mkdocs-simple-hooks package:

import re
import urllib.request

def replacer(match):
  filename = f'{match.group(3)}.{match.group(4)}'
  url = f'https://raw.githubusercontent.com/{match.group(1)}/{match.group(2)}/{filename}'
  code = urllib.request.urlopen(url).read().decode('utf-8')
  return '\n'.join(
    [f'``` {match.group(4)} title="{filename}"'] +
    code.split('\n')[int(match.group(5)) - 1:int(match.group(6))] +
    ['```', f'View at [GitHub]({match.group(0)})']
  )

def page_markdown(markdown, **kwargs):
  return re.sub(
    re.compile(
      r'^https://github.com/([\w/\-]+)/blob/([0-9a-f]+)/([\w\d\-/\.]+)\.(\w+)#L(\d+)-L(\d+)$',
      re.MULTILINE,
    ),
    replacer,
    markdown,
  )

It is applied in aeternity/aepp-sdk-js#1617

Hey dude, really appreciatte the stuff you did there, also been trying out your solution, but unfortunately they don't seem to work inside of admonitions, i'd gladly appreciatte if you could maybe guide me to the right direction here

@MetalKnight56 It needs to preserve spacing of the original url, here is an updated hook:

import re
import urllib.request

def replacer(match):
  filename = f"{match.group('filename')}.{match.group('extension')}"
  url = f"https://raw.githubusercontent.com/{match.group('user')}/{match.group('commit')}/{filename}"
  code = urllib.request.urlopen(url).read().decode('utf-8')
  extension = 'js' if match.group('extension') == 'vue' else match.group('extension')
  spacing = match.group('spacing')
  return '\n'.join(
    [f'{spacing}``` {extension} title="{filename}"'] +
    list(map(
      lambda x: spacing + x,
      code.split('\n')[int(match.group('begin')) - 1:int(match.group('end'))],
    )) +
    [f'{spacing}```', f'{spacing}View at [GitHub]({match.group(0)})']
  )

def page_markdown(markdown, **kwargs):
  return re.sub(
    re.compile(
      r'^(?P<spacing>[ ]*)https://github.com/(?P<user>[\w/\-]+)/blob/(?P<commit>[0-9a-f]+)/(?P<filename>[\w\d\-/\.]+)\.(?P<extension>\w+)#L(?P<begin>\d+)-L(?P<end>\d+)$',
      re.MULTILINE,
    ),
    replacer,
    markdown,
  )

Example:
Screenshot 2024-01-18 at 13 37 28

!!! note "Phasellus posuere in sem ut cursus"

    Test
    https://github.com/aeternity/aepp-sdk-js/blob/f60d1b8a1124b32781769342e4941c8dacf6ad53/examples/browser/aepp/src/StoreAeSdkPlugin.js#L34-L36