diff --git a/CHANGELOG.md b/CHANGELOG.md index d58e80c3d..f06a35f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (#470) - Blender export: - Support for pcb2blender v2.6 (Blender 3.5.1) +- Populate: + - Basic support for regular list items (#480) ### Fixed - Rotated polygons and text used in the worksheet (#466) diff --git a/docs/populate.md b/docs/populate.md index 057dac6fd..9b60dd80d 100644 --- a/docs/populate.md +++ b/docs/populate.md @@ -63,6 +63,9 @@ list item is considered as a single step in populating and will generate an image. The content of the item is the step description. See [example](../tests/data/plain_html.md). +**Note**: list items without an explicit step will be processed as regular list items. +Avoid mixing regular list items and steps in the same list. + To specify which side of the board and which components to add and highlight start the item with a clause in form: ``` diff --git a/kibot/PcbDraw/mdrenderer.py b/kibot/PcbDraw/mdrenderer.py index a42bd381b..f3d09dfb2 100644 --- a/kibot/PcbDraw/mdrenderer.py +++ b/kibot/PcbDraw/mdrenderer.py @@ -56,15 +56,16 @@ def heading(self, text, level, raw=None): def paragraph(self, text): return text + '\n\n' - def list(self, text, ordered=True): - r = '' + def list(self, text, ordered=True, level=None, start=None): + r = '\n' + indent = ' ' * ((level-1) * 2) while text: text, type, t = MdRenderer.get_block(text) if type == 'l': - r += (ordered and ('# ' + t) or ('* ' + t)) + '\n' + r += indent + (ordered and ('# ' + t) or ('* ' + t)) + '\n' return r - def list_item(self, text): + def list_item(self, text, level=None): return 'l' + str(len(text)) + ':' + text def block_text(self, text): @@ -98,6 +99,9 @@ def autolink(self, link, is_email=False): return '<' + link + '>' def link(self, link, title, text, image=False): + if text is None: + text = title + title = None r = (image and '!' or '') + '[' + text + '](' + link + ')' if title: r += '"' + title + '"' diff --git a/kibot/PcbDraw/populate.py b/kibot/PcbDraw/populate.py index a32d4cbe4..77e29e18e 100644 --- a/kibot/PcbDraw/populate.py +++ b/kibot/PcbDraw/populate.py @@ -61,15 +61,17 @@ def output_pcbdraw(self, m: re.Match) -> Any: return self.renderer.pcbdraw(side, components) -def Renderer(BaseRenderer, initial_components: List[str]): # type: ignore +def Renderer(BaseRenderer, initial_components: List[str], format: str): # type: ignore class Tmp(BaseRenderer): # type: ignore - def __init__(self, initial_components: List[str]) -> None: + def __init__(self, initial_components: List[str], format: str) -> None: super(Tmp, self).__init__(escape=False) self.items: List[Dict[str, Any]]= [] self.current_item: Optional[Dict[str, Any]] = None self.active_side: str = "front" self.visited_components: List[str] = initial_components self.active_components: List[str] = [] + self.found_step = False + self.format = format def append_comment(self, html: str) -> None: if self.current_item is not None and self.current_item["type"] == "steps": @@ -103,6 +105,8 @@ def pcbdraw(self, side: str, components: List[str]) -> str: self.active_side = side self.visited_components += components self.active_components = components + # We found a step, this isn't a regular item + self.found_step = True return "" def block_code(self, children: str, info: Optional[str]=None) -> Any: @@ -120,15 +124,22 @@ def block_html(self, html: str) -> Any: self.append_comment(retval) return retval + def name_head(self, name: str, code: str): + if format != "html": + return code + # Add a name to this heading so it can be referenced + name = name.lower().replace(' ', '-') + return f'{code}' + def heading(self, children: str, level: int) -> Any: retval = super(Tmp, self).heading(children, level) - self.append_comment(retval) + self.append_comment(self.name_head(children, retval)) return retval # Mistune 0.8.4 API def header(self, text: str, level: int, raw: Optional[str]=None) -> Any: retval = super(Tmp, self).header(text, level, raw) - self.append_comment(retval) + self.append_comment(self.name_head(text, retval)) return retval # Mistune 0.8.4 API @@ -143,9 +154,19 @@ def thematic_break(self) -> Any: return retval def list(self, text: Any, ordered: bool, level: Any=None, start: Any=None) -> str: - return "" + if not text: + return "" + retval = super(Tmp, self).list(text, ordered, level, start) + if level == 1: + # Add the result from the list when finished and only if not empty + self.append_comment(retval) + return retval def list_item(self, text: str, level: Any=None) -> str: + if not self.found_step: + # If we don't have an image for this step assume this is a regular list + return super(Tmp, self).list_item(text, level) + # Add a step step = { "side": self.active_side, "components": self.visited_components, @@ -153,6 +174,8 @@ def list_item(self, text: str, level: Any=None) -> str: "comment": text } self.append_step(deepcopy(step)) + # Reset the flag + self.found_step = False return "" def paragraph(self, text: str) -> Any: @@ -164,7 +187,7 @@ def table(self, header: str, body: str) -> Any: retval = super(Tmp, self).table(header, body) self.append_comment(retval) return retval - return Tmp(initial_components) + return Tmp(initial_components, format) def load_content(filename: str) -> Tuple[Optional[Dict[str, Any]], str]: header = None @@ -263,9 +286,7 @@ def prepare_params(params: List[str]) -> List[str]: # Added for Kibot # The rendender selection, they are imported here def create_renderer(format, initial_components): - if format == "html": - return Renderer(HTMLRenderer, initial_components) # type: ignore - return Renderer(mdrenderer.MdRenderer, initial_components) # type: ignore + return Renderer(HTMLRenderer if format == "html" else mdrenderer.MdRenderer, initial_components, format) # type: ignore # The helper to look for a file, to avoid pulling LXML from pcbdraw diff --git a/tests/data/populate_with_toc.md b/tests/data/populate_with_toc.md new file mode 100644 index 000000000..d076ffe38 --- /dev/null +++ b/tests/data/populate_with_toc.md @@ -0,0 +1,15 @@ +# PCBA Manual + +- [PCBA Manual](#pcba-manual) + - [PCB Top assembly](#pcb-top-assembly) + - [Conclusion](#conclusion) + +## PCB Top assembly + +First step in the assembly is the populating of the TOP face. + +- [[front | ]] This is the front side of the board we are populating + +## Conclusion + +This is the end of the demo. diff --git a/tests/yaml_samples/populate_with_toc.kibot.yaml b/tests/yaml_samples/populate_with_toc.kibot.yaml new file mode 100644 index 000000000..faf893c1b --- /dev/null +++ b/tests/yaml_samples/populate_with_toc.kibot.yaml @@ -0,0 +1,27 @@ +kiplot: + version: 1 + +outputs: + - name: PcbDraw + comment: "How to draw a step" + type: pcbdraw + run_by_default: false + options: + format: png + + - name: Populate + comment: "Populate example" + type: populate + dir: PopulateSimple + options: + renderer: PcbDraw + input: tests/data/populate_with_toc.md + + - name: Populate MD + comment: "Populate example" + type: populate + dir: PopulateSimple + options: + renderer: PcbDraw + input: tests/data/populate_with_toc.md + format: md