Update Portals.py

This commit is contained in:
sarah committed 2026-09-21 23:07:20 +02:00
1 parent 0cd98873e0
commit 9bd57505bb
1 file changed
+40 -13
+40 -13
View File
@@ -23,6 +23,9 @@ MarkerPattern = re.compile(
LoopMarkerPattern = re.compile(
r"\{(?P<LoopSource>children|siblings|parents)\s+%\s+(?P<LoopVar>[A-Za-z_][A-Za-z0-9_]*)\}"
r"|\{(?P<CloseSource>children|siblings|parents)\s+%\}"
r"|\{(?:(?P<LoopCrossPath>[^\s{}']+)\s+)?\*\*\*(?P<LoopCrossName>[^\s*{}]+)"
r"\s+%\s+(?P<LoopCrossVar>[A-Za-z_][A-Za-z0-9_]*)\}"
r"|\{\*\*\*(?P<CloseCrossName>[^\s*{}]+)\s+%\}"
)
@@ -147,7 +150,24 @@ def _ComputeLoopLists(
return {"children": Children, "siblings": Siblings, "parents": Parents}
def _ResolveLoops(Content: str, Lists: dict[str, list[str]]) -> str:
def _FindLoopClose(Matches: list[re.Match], StartIndex: int, IsFixed: bool, Key: str) -> re.Match | None:
GroupName = "CloseSource" if IsFixed else "CloseCrossName"
for Candidate in Matches[StartIndex:]:
if Candidate.group(GroupName) == Key:
return Candidate
return None
def _ResolveLoops(
Content: str,
Lists: dict[str, list[str]],
RootName: str,
RefererDirectory: str,
Username: str,
UserGroups: list[str],
) -> str:
Matches = list(LoopMarkerPattern.finditer(Content))
Output: list[str] = []
Cursor = 0
@@ -155,23 +175,28 @@ def _ResolveLoops(Content: str, Lists: dict[str, list[str]]) -> str:
while Index < len(Matches):
Match = Matches[Index]
IsFixed = bool(Match.group("LoopSource"))
IsCross = bool(Match.group("LoopCrossName"))
if not Match.group("LoopSource"):
if not IsFixed and not IsCross:
Index += 1
continue
Source = Match.group("LoopSource")
if IsFixed:
Key = Match.group("LoopSource")
LoopVar = Match.group("LoopVar")
Items = Lists.get(Key, [])
else:
Key = Match.group("LoopCrossName")
LoopVar = Match.group("LoopCrossVar")
PortalContent = _ResolveCrossFileReference(
RootName, RefererDirectory, Match.group("LoopCrossPath"), Key, Username, UserGroups
)
Items = PortalContent.splitlines() if PortalContent is not None else []
CloseMatch = None
for Candidate in Matches[Index + 1 :]:
if Candidate.group("CloseSource") == Source:
CloseMatch = Candidate
break
CloseMatch = _FindLoopClose(Matches, Index + 1, IsFixed, Key)
BodyEnd = CloseMatch.start() if CloseMatch is not None else len(Content)
BodyTemplate = Content[Match.end() : BodyEnd]
Items = Lists.get(Source, [])
VariablePattern = re.compile(rf"%{re.escape(LoopVar)}\b")
Rendered = "\n".join(VariablePattern.sub(Item, BodyTemplate) for Item in Items)
@@ -319,10 +344,12 @@ def _ResolveLineNumberReference(
def ResolvePortals(
RootName: str, RelativePath: str, Content: str, Username: str, UserGroups: list[str]
) -> str:
LoopLists = _ComputeLoopLists(RootName, RelativePath, Username, UserGroups)
WithLoopsResolved = _ResolveLoops(Content, LoopLists)
LocallyResolved = _ResolveLocalPortals(WithLoopsResolved)
RefererDirectory = RelativePath.rsplit("/", 1)[0] if "/" in RelativePath else ""
LoopLists = _ComputeLoopLists(RootName, RelativePath, Username, UserGroups)
WithLoopsResolved = _ResolveLoops(
Content, LoopLists, RootName, RefererDirectory, Username, UserGroups
)
LocallyResolved = _ResolveLocalPortals(WithLoopsResolved)
Matches = list(MarkerPattern.finditer(LocallyResolved))
Output: list[str] = []