home · contact · privacy
Overhaul .dat parsing to simplify code, preserve more whitespace, prepend gap lines...
authorChristian Heller <c.heller@plomlompom.de>
Thu, 29 Jan 2026 01:18:15 +0000 (02:18 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 29 Jan 2026 01:18:15 +0000 (02:18 +0100)
20 files changed:
src/ledgplom/ledger.py
src/templates/edit_structured.html
src/templates/edit_structured.js
src/templates/ledger_structured.html
src/tests/empty.ledger_raw
src/tests/empty.ledger_structured
src/tests/full.balance
src/tests/full.balance.3 [new file with mode: 0644]
src/tests/full.balance.4 [deleted file]
src/tests/full.edit_raw.0 [new file with mode: 0644]
src/tests/full.edit_raw.1 [deleted file]
src/tests/full.edit_raw.3 [new file with mode: 0644]
src/tests/full.edit_raw.4 [deleted file]
src/tests/full.edit_structured.0 [new file with mode: 0644]
src/tests/full.edit_structured.1 [deleted file]
src/tests/full.edit_structured.3 [new file with mode: 0644]
src/tests/full.edit_structured.4
src/tests/full.edit_structured.5 [deleted file]
src/tests/full.ledger_raw
src/tests/full.ledger_structured

index dce6140b44d56e5621817f037a32603de9c93a9d..ac6acffe43f2943844940383c37d6207339d4209 100644 (file)
@@ -1,15 +1,17 @@
 'Actual ledger classes.'
 # standard libs
-from abc import ABC, abstractmethod
+from abc import ABC
 from datetime import date as dt_date
 from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
 from pathlib import Path
 from typing import Any, Generic, Iterator, Optional, Self, TypeVar
 
 
-TypeDatLine = TypeVar('TypeDatLine', bound='_DatLine')
+_TypeDatLine = TypeVar('_TypeDatLine', bound='_DatLine')
 
 
+_INDENT_CHARS = {' ', '\t'}
+_SEP_COMMENTS = ';'
 _PREFIX_DEF = '#def '
 DEFAULT_INDENT = 2 * ' '
 
@@ -117,41 +119,49 @@ class _Account:
 
 class _DatLine:
     'Line of .dat file parsed into comments and machine-readable data.'
-    to_copy = ['code', 'comment']
 
-    def __init__(
-            self,
-            code: str = '',
-            comment: str = '',
-            ) -> None:
-        self._code_read = code
-        self.comment = comment
+    def __init__(self, text: str) -> None:
+        self._raw = text
+
+    def _into_parts(self) -> tuple[str, str, str]:
+        stage_count = 0
+        indent = ''
+        code = ''
+        comment = ''
+        for c in self._raw:
+            if stage_count == 0:
+                if c in _INDENT_CHARS:
+                    indent += c
+                else:
+                    stage_count += 1
+            if stage_count == 1:
+                if c != _SEP_COMMENTS:
+                    code += c
+                else:
+                    stage_count += 1
+            if stage_count == 2:
+                comment += c
+        return indent, code, comment
+
+    @property
+    def indent(self) -> str:
+        'All (maybe zero) the chars of whitespace line starts with.'
+        return self._into_parts()[0]
 
     @property
     def code(self) -> str:
-        'Return collected code (re-generate by subclasses for writing).'
-        return self._code_read
+        'Either IntroLine or TransferLine instructions.'
+        return self._into_parts()[1]
+
+    @property
+    def comment(self) -> str:
+        'Anything past ";", with whitespace in-between stripped.'
+        return self._into_parts()[2][1:].lstrip()
 
     @property
     def raw(self) -> str:
         "Return as how to be written in .dat file's text content."
-        comment_part = ' ; '.join([''] + [s for s in [self.comment] if s])
-        code_part = f'{self.code} ' if self.code else ''
-        return f'{code_part}{comment_part.lstrip()}'.rstrip()
-
-    def copy(self) -> Self:
-        'Create new instance copying the fields named in .to_copy.'
-        kwargs = {fieldname: getattr(self, fieldname)
-                  for fieldname in self.to_copy}
-        return self.__class__(**kwargs)
-
-    @classmethod
-    def from_raw(cls, line: str) -> Self:
-        'Parse line into new _DatLine.'
-        halves = [t.rstrip() for t in line.split(';', maxsplit=1)]
-        comment = halves[1].lstrip() if len(halves) > 1 else ''
-        code = halves[0]
-        return cls(code, comment)
+        return self._raw[:]
 
     @property
     def comment_instructions(self) -> dict[str, str]:
@@ -159,7 +169,7 @@ class _DatLine:
         instructions = {}
         if self.comment.startswith(_PREFIX_DEF):
             parts = [part.strip() for part
-                     in self.comment[len(_PREFIX_DEF):].split(';')]
+                     in self.comment[len(_PREFIX_DEF):].split(_SEP_COMMENTS)]
             first_part_parts = parts[0].split(maxsplit=1)
             account_name = first_part_parts[0]
             desc = first_part_parts[1] if len(first_part_parts) > 1 else ''
@@ -167,147 +177,100 @@ class _DatLine:
         return instructions
 
 
-class _DatLineSubclass(_DatLine, ABC):
-
-    @classmethod
-    @abstractmethod
-    def from_dat(cls, dat_line: '_DatLine') -> Self:
-        'Evolve from mere dat_line into subclass.'
-
-
-class _GapLine(_DatLineSubclass):
-
-    @classmethod
-    def from_dat(cls, dat_line: _DatLine) -> Self:
-        return cls('', dat_line.raw if dat_line.code else dat_line.comment)
-
-
-class _BookingLine(_DatLineSubclass):
+class _BookingLine(_DatLine, ABC):
     'Parsed _DatLine belonging to a _Booking.'
-    dictables = {'comment', 'errors'}
-
-    def __init__(self, comment, errors: Optional[list[str]]) -> None:
-        super().__init__('', comment)
-        self._errors: list[str] = errors if errors else []
+    _field_names = {'errors', 'comment'}
 
     @property
     def as_dict(self) -> dict[str, Any]:
-        'Return as JSON-ready dict attributes listed in .dictables.'
+        'Return as JSON-ready dict attributes listed in ._field_names.'
         def to_dictable(value):
             if isinstance(value, (str, int)):
                 return value
             if hasattr(value, 'as_dict'):
                 return value.as_dict
-            if isinstance(value, list):
-                return [to_dictable(v) for v in value]
+            if isinstance(value, tuple):
+                return tuple(to_dictable(v) for v in value)
             return str(value)
         d = {}
-        for name in self.dictables:
+        for name in self._field_names | _BookingLine._field_names:
             d[name] = to_dictable(getattr(self, name))
         return d
 
+    def _code_into_parts(self, n_parts: int) -> tuple[str, ...]:
+        maxsplit = n_parts + 1
+        parts = self.code.split(maxsplit=maxsplit)
+        return tuple((parts[idx] if len(parts) > idx else '')
+                     for idx in range(maxsplit))
+
     @property
-    def errors(self) -> list[str]:
-        'Return collected errors (subclasses may add dynamic ones).'
-        return self._errors[:]
+    def errors(self) -> tuple[str, ...]:
+        'Whatever is wrong with the respective line.'
+        return tuple(f'{name} empty' for name in self._field_names
+                     if not getattr(self, name))
 
 
 class _IntroLine(_BookingLine):
     'First line of a _Booking, expected to carry date etc.'
-    to_copy = ['date', 'target', 'comment']
-    dictables = {'date', 'target'} | _BookingLine.dictables
+    _field_names = {'date', 'target'}
 
-    def __init__(
-            self,
-            date: str,
-            target: str,
-            comment: str = '',
-            errors: Optional[list[str]] = None,
-            ) -> None:
-        super().__init__(comment, errors)
-        self.target = target
-        self.date = date
+    @property
+    def date(self) -> str:
+        'YYYY-MM-DD of Booking.'
+        return self._code_into_parts(2)[0]
+
+    @property
+    def target(self) -> str:
+        'Whatever the ledger definition actually means by that …'
+        return self._code_into_parts(2)[1]
 
     @property
-    def errors(self) -> list[str]:
-        errors = super().errors
+    def errors(self) -> tuple[str, ...]:
+        errors = list(super().errors)
+        if self.indent:
+            errors += ['intro line indented']
         try:
             dt_date.fromisoformat(self.date)
         except ValueError:
             errors += [f'not properly formatted legal date: {self.date}']
-        if not self.target:
-            errors += ['target empty']
-        return errors
-
-    @classmethod
-    def from_dat(cls, dat_line: _DatLine) -> Self:
-        errors = []
-        if dat_line.code[0].isspace():
-            errors += ['(intro line indented)']
-        toks = dat_line.code.lstrip().split(maxsplit=1)
-        return cls(toks[0], toks[1] if len(toks) > 1 else '',
-                   dat_line.comment, errors)
-
-    @property
-    def code(self) -> str:
-        return f'{self.date} {self.target}'
+        return tuple(errors)
 
 
 class _TransferLine(_BookingLine):
     'Non-first _Booking line, expected to carry value movement.'
-    to_copy = ['account', 'amount', 'currency', 'comment']
-    dictables = {'amount', 'account', 'currency'} | _BookingLine.dictables
+    _field_names = {'account', 'amount', 'currency'}
 
-    def __init__(
-            self,
-            account: str,
-            amount: str,
-            currency: str,
-            comment: str = '',
-            errors: Optional[list[str]] = None
-            ) -> None:
-        super().__init__(comment, errors)
-        self.account = account
-        self._amount_str = amount
-        self.currency = currency
+    @property
+    def account(self) -> str:
+        'Name of Account.'
+        return self._code_into_parts(3)[0]
 
     @property
     def amount(self) -> Optional[Decimal] | str:
         'Decimal if amount known, None if not, str if un-decimable.'
-        if not self._amount_str:
+        amount_str = self._code_into_parts(3)[1]
+        if not amount_str:
             return None
         try:
-            return Decimal(self._amount_str)
+            return Decimal(amount_str)
         except DecimalInvalidOperation:
-            return self._amount_str
+            return amount_str
+
+    @property
+    def currency(self) -> str:
+        'If .amount but itself not found, will default to "€".'
+        return (self._code_into_parts(3)[2] or '€') if self.amount else ''
 
     @property
-    def errors(self) -> list[str]:
-        errors = super().errors
+    def errors(self) -> tuple[str, ...]:
+        errors = list(super().errors)
+        # if not self.indent:
+        #     errors += ['transfer line not indented']
         if isinstance(self.amount, str):
             errors += [f'improper amount value: {self.amount}']
         if len(self.currency.split()) > 1:
             errors += ['improper number of tokens']
-        return errors
-
-    @classmethod
-    def from_dat(cls, dat_line: _DatLine) -> Self:
-        errors = []
-        currency: str = ''
-        if not dat_line.code[0].isspace():
-            errors += ['(transfer line not indented)']
-        toks = dat_line.code.lstrip().split(maxsplit=2)
-        amount_str = toks[1] if len(toks) > 1 else ''
-        if len(toks) > 1:
-            currency = toks[2] if 3 == len(toks) else '€'
-        return cls(toks[0], amount_str, currency, dat_line.comment, errors)
-
-    @property
-    def code(self) -> str:
-        code = f'{DEFAULT_INDENT}{self.account}'
-        if self.amount is not None:
-            code += f'  {self.amount} {self.currency}'
-        return code
+        return tuple(errors)
 
     @property
     def amount_short(self) -> str:
@@ -321,76 +284,70 @@ class _TransferLine(_BookingLine):
         return ''
 
 
-class _LinesBlock(Generic[TypeDatLine]):
+class _LinesBlock(Generic[_TypeDatLine]):
+    _lines: list[_TypeDatLine]
 
-    def __init__(self, lines: Optional[list[TypeDatLine]] = None) -> None:
-        self._lines = lines if lines else []
+    def __init__(self) -> None:
+        self._lines = []
 
     @property
-    def lines(self) -> list[TypeDatLine]:
+    def lines(self) -> tuple[_TypeDatLine, ...]:
         'Return collected lines.'
-        return self._lines
-
-    def copy(self) -> Self:
-        "Re-create via .lines' copy()."
-        return self.__class__([line.copy() for line in self.lines])
+        return tuple(self._lines)
 
+    def add(self, lines: tuple[_TypeDatLine, ...], at_end=True) -> None:
+        'Grow block downwards by this one DatLine.'
+        if at_end:
+            self._lines += lines
+        else:
+            self._lines[0:0] = list(lines)
 
-class _Gap(_LinesBlock[_GapLine]):
 
-    def add(self, lines: list[_GapLine]) -> None:
-        'Grow self by lines.'
-        self._lines += lines
+class _Booking(_LinesBlock[_BookingLine]):
 
     @property
-    def redundant_empty_lines(self):
-        'If self has more empty lines than necessary.'
-        redundancies = []
-        prev_line = None
-        idx_last_non_empty = -1
-        for idx, line in enumerate(self._lines):
-            if line.comment:
-                idx_last_non_empty = idx
-            elif '' == prev_line and not line.comment:
-                redundancies += [line]
-            prev_line = line
-        redundancies += [line for line in self._lines[idx_last_non_empty + 2:]
-                         if line not in redundancies]
-        return redundancies
+    def _sink_account(self) -> str:
+        for tf_line in [tl for tl in self.transfer_lines
+                        if tl.amount is None and not tl.errors]:
+            return tf_line.account
+        return ''
 
-    def remove_redundant_empty_lines(self):
-        'From self remove redundant empty lines.'
-        for line in self.redundant_empty_lines:
-            self._lines.remove(line)
+    @property
+    def lines(self) -> tuple[_BookingLine, ...]:
+        'Return collected lines.'
+        return (self.intro_line, ) + self.transfer_lines
 
+    @property
+    def _diffs_targeted(self) -> dict[str, _Wealth]:
+        balancing_diff = _Wealth()
+        diffs_targeted: dict[str, _Wealth] = {'': _Wealth()}
+        for tf_line in [tl for tl in self.transfer_lines if not tl.errors]:
+            if tf_line.account not in diffs_targeted:
+                diffs_targeted[tf_line.account] = _Wealth()
+            if isinstance(tf_line.amount, Decimal):
+                diff = _Wealth({tf_line.currency: tf_line.amount})
+                diffs_targeted[tf_line.account] += diff
+                balancing_diff += diff
+        diffs_targeted[self._sink_account] += balancing_diff.as_sink
+        return diffs_targeted
 
-class _Booking(_LinesBlock[_BookingLine]):
+    @property
+    def diffs_targeted(self) -> dict[str, _Wealth]:
+        'All wealth differences explicitly defined in transfer lines.'
+        return {acc: diff for acc, diff in self._diffs_targeted.items() if acc}
 
-    def __init__(self, lines: list[_BookingLine]) -> None:
-        super().__init__(lines)
-        diffs = _Wealth()
-        sink_account = None
-        self.sink_error = ''
-        self.diffs_targeted: dict[str, _Wealth] = {}
-        for tf_line in [tl for tl in self.transfer_lines if not tl.errors]:
-            if tf_line.account not in self.diffs_targeted:
-                self.diffs_targeted[tf_line.account] = _Wealth()
-            if tf_line.amount is None:
-                if sink_account:
-                    self.sink_error = 'too many sinks'
-                else:
-                    sink_account = tf_line.account
-                continue
-            assert isinstance(tf_line.amount, Decimal)
-            diff = _Wealth({tf_line.currency: tf_line.amount})
-            self.diffs_targeted[tf_line.account] += diff
-            diffs += diff
-        if sink_account:
-            self.diffs_targeted[sink_account] += diffs.as_sink
-        elif diffs.as_sink.moneys:
-            self.sink_error = 'sink missing for: '\
-                    + ', '.join(f'{amt} {cur}'
-                                for cur, amt in diffs.as_sink.moneys.items())
+    @property
+    def sink_error(self) -> str:
+        'Message on error, if any, regarding sink calculation/placement.'
+        for _ in [tl for tl in self.transfer_lines
+                  if tl.account != self._sink_account
+                  and tl.amount is None
+                  and not tl.errors]:
+            return 'too many sinks'
+        unsunk_moneys = self._diffs_targeted[''].moneys.items()
+        return ('' if not unsunk_moneys else
+                ('sink missing for: '
+                 + (', '.join(f'{amt} {cur}' for cur, amt in unsunk_moneys))))
 
     @property
     def diffs_inheriting(self) -> dict[str, _Wealth]:
@@ -406,17 +363,13 @@ class _Booking(_LinesBlock[_BookingLine]):
     @property
     def intro_line(self) -> _IntroLine:
         'Return collected _IntroLine.'
-        assert isinstance(self._lines[0], _IntroLine)
-        return self._lines[0]
-
-    @property
-    def transfer_lines(self) -> list[_TransferLine]:
-        'Return collected _TransferLines.'      # NB: currently no easy way to
-        return self._lines[1:]  # type: ignore  # assert mypy list be of type
+        return _IntroLine(self._lines[0].raw)
 
     @property
-    def lines(self) -> list[_BookingLine]:
-        return [self.intro_line] + list(self.transfer_lines)
+    def transfer_lines(self) -> tuple[_TransferLine, ...]:
+        'Any lines past the first with .code.'
+        return tuple(_TransferLine(line.raw) for line in self._lines[1:]
+                     if line.code)
 
     @property
     def date(self) -> str:
@@ -428,25 +381,65 @@ class _Booking(_LinesBlock[_BookingLine]):
         'Main other party for transaction.'
         return self.intro_line.target
 
-    def copy_to_current_date(self) -> Self:
-        'Make copy of same lines but now as date.'
-        copy = self.copy()
-        copy.intro_line.date = dt_date.today().isoformat()
-        return copy
 
+class _DatBlock(_LinesBlock[_DatLine]):
+    'Unit of lines with optional .booking, and (possibly zero) .gap_lines.'
+    _prev: Optional[Self] = None
+    _next: Optional[Self] = None
 
-class _DatBlock:
-    'Unit of lines with optional .booking, and possibly empty .gap.'
+    @classmethod
+    def from_lines(cls, lines: tuple[str, ...]) -> tuple['_DatBlock', ...]:
+        'Sequence of DatBlocks parsed from lines.'
+        i_block: _DatBlock = cls()
+        blocks = []
+        for dat_line in (_DatLine(line) for line in lines):
+            if (not dat_line.indent) and i_block.indented:
+                blocks += [i_block]
+                i_block.next = _DatBlock()
+                i_block = i_block.next
+            i_block.add((dat_line, ))
+        return tuple(blocks)
 
-    def __init__(
-            self,
-            booking: Optional['_Booking'],
-            gap: Optional['_Gap'] = None
-            ) -> None:
-        self.booking = booking
-        self.gap = gap if gap else _Gap()
-        self._prev: Optional[Self] = None
-        self._next: Optional[Self] = None
+    @property
+    def indented(self) -> bool:
+        'Does the block contain any indented lines?'
+        return bool([line for line in self.lines if line.indent])
+
+    @property
+    def gap_lines(self) -> tuple[_DatLine, ...]:
+        'Sequence of all included DatLines without code and indent.'
+        return tuple(line for line in self.lines
+                     if not line.indent + line.code)
+
+    @property
+    def redundant_empty_lines(self) -> tuple[_DatLine, ...]:
+        'Empty lines in sequence (separated between .gap_lines and .booking).'
+        redundancies: list[_DatLine] = []
+        for lines in (self.gap_lines,
+                      self.booking.lines if self.booking else tuple()):
+            prev_line: Optional[_DatLine] = None
+            for line in lines:
+                if prev_line and not (line.raw.strip()
+                                      or prev_line.raw.strip()):
+                    redundancies += [line]
+                prev_line = line
+        return tuple(redundancies)
+
+    def remove_redundant_empty_lines(self):
+        'From self remove .redundant_empty_lines.'
+        for line in self.redundant_empty_lines:
+            self._lines.remove(line)
+
+    @property
+    def booking(self) -> Optional[_Booking]:
+        'Booking made from lines indented or with code.'
+        booking_lines = tuple(_BookingLine(line.raw) for line in self.lines
+                              if line.indent or line.code)
+        if not booking_lines:
+            return None
+        booking = _Booking()
+        booking.add(booking_lines)
+        return booking
 
     @property
     def id_(self) -> int:
@@ -465,14 +458,6 @@ class _DatBlock:
             return 'date < previous date'
         return ''
 
-    @property
-    def lines(self) -> list[_BookingLine | _GapLine]:
-        'Return .lines of .booking and .gap as list[_DatLine].'
-        lines = (self.booking.lines if self.booking else []) + self.gap.lines
-        if self.booking and not self.gap.lines:
-            lines += [_GapLine()]
-        return lines
-
     def _set_neighbor(
             self,
             new_this: Optional[Self],
@@ -488,21 +473,21 @@ class _DatBlock:
         setattr(self, f'_{this}', new_this)
 
     @property
-    def next(self) -> Optional['_DatBlock']:
+    def next(self) -> Optional[Self]:
         'Successor in chain.'
         return self._next
 
     @next.setter
-    def next(self, new_next: Optional['_DatBlock']) -> None:
+    def next(self, new_next: Optional[Self]) -> None:
         self._set_neighbor(new_next, 'next', 'prev')
 
     @property
-    def prev(self) -> Optional['_DatBlock']:
+    def prev(self) -> Optional[Self]:
         'Predecessor in chain.'
         return self._prev
 
     @prev.setter
-    def prev(self, new_prev: Optional['_DatBlock']):
+    def prev(self, new_prev: Optional[Self]):
         self._set_neighbor(new_prev, 'prev', 'next')
 
     @property
@@ -535,13 +520,6 @@ class _DatBlock:
             self.prev = old_next
             old_next.prev = old_prev
 
-    def drop(self) -> None:
-        'Remove from chain.'
-        if self.prev:
-            self.prev.next = self.next
-        elif self.next:
-            self.next.prev = self.prev
-
     def fix_position(self):
         'Move around in chain until properly positioned by .date.'
         while self.prev and self.prev.date > self.date:
@@ -549,19 +527,18 @@ class _DatBlock:
         while self.next and self.next.date < self.date:
             self.move(up=False)
 
-    def replace_with(self, new_block: Self) -> None:
-        'Have new_block take own position.'
-        if self.prev:
-            self.prev.next = new_block
-        if self.next:
-            self.next.prev = new_block
-        new_block.fix_position()
-
-    def copy_to_current_date(self) -> '_DatBlock':
-        'Make copy of same lines but now as date, position accordingly.'
-        copy = _DatBlock(
-                self.booking.copy_to_current_date() if self.booking else None,
-                self.gap.copy())
+    def copy_to_current_date(self) -> Self:
+        'Make copy of same lines but date of now, position accordingly.'
+        copy = self.__class__()
+        copy.add(tuple(_DatLine(line.raw) for line in self.gap_lines))
+        if self.booking:
+            copy.add((_DatLine(' '.join((dt_date.today().isoformat(),
+                                         self.booking.intro_line.target,
+                                         self.booking.intro_line.comment))),
+                      ),
+                     at_end=False)
+            copy.add(tuple(_DatLine(line.raw)
+                           for line in self.booking.transfer_lines))
         if self.next:
             self.next.prev = copy
         self.next = copy
@@ -579,26 +556,9 @@ class Ledger:
 
     def load(self) -> None:
         'Re-)read ledger from file at ._path_dat.'
-        dat_lines: list[_DatLine] = [
-            _DatLine.from_raw(line)
-            for line in self._path_dat.read_text(encoding='utf8').splitlines()]
-        if (not dat_lines) or dat_lines[-1].code:  # ensure final gap line so
-            dat_lines += [_DatLine()]              # last booking gets finished
-        booking_lines: list[_BookingLine] = []
-        i_block = _DatBlock(None, _Gap())
-        self._blocks_start = i_block
-        for dat_line in dat_lines:
-            if bool(dat_line.code):
-                if not booking_lines:
-                    booking_lines += [_IntroLine.from_dat(dat_line)]
-                else:
-                    booking_lines += [_TransferLine.from_dat(dat_line)]
-            else:  # enter new gap -> ready to start next block
-                if booking_lines:
-                    i_block.next = _DatBlock(_Booking(booking_lines))
-                    i_block = i_block.next
-                    booking_lines = []
-                i_block.gap.add([_GapLine.from_dat(dat_line)])
+        blocks = _DatBlock.from_lines(
+                tuple(self._path_dat.read_text(encoding='utf8').splitlines()))
+        self._blocks_start = blocks[0] if blocks else _DatBlock()
         self.last_save_hash = self._hash_dat_lines()
 
     @property
@@ -612,12 +572,12 @@ class Ledger:
         return blocks
 
     @property
-    def _dat_lines(self) -> list[_DatLine]:
+    def _dat_lines(self) -> tuple[_DatLine, ...]:
         'From .blocks build list of current _DatLines.'
         lines = []
         for block in self.blocks:
-            lines += block.lines
-        return [_DatLine(line.code, line.comment) for line in lines]
+            lines += list(block.lines)
+        return tuple(lines)
 
     def _calc_accounts(self) -> dict[str, _Account]:
         'Build mapping of account names to _Accounts.'
@@ -666,14 +626,13 @@ class Ledger:
 
     @property
     def _has_redundant_empty_lines(self) -> bool:
-        'If any gaps have redunant empty lines.'
-        return bool([b for b in self.blocks if b.gap.redundant_empty_lines])
+        'If any blocks have redunant empty lines.'
+        return bool([b for b in self.blocks if b.redundant_empty_lines])
 
     def remove_redundant_empty_lines(self) -> None:
         'From all .blocks remove redundant empty lines.'
-        for gap in [b.gap for b in self.blocks
-                    if b.gap.redundant_empty_lines]:
-            gap.remove_redundant_empty_lines()
+        for block in self.blocks:
+            block.remove_redundant_empty_lines()
 
     @property
     def tainted(self) -> bool:
@@ -688,46 +647,28 @@ class Ledger:
 
     def rewrite_block(self, old_id: int, new_lines: list[str]) -> int:
         'Rewrite with new_lines, move if changed date.'
-        lines_gap_pre_booking: list[_GapLine] = []
-        lines_booking: list[_BookingLine] = []
-        lines_gap_post_booking: list[_GapLine] = []
-        for dat_line in [_DatLine.from_raw(line) for line in new_lines]:
-            if dat_line.code:
-                if lines_gap_post_booking:  # .code belongs to _next_ Booking
-                    lines_gap_post_booking += [_GapLine.from_dat(dat_line)]
-                elif not lines_booking:
-                    lines_booking += [_IntroLine.from_dat(dat_line)]
-                else:
-                    lines_booking += [_TransferLine.from_dat(dat_line)]
-            else:
-                if not lines_booking:
-                    lines_gap_pre_booking += [_GapLine.from_dat(dat_line)]
-                else:
-                    lines_gap_post_booking += [_GapLine.from_dat(dat_line)]
         old_block = self.blocks[old_id]
-        if not lines_booking:
-            if old_block.prev:
-                old_block.prev.gap.add(lines_gap_pre_booking)
-                old_block.drop()
-            else:
-                old_block.booking = None
-                old_block.gap.add(lines_gap_pre_booking)
-            return max(0, old_id - 1)
-        new_block = _DatBlock(_Booking(lines_booking),
-                              _Gap(lines_gap_post_booking))
-        self.blocks[old_id].replace_with(new_block)
-        if not new_block.prev:
-            self._blocks_start = _DatBlock(None, _Gap())
-            self._blocks_start.next = new_block
-            assert new_block.prev is not None
-        if lines_gap_pre_booking:
-            new_block.prev.gap.add(lines_gap_pre_booking)
-        return new_block.id_
+        old_prev, old_next = old_block.prev, old_block.next
+        new_blocks = _DatBlock.from_lines(tuple(new_lines))
+        if old_next:
+            if not new_blocks[0].booking:
+                assert len(new_blocks) == 1
+                old_next.add(new_blocks[0].lines)
+                old_next.prev = old_prev
+                return old_next.id_
+            old_next.prev = new_blocks[-1]
+        if old_prev:
+            old_prev.next = new_blocks[0]
+        else:
+            self._blocks_start = new_blocks[0]
+        for block in new_blocks:
+            block.fix_position()
+        return new_blocks[0].id_
 
     def add_empty_block(self) -> int:
         'Add new _DatBlock of empty _Booking to end of ledger.'
-        new_block = _DatBlock(
-                _Booking([_IntroLine(dt_date.today().isoformat(), '?')]))
+        new_block = _DatBlock()
+        new_block.add((_DatLine(f'{dt_date.today().isoformat()} ?'), ))
         self.blocks[-1].next = new_block
         new_block.fix_position()
         return new_block.id_
@@ -751,12 +692,10 @@ class Ledger:
         'All context data relevant for rendering an edit view.'
         block = self.blocks[id_]
         if lines:
-            return {'raw_gap_lines': [dl.raw for dl in block.gap.lines],
-                    'booking_lines': (
-                        [block.booking.intro_line.as_dict]
-                        + [tf_line.as_dict
-                           for tf_line in block.booking.transfer_lines]
-                        ) if block.booking else []}
+            return {'raw_gap_lines': [dl.raw for dl in block.gap_lines],
+                    'booking_lines': ([line.as_dict
+                                       for line in block.booking.lines]
+                                      if block.booking else tuple())}
         accounts = self._calc_accounts()
         roots: list[dict[str, Any]] = []
         for full_path in sorted(block.booking.diffs_targeted.keys()
@@ -791,7 +730,7 @@ class Ledger:
                'valid': self._blocks_valid_up_incl(id_),
                'roots': roots}
         if not raw:
-            ctx['raw_gap_lines'] = [dl.raw for dl in block.gap.lines]
+            ctx['raw_gap_lines'] = [dl.raw for dl in block.gap_lines]
             ctx['all_accounts'] = sorted(accounts.keys())
         return ctx
 
index 675954a3d626d8bc08be5f4a794a243127a89274..f62b85bd617c1da890df3740a6b2f2c809d02858 100644 (file)
@@ -37,8 +37,6 @@ to
 <input id="replace_to" />
 </span>
 <hr />
-<table id="booking_lines" class="alternating">
-</table>
 <div>Gap:</div>
 <textarea id="gap_lines"
           name="raw_lines"
@@ -47,6 +45,8 @@ to
           class="tainter"
           >
 </textarea>
+<table id="booking_lines" class="alternating">
+</table>
 </form>
 <datalist id="all_accounts">
 {% for acc in all_accounts %}
index e83816adf39a768c2db6852c39ad20821fe36b95..00f0932ff42a9ece315c2e13cfec4009943bb096 100644 (file)
@@ -95,10 +95,10 @@ const updateForm = () => {
         table = document.getElementById("booking_lines"),
         textarea = document.getElementById("gap_lines");
 
-    // empty and redo gapLines, empty bookingLines table
-    textarea.value = "";
+    // empty and redo gapLines textarea, empty bookingLines table
+    textarea.innerHTML = ""
     rawGapLines.forEach((line) => {
-        textarea.value += `${line}\n`;
+        textarea.innerHTML += `${line}\n`;
     });
     table.innerHTML = "";
 
index 6c06acdec5b003662d9436360a976ba0f01ed783..26318f0afa9414ce6911b263e040ddca9dcbe969 100644 (file)
 <tbody>
 {% for block in blocks %}
 {{ macros.ledger_block_columns('structured', block) -}}
+{##}{% for line in block.gap_lines %}
+    <tr>
+        <td colspan=4>{{ line.raw }}&nbsp;</td>
+    </tr>
+{##}{% endfor %}
 {##}{% if block.booking %}
     <tr>
         <td colspan=3{{ ' class="critical"'
     </tr>
 {####}{% endfor %}
 {##}{% endif %}
-{##}{% for line in block.gap.lines %}
-    <tr>
-        <td colspan=4>{{ line.raw }}&nbsp;</td>
-    </tr>
-{##}{% endfor %}
 {% endfor %}
 </tbody>
 </table>
index def169cce0b9c6ab6e54006774918d5faec9bb88..a479a03c0ad0ee6f6cf330c842656088531b9224 100644 (file)
@@ -55,20 +55,19 @@ table {
 <tbody>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_0">
-        <td rowspan="2" class="block_column">
+        <td rowspan="1" class="block_column">
             <input type="submit" name="ledger_moveup_0" value="^" disabled="">
             <br>
             <input type="submit" name="ledger_movedown_0" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_0" value="C">
         </td>
-        <td rowspan="2" class="block_column">
+        <td rowspan="1" class="block_column">
             [<a href="#block_0">#</a>]<br>
             [<a href="/balance/0">b</a>]<br>
             [<a href="/edit_raw/0">e</a>]
         </td>
     </tr>
-    <tr><td>&nbsp;</td></tr>
 </tbody>
 </table>
 </form>
index 34da94775fdf05507d994a30a7196cbda553cea8..86547816ff0d80403f5cb633de54bb0e5a61fd61 100644 (file)
@@ -60,22 +60,19 @@ td.currency {
 <tbody>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_0">
-        <td rowspan="2" class="block_column">
+        <td rowspan="1" class="block_column">
             <input type="submit" name="ledger_moveup_0" value="^" disabled="">
             <br>
             <input type="submit" name="ledger_movedown_0" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_0" value="C">
         </td>
-        <td rowspan="2" class="block_column">
+        <td rowspan="1" class="block_column">
             [<a href="#block_0">#</a>]<br>
             [<a href="/balance/0">b</a>]<br>
             [<a href="/edit_structured/0">e</a>]
         </td>
     </tr>
-    <tr>
-        <td colspan="4">&nbsp;</td>
-    </tr>
 </tbody>
 </table>
 <input type="submit" name="add_booking" value="add booking">
index f68cfd41cb190b61285646355a5dd3936322b886..d5684a12dad968bb20a9ed4164ab3db3c90078fd 100644 (file)
@@ -78,10 +78,10 @@ span.indent {
     </form>
 </div>
 <p>
-    <a href="/balance/4">prev</a>
+    <a href="/balance/3">prev</a>
     <del>next</del>
     |
-    balance after <a href="/blocks/5">booking 5 (2001-01-03: test)</a>
+    balance after <a href="/blocks/4">booking 4 (2001-01-03: test)</a>
 </p>
 <table class="alternating critical">
 <tbody>
diff --git a/src/tests/full.balance.3 b/src/tests/full.balance.3
new file mode 100644 (file)
index 0000000..37e623d
--- /dev/null
@@ -0,0 +1,239 @@
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<style>
+html {
+    scroll-padding-top: 2em;
+}
+body {
+    background: #ffffff;
+    font-family: sans-serif;
+    text-align: left;
+    margin: 0;
+    padding: 0;
+}
+#header {
+    background: #ffffff;
+    position: sticky;
+    top: 0;
+    padding-left: 0.5em;
+    padding-bottom: 0.25em;
+    border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+    background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+    background: #ffffff;
+}
+td {
+    vertical-align: top;
+}
+.critical {
+    background: #ff6666 !important;
+}
+td.amount {
+    text-align: right;
+}
+td.amount,
+td.currency {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+    background-color: #ff8a8a;
+}
+td.balance.amount {
+    width: 10em;
+}
+td.balance.currency {
+    width: 3em;
+}
+td.money table {
+    float: left;
+}
+summary::marker {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+summary {
+    list-style-type: "[…]";
+}
+details[open] > summary {
+    list-style-type: "[^]";
+}
+span.indent {
+    letter-spacing: 3em;
+}
+</style>
+</head>
+<body>
+<div id="header">
+    <form action="/balance/3" method="POST">
+        <span class="disable_on_taint">
+            ledger <a href="/ledger_structured">structured</a>
+            / <a href="/ledger_raw">raw</a>
+            · <a href="/balance">balance</a>
+            · <input type="submit" name="file_load" value="reload">
+        </span>
+    </form>
+</div>
+<p>
+    <a href="/balance/2">prev</a>
+    <a href="/balance/4">next</a>
+    |
+    balance after <a href="/blocks/3">booking 3 (2001-01-03: test)</a>
+</p>
+<table class="alternating ">
+<tbody>
+    <tr>
+        <td class="money">
+            <details>
+                <summary>
+                    <table>
+                    <tbody>
+                        <tr>
+                            <td class="balance amount">-10</td>
+                            <td class="balance currency">€</td>
+                        </tr>
+                    </tbody>
+                    </table>
+                </summary>
+                <table>
+                <tbody>
+                    <tr>
+                        <td class="balance amount">-1</td>
+                        <td class="balance currency">USD</td>
+                    </tr>
+                </tbody>
+                </table>
+            </details>
+        </td>
+        <td>
+            <span class="indent"></span>bar:
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="money">
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <span class="indent">&nbsp;</span>:x:
+        </td>
+        <td>bla bla bla</td>
+    </tr>
+    <tr>
+        <td class="money">
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <span class="indent">&nbsp;&nbsp;</span>:y
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="money">
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <span class="indent">&nbsp;</span>:z
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="money">
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <span class="indent"></span>baz
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="money">
+            <details>
+                <summary>
+                    <table>
+                    <tbody>
+                        <tr>
+                            <td class="balance amount">20</td>
+                            <td class="balance currency">€</td>
+                        </tr>
+                    </tbody>
+                    </table>
+                </summary>
+                <table>
+                <tbody>
+                    <tr>
+                        <td class="balance amount">1</td>
+                        <td class="balance currency">USD</td>
+                    </tr>
+                </tbody>
+                </table>
+            </details>
+        </td>
+        <td>
+            <span class="indent"></span>foo:
+        </td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="money">
+            <details>
+                <summary>
+                    <table>
+                    <tbody>
+                        <tr>
+                            <td class="balance amount">10</td>
+                            <td class="balance currency">€</td>
+                        </tr>
+                    </tbody>
+                    </table>
+                </summary>
+                <table>
+                <tbody>
+                    <tr>
+                        <td class="balance amount">1</td>
+                        <td class="balance currency">USD</td>
+                    </tr>
+                </tbody>
+                </table>
+            </details>
+        </td>
+        <td>
+            <span class="indent">&nbsp;</span>:x
+        </td>
+        <td></td>
+    </tr>
+</tbody>
+</table>
+
+</body></html>
diff --git a/src/tests/full.balance.4 b/src/tests/full.balance.4
deleted file mode 100644 (file)
index 6785650..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<style>
-html {
-    scroll-padding-top: 2em;
-}
-body {
-    background: #ffffff;
-    font-family: sans-serif;
-    text-align: left;
-    margin: 0;
-    padding: 0;
-}
-#header {
-    background: #ffffff;
-    position: sticky;
-    top: 0;
-    padding-left: 0.5em;
-    padding-bottom: 0.25em;
-    border-bottom: 1px solid black;
-}
-table.alternating > tbody > tr:nth-child(odd) {
-    background-color: #dcdcdc;
-}
-table.alternating > tbody > tr:nth-child(even) {
-    background: #ffffff;
-}
-td {
-    vertical-align: top;
-}
-.critical {
-    background: #ff6666 !important;
-}
-td.amount {
-    text-align: right;
-}
-td.amount,
-td.currency {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-table.alternating.critical > tbody > tr:nth-child(even) {
-    background-color: #ff8a8a;
-}
-td.balance.amount {
-    width: 10em;
-}
-td.balance.currency {
-    width: 3em;
-}
-td.money table {
-    float: left;
-}
-summary::marker {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-summary {
-    list-style-type: "[…]";
-}
-details[open] > summary {
-    list-style-type: "[^]";
-}
-span.indent {
-    letter-spacing: 3em;
-}
-</style>
-</head>
-<body>
-<div id="header">
-    <form action="/balance/4" method="POST">
-        <span class="disable_on_taint">
-            ledger <a href="/ledger_structured">structured</a>
-            / <a href="/ledger_raw">raw</a>
-            · <a href="/balance">balance</a>
-            · <input type="submit" name="file_load" value="reload">
-        </span>
-    </form>
-</div>
-<p>
-    <a href="/balance/3">prev</a>
-    <a href="/balance/5">next</a>
-    |
-    balance after <a href="/blocks/4">booking 4 (2001-01-03: test)</a>
-</p>
-<table class="alternating ">
-<tbody>
-    <tr>
-        <td class="money">
-            <details>
-                <summary>
-                    <table>
-                    <tbody>
-                        <tr>
-                            <td class="balance amount">-10</td>
-                            <td class="balance currency">€</td>
-                        </tr>
-                    </tbody>
-                    </table>
-                </summary>
-                <table>
-                <tbody>
-                    <tr>
-                        <td class="balance amount">-1</td>
-                        <td class="balance currency">USD</td>
-                    </tr>
-                </tbody>
-                </table>
-            </details>
-        </td>
-        <td>
-            <span class="indent"></span>bar:
-        </td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="money">
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <span class="indent">&nbsp;</span>:x:
-        </td>
-        <td>bla bla bla</td>
-    </tr>
-    <tr>
-        <td class="money">
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <span class="indent">&nbsp;&nbsp;</span>:y
-        </td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="money">
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <span class="indent">&nbsp;</span>:z
-        </td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="money">
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <span class="indent"></span>baz
-        </td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="money">
-            <details>
-                <summary>
-                    <table>
-                    <tbody>
-                        <tr>
-                            <td class="balance amount">20</td>
-                            <td class="balance currency">€</td>
-                        </tr>
-                    </tbody>
-                    </table>
-                </summary>
-                <table>
-                <tbody>
-                    <tr>
-                        <td class="balance amount">1</td>
-                        <td class="balance currency">USD</td>
-                    </tr>
-                </tbody>
-                </table>
-            </details>
-        </td>
-        <td>
-            <span class="indent"></span>foo:
-        </td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="money">
-            <details>
-                <summary>
-                    <table>
-                    <tbody>
-                        <tr>
-                            <td class="balance amount">10</td>
-                            <td class="balance currency">€</td>
-                        </tr>
-                    </tbody>
-                    </table>
-                </summary>
-                <table>
-                <tbody>
-                    <tr>
-                        <td class="balance amount">1</td>
-                        <td class="balance currency">USD</td>
-                    </tr>
-                </tbody>
-                </table>
-            </details>
-        </td>
-        <td>
-            <span class="indent">&nbsp;</span>:x
-        </td>
-        <td></td>
-    </tr>
-</tbody>
-</table>
-
-</body></html>
diff --git a/src/tests/full.edit_raw.0 b/src/tests/full.edit_raw.0
new file mode 100644 (file)
index 0000000..7b98e50
--- /dev/null
@@ -0,0 +1,169 @@
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/taint.js">
+</script>
+<style>
+html {
+    scroll-padding-top: 2em;
+}
+body {
+    background: #ffffff;
+    font-family: sans-serif;
+    text-align: left;
+    margin: 0;
+    padding: 0;
+}
+#header {
+    background: #ffffff;
+    position: sticky;
+    top: 0;
+    padding-left: 0.5em;
+    padding-bottom: 0.25em;
+    border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+    background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+    background: #ffffff;
+}
+td {
+    vertical-align: top;
+}
+.critical {
+    background: #ff6666 !important;
+}
+td.amount {
+    text-align: right;
+}
+td.amount,
+td.currency {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+    background-color: #ff8a8a;
+}
+td.balance.amount {
+    width: 10em;
+}
+td.balance.currency {
+    width: 3em;
+}
+td.direct_target {
+    font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="header">
+    <form action="/edit_raw/0" method="POST">
+        <span class="disable_on_taint">
+            ledger <a href="/ledger_structured">structured</a>
+            / <a href="/ledger_raw">raw</a>
+            · <a href="/balance">balance</a>
+            · <input type="submit" name="file_load" value="reload">
+        </span>
+    </form>
+</div>
+<form action="/edit_raw/0" method="POST">
+<span class="disable_on_taint">
+<del>prev</del>
+<a href="/blocks/1">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_structured/0">switch to structured</a>
+<a href="/balance/0">balance after</a>
+<a href="/ledger_raw/#block_0">in ledger</a>
+</span>
+<hr>
+
+<textarea name="raw_lines" class="tainter" cols="100" rows="6">; #def bar:x bla bla bla
+
+2001-01-01 test  ; foo
+    foo    10 €
+    bar   -10 €
+</textarea>
+</form>
+<table class="alternating">
+<tbody>
+    <tr>
+        <th>account</th>
+        <th>before</th>
+        <th>diff</th>
+        <th>after</th>
+    </tr>
+    <tr>
+        <td class="direct_target">bar</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">foo</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+</tbody>
+</table>
+
+</body></html>
diff --git a/src/tests/full.edit_raw.1 b/src/tests/full.edit_raw.1
deleted file mode 100644 (file)
index bf3f02b..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/taint.js">
-</script>
-<style>
-html {
-    scroll-padding-top: 2em;
-}
-body {
-    background: #ffffff;
-    font-family: sans-serif;
-    text-align: left;
-    margin: 0;
-    padding: 0;
-}
-#header {
-    background: #ffffff;
-    position: sticky;
-    top: 0;
-    padding-left: 0.5em;
-    padding-bottom: 0.25em;
-    border-bottom: 1px solid black;
-}
-table.alternating > tbody > tr:nth-child(odd) {
-    background-color: #dcdcdc;
-}
-table.alternating > tbody > tr:nth-child(even) {
-    background: #ffffff;
-}
-td {
-    vertical-align: top;
-}
-.critical {
-    background: #ff6666 !important;
-}
-td.amount {
-    text-align: right;
-}
-td.amount,
-td.currency {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-table.alternating.critical > tbody > tr:nth-child(even) {
-    background-color: #ff8a8a;
-}
-td.balance.amount {
-    width: 10em;
-}
-td.balance.currency {
-    width: 3em;
-}
-td.direct_target {
-    font-weight: bold;
-}
-</style>
-</head>
-<body>
-<div id="header">
-    <form action="/edit_raw/1" method="POST">
-        <span class="disable_on_taint">
-            ledger <a href="/ledger_structured">structured</a>
-            / <a href="/ledger_raw">raw</a>
-            · <a href="/balance">balance</a>
-            · <input type="submit" name="file_load" value="reload">
-        </span>
-    </form>
-</div>
-<form action="/edit_raw/1" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/0">prev</a>
-<a href="/blocks/2">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_structured/1">switch to structured</a>
-<a href="/balance/1">balance after</a>
-<a href="/ledger_raw/#block_1">in ledger</a>
-</span>
-<hr>
-
-<textarea name="raw_lines" class="tainter" cols="100" rows="5">2001-01-01 test ; foo
-  foo  10 €
-  bar  -10 €
-
-</textarea>
-</form>
-<table class="alternating">
-<tbody>
-    <tr>
-        <th>account</th>
-        <th>before</th>
-        <th>diff</th>
-        <th>after</th>
-    </tr>
-    <tr>
-        <td class="direct_target">bar</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">foo</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-</tbody>
-</table>
-
-</body></html>
diff --git a/src/tests/full.edit_raw.3 b/src/tests/full.edit_raw.3
new file mode 100644 (file)
index 0000000..f7197ef
--- /dev/null
@@ -0,0 +1,338 @@
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/taint.js">
+</script>
+<style>
+html {
+    scroll-padding-top: 2em;
+}
+body {
+    background: #ffffff;
+    font-family: sans-serif;
+    text-align: left;
+    margin: 0;
+    padding: 0;
+}
+#header {
+    background: #ffffff;
+    position: sticky;
+    top: 0;
+    padding-left: 0.5em;
+    padding-bottom: 0.25em;
+    border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+    background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+    background: #ffffff;
+}
+td {
+    vertical-align: top;
+}
+.critical {
+    background: #ff6666 !important;
+}
+td.amount {
+    text-align: right;
+}
+td.amount,
+td.currency {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+    background-color: #ff8a8a;
+}
+td.balance.amount {
+    width: 10em;
+}
+td.balance.currency {
+    width: 3em;
+}
+td.direct_target {
+    font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="header">
+    <form action="/edit_raw/3" method="POST">
+        <span class="disable_on_taint">
+            ledger <a href="/ledger_structured">structured</a>
+            / <a href="/ledger_raw">raw</a>
+            · <a href="/balance">balance</a>
+            · <input type="submit" name="file_load" value="reload">
+        </span>
+    </form>
+</div>
+<form action="/edit_raw/3" method="POST">
+<span class="disable_on_taint">
+<a href="/blocks/2">prev</a>
+<a href="/blocks/4">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_structured/3">switch to structured</a>
+<a href="/balance/3">balance after</a>
+<a href="/ledger_raw/#block_3">in ledger</a>
+</span>
+<hr>
+
+<textarea name="raw_lines" class="tainter" cols="100" rows="7">
+2001-01-03 test
+    foo:x    10 €
+    foo:x    1 USD
+    bar:x:y   -10 €
+    bar:z   -1 USD
+</textarea>
+</form>
+<table class="alternating">
+<tbody>
+    <tr>
+        <th>account</th>
+        <th>before</th>
+        <th>diff</th>
+        <th>after</th>
+    </tr>
+    <tr>
+        <td>bar:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td>bar:x:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">bar:x:y</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">bar:z</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td>foo:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">20</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">foo:x</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+</tbody>
+</table>
+
+</body></html>
diff --git a/src/tests/full.edit_raw.4 b/src/tests/full.edit_raw.4
deleted file mode 100644 (file)
index 158fa53..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/taint.js">
-</script>
-<style>
-html {
-    scroll-padding-top: 2em;
-}
-body {
-    background: #ffffff;
-    font-family: sans-serif;
-    text-align: left;
-    margin: 0;
-    padding: 0;
-}
-#header {
-    background: #ffffff;
-    position: sticky;
-    top: 0;
-    padding-left: 0.5em;
-    padding-bottom: 0.25em;
-    border-bottom: 1px solid black;
-}
-table.alternating > tbody > tr:nth-child(odd) {
-    background-color: #dcdcdc;
-}
-table.alternating > tbody > tr:nth-child(even) {
-    background: #ffffff;
-}
-td {
-    vertical-align: top;
-}
-.critical {
-    background: #ff6666 !important;
-}
-td.amount {
-    text-align: right;
-}
-td.amount,
-td.currency {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-table.alternating.critical > tbody > tr:nth-child(even) {
-    background-color: #ff8a8a;
-}
-td.balance.amount {
-    width: 10em;
-}
-td.balance.currency {
-    width: 3em;
-}
-td.direct_target {
-    font-weight: bold;
-}
-</style>
-</head>
-<body>
-<div id="header">
-    <form action="/edit_raw/4" method="POST">
-        <span class="disable_on_taint">
-            ledger <a href="/ledger_structured">structured</a>
-            / <a href="/ledger_raw">raw</a>
-            · <a href="/balance">balance</a>
-            · <input type="submit" name="file_load" value="reload">
-        </span>
-    </form>
-</div>
-<form action="/edit_raw/4" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/3">prev</a>
-<a href="/blocks/5">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_structured/4">switch to structured</a>
-<a href="/balance/4">balance after</a>
-<a href="/ledger_raw/#block_4">in ledger</a>
-</span>
-<hr>
-
-<textarea name="raw_lines" class="tainter" cols="100" rows="7">2001-01-03 test
-  foo:x  10 €
-  foo:x  1 USD
-  bar:x:y  -10 €
-  bar:z  -1 USD
-
-</textarea>
-</form>
-<table class="alternating">
-<tbody>
-    <tr>
-        <th>account</th>
-        <th>before</th>
-        <th>diff</th>
-        <th>after</th>
-    </tr>
-    <tr>
-        <td>bar:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td>bar:x:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">bar:x:y</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">bar:z</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td>foo:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">20</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">foo:x</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-</tbody>
-</table>
-
-</body></html>
diff --git a/src/tests/full.edit_structured.0 b/src/tests/full.edit_structured.0
new file mode 100644 (file)
index 0000000..ea6ffe1
--- /dev/null
@@ -0,0 +1,259 @@
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/edit_structured.js/0">
+</script>
+<style>
+html {
+    scroll-padding-top: 2em;
+}
+body {
+    background: #ffffff;
+    font-family: sans-serif;
+    text-align: left;
+    margin: 0;
+    padding: 0;
+}
+#header {
+    background: #ffffff;
+    position: sticky;
+    top: 0;
+    padding-left: 0.5em;
+    padding-bottom: 0.25em;
+    border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+    background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+    background: #ffffff;
+}
+td {
+    vertical-align: top;
+}
+.critical {
+    background: #ff6666 !important;
+}
+td.amount {
+    text-align: right;
+}
+td.amount,
+td.currency {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+    background-color: #ff8a8a;
+}
+td.balance.amount {
+    width: 10em;
+}
+td.balance.currency {
+    width: 3em;
+}
+td.direct_target {
+    font-weight: bold;
+}
+
+input.amount {
+    text-align: right;
+    font-family: monospace;
+}
+#date_input {
+    margin-right: 0.3em;
+    font-family: monospace;
+}
+</style>
+</head>
+<body>
+<div id="header">
+    <form action="/edit_structured/0" method="POST">
+        <span class="disable_on_taint">
+            ledger <a href="/ledger_structured">structured</a>
+            / <a href="/ledger_raw">raw</a>
+            · <a href="/balance">balance</a>
+            · <input type="submit" name="file_load" value="reload">
+        </span>
+    </form>
+</div>
+<form action="/edit_structured/0" method="POST">
+<span class="disable_on_taint">
+<del>prev</del>
+<a href="/blocks/1">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_raw/0">switch to raw</a>
+<a href="/balance/0">balance after</a>
+<a href="/ledger_structured/#block_0">in ledger</a>
+</span>
+<hr>
+
+<span class="disable_on_taint">
+<input id="btn_mirror" type="button" value="mirror">
+<input id="btn_sink" type="button" value="fill sink">
+|
+<input id="btn_replace" type="button" value="replace string">
+from
+<input id="replace_from">
+to
+<input id="replace_to">
+</span>
+<hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="3" class="tainter">; #def bar:x bla bla bla
+
+</textarea>
+<EXPANDED>
+<table id="booking_lines" class="alternating">
+    <tr>
+        <td colspan="1">
+        </td>
+        <td colspan="3">
+            <input name="line_0_date" size="10" value="2001-01-01" id="date_input">
+            <input name="line_0_target" size="37" value="test">
+        </td>
+        <td colspan="1">
+            <input name="line_0_comment" size="40" value="foo">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button" disabled="">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_1_account" size="30" value="foo" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_1_currency" size="3" value="€" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_1_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_2_account" size="30" value="bar" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_2_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_2_currency" size="3" value="€" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_2_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+</table>
+</EXPANDED>
+</form>
+<datalist id="all_accounts">
+<option value="bar">bar</option>
+<option value="bar:x">bar:x</option>
+<option value="bar:x:y">bar:x:y</option>
+<option value="bar:z">bar:z</option>
+<option value="baz">baz</option>
+<option value="foo">foo</option>
+<option value="foo:x">foo:x</option>
+</datalist>
+<hr>
+<table class="alternating">
+<tbody>
+    <tr>
+        <th>account</th>
+        <th>before</th>
+        <th>diff</th>
+        <th>after</th>
+    </tr>
+    <tr>
+        <td class="direct_target">bar</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">foo</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+</tbody>
+</table>
+
+</body></html>
diff --git a/src/tests/full.edit_structured.1 b/src/tests/full.edit_structured.1
deleted file mode 100644 (file)
index 4d9fbb5..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/edit_structured.js/1">
-</script>
-<style>
-html {
-    scroll-padding-top: 2em;
-}
-body {
-    background: #ffffff;
-    font-family: sans-serif;
-    text-align: left;
-    margin: 0;
-    padding: 0;
-}
-#header {
-    background: #ffffff;
-    position: sticky;
-    top: 0;
-    padding-left: 0.5em;
-    padding-bottom: 0.25em;
-    border-bottom: 1px solid black;
-}
-table.alternating > tbody > tr:nth-child(odd) {
-    background-color: #dcdcdc;
-}
-table.alternating > tbody > tr:nth-child(even) {
-    background: #ffffff;
-}
-td {
-    vertical-align: top;
-}
-.critical {
-    background: #ff6666 !important;
-}
-td.amount {
-    text-align: right;
-}
-td.amount,
-td.currency {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-table.alternating.critical > tbody > tr:nth-child(even) {
-    background-color: #ff8a8a;
-}
-td.balance.amount {
-    width: 10em;
-}
-td.balance.currency {
-    width: 3em;
-}
-td.direct_target {
-    font-weight: bold;
-}
-
-input.amount {
-    text-align: right;
-    font-family: monospace;
-}
-#date_input {
-    margin-right: 0.3em;
-    font-family: monospace;
-}
-</style>
-</head>
-<body>
-<div id="header">
-    <form action="/edit_structured/1" method="POST">
-        <span class="disable_on_taint">
-            ledger <a href="/ledger_structured">structured</a>
-            / <a href="/ledger_raw">raw</a>
-            · <a href="/balance">balance</a>
-            · <input type="submit" name="file_load" value="reload">
-        </span>
-    </form>
-</div>
-<form action="/edit_structured/1" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/0">prev</a>
-<a href="/blocks/2">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_raw/1">switch to raw</a>
-<a href="/balance/1">balance after</a>
-<a href="/ledger_structured/#block_1">in ledger</a>
-</span>
-<hr>
-
-<span class="disable_on_taint">
-<input id="btn_mirror" type="button" value="mirror">
-<input id="btn_sink" type="button" value="fill sink">
-|
-<input id="btn_replace" type="button" value="replace string">
-from
-<input id="replace_from">
-to
-<input id="replace_to">
-</span>
-<hr>
-<EXPANDED>
-<table id="booking_lines" class="alternating">
-    <tr>
-        <td colspan="1">
-        </td>
-        <td colspan="3">
-            <input name="line_0_date" size="10" value="2001-01-01" id="date_input">
-            <input name="line_0_target" size="37" value="test">
-        </td>
-        <td colspan="1">
-            <input name="line_0_comment" size="40" value="foo">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button" disabled="">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_1_account" size="30" value="foo" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_1_currency" size="3" value="€" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_1_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_2_account" size="30" value="bar" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_2_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_2_currency" size="3" value="€" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_2_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-</table>
-</EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
-</form>
-<datalist id="all_accounts">
-<option value="bar">bar</option>
-<option value="bar:x">bar:x</option>
-<option value="bar:x:y">bar:x:y</option>
-<option value="bar:z">bar:z</option>
-<option value="baz">baz</option>
-<option value="foo">foo</option>
-<option value="foo:x">foo:x</option>
-</datalist>
-<hr>
-<table class="alternating">
-<tbody>
-    <tr>
-        <th>account</th>
-        <th>before</th>
-        <th>diff</th>
-        <th>after</th>
-    </tr>
-    <tr>
-        <td class="direct_target">bar</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">foo</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">0</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-</tbody>
-</table>
-
-</body></html>
diff --git a/src/tests/full.edit_structured.3 b/src/tests/full.edit_structured.3
new file mode 100644 (file)
index 0000000..469bcbb
--- /dev/null
@@ -0,0 +1,470 @@
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/edit_structured.js/3">
+</script>
+<style>
+html {
+    scroll-padding-top: 2em;
+}
+body {
+    background: #ffffff;
+    font-family: sans-serif;
+    text-align: left;
+    margin: 0;
+    padding: 0;
+}
+#header {
+    background: #ffffff;
+    position: sticky;
+    top: 0;
+    padding-left: 0.5em;
+    padding-bottom: 0.25em;
+    border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+    background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+    background: #ffffff;
+}
+td {
+    vertical-align: top;
+}
+.critical {
+    background: #ff6666 !important;
+}
+td.amount {
+    text-align: right;
+}
+td.amount,
+td.currency {
+    font-family: monospace;
+    font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+    background-color: #ff8a8a;
+}
+td.balance.amount {
+    width: 10em;
+}
+td.balance.currency {
+    width: 3em;
+}
+td.direct_target {
+    font-weight: bold;
+}
+
+input.amount {
+    text-align: right;
+    font-family: monospace;
+}
+#date_input {
+    margin-right: 0.3em;
+    font-family: monospace;
+}
+</style>
+</head>
+<body>
+<div id="header">
+    <form action="/edit_structured/3" method="POST">
+        <span class="disable_on_taint">
+            ledger <a href="/ledger_structured">structured</a>
+            / <a href="/ledger_raw">raw</a>
+            · <a href="/balance">balance</a>
+            · <input type="submit" name="file_load" value="reload">
+        </span>
+    </form>
+</div>
+<form action="/edit_structured/3" method="POST">
+<span class="disable_on_taint">
+<a href="/blocks/2">prev</a>
+<a href="/blocks/4">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_raw/3">switch to raw</a>
+<a href="/balance/3">balance after</a>
+<a href="/ledger_structured/#block_3">in ledger</a>
+</span>
+<hr>
+
+<span class="disable_on_taint">
+<input id="btn_mirror" type="button" value="mirror">
+<input id="btn_sink" type="button" value="fill sink">
+|
+<input id="btn_replace" type="button" value="replace string">
+from
+<input id="replace_from">
+to
+<input id="replace_to">
+</span>
+<hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter">
+</textarea>
+<EXPANDED>
+<table id="booking_lines" class="alternating">
+    <tr>
+        <td colspan="1">
+        </td>
+        <td colspan="3">
+            <input name="line_0_date" size="10" value="2001-01-03" id="date_input">
+            <input name="line_0_target" size="37" value="test">
+        </td>
+        <td colspan="1">
+            <input name="line_0_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button" disabled="">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_1_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_1_currency" size="3" value="€" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_1_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_2_amount" size="12" value="1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_2_currency" size="3" value="USD" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_2_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_3_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_3_currency" size="3" value="€" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_3_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+    <tr>
+        <td colspan="1">
+            <button type="button">^</button>
+            <button type="button">v</button>
+        </td>
+        <td colspan="1">
+            <input name="line_4_account" size="30" value="bar:z" list="all_accounts" autocomplete="off">
+        </td>
+        <td colspan="1">
+            <input name="line_4_amount" size="12" value="-1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+        </td>
+        <td colspan="1">
+            <input name="line_4_currency" size="3" value="USD" placeholder="€">
+        </td>
+        <td colspan="1">
+            <input name="line_4_comment" size="40" value="">
+        </td>
+        <td colspan="1">
+            <button type="button">add new</button>
+            <button type="button">delete</button>
+        </td>
+    </tr>
+</table>
+</EXPANDED>
+</form>
+<datalist id="all_accounts">
+<option value="bar">bar</option>
+<option value="bar:x">bar:x</option>
+<option value="bar:x:y">bar:x:y</option>
+<option value="bar:z">bar:z</option>
+<option value="baz">baz</option>
+<option value="foo">foo</option>
+<option value="foo:x">foo:x</option>
+</datalist>
+<hr>
+<table class="alternating">
+<tbody>
+    <tr>
+        <th>account</th>
+        <th>before</th>
+        <th>diff</th>
+        <th>after</th>
+    </tr>
+    <tr>
+        <td>bar:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td>bar:x:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">bar:x:y</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">bar:z</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">-1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td>foo:</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">20</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+    <tr>
+        <td class="direct_target">foo:x</td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">0</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+        <td>
+            <table>
+            <tbody>
+                <tr>
+                    <td class="balance amount">10</td>
+                    <td class="balance currency">€</td>
+                </tr>
+                <tr>
+                    <td class="balance amount">1</td>
+                    <td class="balance currency">USD</td>
+                </tr>
+            </tbody>
+            </table>
+        </td>
+    </tr>
+</tbody>
+</table>
+
+</body></html>
index 262655703bea979ba8d53dee6588300e098e4377..c7097a3d043d52f117ae25afb2e9b263bad2fe1f 100644 (file)
@@ -78,7 +78,7 @@ input.amount {
 <form action="/edit_structured/4" method="POST">
 <span class="disable_on_taint">
 <a href="/blocks/3">prev</a>
-<a href="/blocks/5">next</a>
+<del>next</del>
 </span>
 <input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
 <input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
@@ -90,6 +90,12 @@ input.amount {
 <a href="/ledger_structured/#block_4">in ledger</a>
 </span>
 <hr>
+<div class="critical">
+    block-wide errors:
+    
+    sink missing for: -1 €, -2 USD
+</div>
+<hr>
 
 <span class="disable_on_taint">
 <input id="btn_mirror" type="button" value="mirror">
@@ -102,6 +108,9 @@ to
 <input id="replace_to">
 </span>
 <hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter">
+</textarea>
 <EXPANDED>
 <table id="booking_lines" class="alternating">
     <tr>
@@ -149,7 +158,7 @@ to
             <input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
         </td>
         <td colspan="1">
-            <input name="line_2_amount" size="12" value="1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+            <input name="line_2_amount" size="12" value="3" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
         </td>
         <td colspan="1">
             <input name="line_2_currency" size="3" value="USD" placeholder="€">
@@ -171,7 +180,7 @@ to
             <input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
         </td>
         <td colspan="1">
-            <input name="line_3_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+            <input name="line_3_amount" size="12" value="-9" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
         </td>
         <td colspan="1">
             <input name="line_3_currency" size="3" value="€" placeholder="€">
@@ -208,8 +217,6 @@ to
     </tr>
 </table>
 </EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
 </form>
 <datalist id="all_accounts">
 <option value="bar">bar</option>
@@ -221,7 +228,7 @@ to
 <option value="foo:x">foo:x</option>
 </datalist>
 <hr>
-<table class="alternating">
+<table class="alternating critical">
 <tbody>
     <tr>
         <th>account</th>
@@ -235,11 +242,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">-10</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">-1</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -249,7 +256,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-9</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
@@ -263,11 +270,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-19</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">-1</td>
+                    <td class="balance amount">-2</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -280,7 +287,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">-10</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -290,7 +297,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-9</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -300,7 +307,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-19</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -313,7 +320,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">-10</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -323,7 +330,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-9</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -333,7 +340,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-10</td>
+                    <td class="balance amount">-19</td>
                     <td class="balance currency">€</td>
                 </tr>
             </tbody>
@@ -346,7 +353,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">-1</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -366,7 +373,7 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">-1</td>
+                    <td class="balance amount">-2</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -379,11 +386,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">10</td>
+                    <td class="balance amount">20</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">1</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -397,7 +404,7 @@ to
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">1</td>
+                    <td class="balance amount">3</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -407,11 +414,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">20</td>
+                    <td class="balance amount">30</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">1</td>
+                    <td class="balance amount">4</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -424,11 +431,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">10</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">0</td>
+                    <td class="balance amount">1</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -442,7 +449,7 @@ to
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">1</td>
+                    <td class="balance amount">3</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
@@ -452,11 +459,11 @@ to
             <table>
             <tbody>
                 <tr>
-                    <td class="balance amount">10</td>
+                    <td class="balance amount">20</td>
                     <td class="balance currency">€</td>
                 </tr>
                 <tr>
-                    <td class="balance amount">1</td>
+                    <td class="balance amount">4</td>
                     <td class="balance currency">USD</td>
                 </tr>
             </tbody>
diff --git a/src/tests/full.edit_structured.5 b/src/tests/full.edit_structured.5
deleted file mode 100644 (file)
index b85a6e6..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/edit_structured.js/5">
-</script>
-<style>
-html {
-    scroll-padding-top: 2em;
-}
-body {
-    background: #ffffff;
-    font-family: sans-serif;
-    text-align: left;
-    margin: 0;
-    padding: 0;
-}
-#header {
-    background: #ffffff;
-    position: sticky;
-    top: 0;
-    padding-left: 0.5em;
-    padding-bottom: 0.25em;
-    border-bottom: 1px solid black;
-}
-table.alternating > tbody > tr:nth-child(odd) {
-    background-color: #dcdcdc;
-}
-table.alternating > tbody > tr:nth-child(even) {
-    background: #ffffff;
-}
-td {
-    vertical-align: top;
-}
-.critical {
-    background: #ff6666 !important;
-}
-td.amount {
-    text-align: right;
-}
-td.amount,
-td.currency {
-    font-family: monospace;
-    font-size: 1.25em;
-}
-table.alternating.critical > tbody > tr:nth-child(even) {
-    background-color: #ff8a8a;
-}
-td.balance.amount {
-    width: 10em;
-}
-td.balance.currency {
-    width: 3em;
-}
-td.direct_target {
-    font-weight: bold;
-}
-
-input.amount {
-    text-align: right;
-    font-family: monospace;
-}
-#date_input {
-    margin-right: 0.3em;
-    font-family: monospace;
-}
-</style>
-</head>
-<body>
-<div id="header">
-    <form action="/edit_structured/5" method="POST">
-        <span class="disable_on_taint">
-            ledger <a href="/ledger_structured">structured</a>
-            / <a href="/ledger_raw">raw</a>
-            · <a href="/balance">balance</a>
-            · <input type="submit" name="file_load" value="reload">
-        </span>
-    </form>
-</div>
-<form action="/edit_structured/5" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/4">prev</a>
-<del>next</del>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_raw/5">switch to raw</a>
-<a href="/balance/5">balance after</a>
-<a href="/ledger_structured/#block_5">in ledger</a>
-</span>
-<hr>
-<div class="critical">
-    block-wide errors:
-    
-    sink missing for: -1 €, -2 USD
-</div>
-<hr>
-
-<span class="disable_on_taint">
-<input id="btn_mirror" type="button" value="mirror">
-<input id="btn_sink" type="button" value="fill sink">
-|
-<input id="btn_replace" type="button" value="replace string">
-from
-<input id="replace_from">
-to
-<input id="replace_to">
-</span>
-<hr>
-<EXPANDED>
-<table id="booking_lines" class="alternating">
-    <tr>
-        <td colspan="1">
-        </td>
-        <td colspan="3">
-            <input name="line_0_date" size="10" value="2001-01-03" id="date_input">
-            <input name="line_0_target" size="37" value="test">
-        </td>
-        <td colspan="1">
-            <input name="line_0_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button" disabled="">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_1_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_1_currency" size="3" value="€" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_1_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_2_amount" size="12" value="3" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_2_currency" size="3" value="USD" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_2_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_3_amount" size="12" value="-9" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_3_currency" size="3" value="€" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_3_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="1">
-            <button type="button">^</button>
-            <button type="button">v</button>
-        </td>
-        <td colspan="1">
-            <input name="line_4_account" size="30" value="bar:z" list="all_accounts" autocomplete="off">
-        </td>
-        <td colspan="1">
-            <input name="line_4_amount" size="12" value="-1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
-        </td>
-        <td colspan="1">
-            <input name="line_4_currency" size="3" value="USD" placeholder="€">
-        </td>
-        <td colspan="1">
-            <input name="line_4_comment" size="40" value="">
-        </td>
-        <td colspan="1">
-            <button type="button">add new</button>
-            <button type="button">delete</button>
-        </td>
-    </tr>
-</table>
-</EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
-</form>
-<datalist id="all_accounts">
-<option value="bar">bar</option>
-<option value="bar:x">bar:x</option>
-<option value="bar:x:y">bar:x:y</option>
-<option value="bar:z">bar:z</option>
-<option value="baz">baz</option>
-<option value="foo">foo</option>
-<option value="foo:x">foo:x</option>
-</datalist>
-<hr>
-<table class="alternating critical">
-<tbody>
-    <tr>
-        <th>account</th>
-        <th>before</th>
-        <th>diff</th>
-        <th>after</th>
-    </tr>
-    <tr>
-        <td>bar:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-9</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-19</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">-2</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td>bar:x:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-9</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-19</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">bar:x:y</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-9</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-19</td>
-                    <td class="balance currency">€</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">bar:z</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">-2</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td>foo:</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">20</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">3</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">30</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">4</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td class="direct_target">foo:x</td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">1</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">10</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">3</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-        <td>
-            <table>
-            <tbody>
-                <tr>
-                    <td class="balance amount">20</td>
-                    <td class="balance currency">€</td>
-                </tr>
-                <tr>
-                    <td class="balance amount">4</td>
-                    <td class="balance currency">USD</td>
-                </tr>
-            </tbody>
-            </table>
-        </td>
-    </tr>
-</tbody>
-</table>
-
-</body></html>
index 89896b63ae2eeedf70ab91020eab27d251102e2c..40fef85d8b871ba204f4a8799b3b5dd3de9e9fff 100644 (file)
@@ -57,14 +57,14 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
 <tbody>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_0">
-        <td rowspan="3" class="block_column">
+        <td rowspan="6" class="block_column">
             <input type="submit" name="ledger_moveup_0" value="^" disabled="">
             <br>
             <input type="submit" name="ledger_movedown_0" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_0" value="C">
         </td>
-        <td rowspan="3" class="block_column">
+        <td rowspan="6" class="block_column">
             [<a href="#block_0">#</a>]<br>
             [<a href="/balance/0">b</a>]<br>
             [<a href="/edit_raw/0">e</a>]
@@ -72,12 +72,15 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
     </tr>
     <tr><td>; #def bar:x bla bla bla&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
+    <tr><td>2001-01-01 test  ; foo&nbsp;</td></tr>
+    <tr><td>    foo    10 €&nbsp;</td></tr>
+    <tr><td>    bar   -10 €&nbsp;</td></tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_1">
         <td rowspan="5" class="block_column">
             <input type="submit" name="ledger_moveup_1" value="^" disabled="">
             <br>
-            <input type="submit" name="ledger_movedown_1" value="v" disabled="">
+            <input type="submit" name="ledger_movedown_1" value="v">
             <br>
             <input type="submit" name="ledger_copy_1" value="C">
         </td>
@@ -87,16 +90,16 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
             [<a href="/edit_raw/1">e</a>]
         </td>
     </tr>
-    <tr><td>2001-01-01 test ; foo&nbsp;</td></tr>
-    <tr><td>  foo  10 €&nbsp;</td></tr>
-    <tr><td>  bar  -10 €&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
+    <tr><td>2001-01-02 test&nbsp;</td></tr>
+    <tr><td>    bar   -10 €  ; bar&nbsp;</td></tr>
+    <tr><td>    baz    10 €&nbsp;</td></tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_2">
         <td rowspan="6" class="block_column">
-            <input type="submit" name="ledger_moveup_2" value="^" disabled="">
+            <input type="submit" name="ledger_moveup_2" value="^">
             <br>
-            <input type="submit" name="ledger_movedown_2" value="v">
+            <input type="submit" name="ledger_movedown_2" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_2" value="C">
         </td>
@@ -106,72 +109,53 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
             [<a href="/edit_raw/2">e</a>]
         </td>
     </tr>
-    <tr><td>2001-01-02 test&nbsp;</td></tr>
-    <tr><td>  bar  -10 € ; bar&nbsp;</td></tr>
-    <tr><td>  baz  10 €&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
+    <tr><td>2001-01-02 test&nbsp;</td></tr>
+    <tr><td>    bar    20 €&nbsp;</td></tr>
+    <tr><td>    baz   -20 €  ; baz&nbsp;</td></tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_3">
-        <td rowspan="5" class="block_column">
-            <input type="submit" name="ledger_moveup_3" value="^">
+        <td rowspan="7" class="block_column">
+            <input type="submit" name="ledger_moveup_3" value="^" disabled="">
             <br>
-            <input type="submit" name="ledger_movedown_3" value="v" disabled="">
+            <input type="submit" name="ledger_movedown_3" value="v">
             <br>
             <input type="submit" name="ledger_copy_3" value="C">
         </td>
-        <td rowspan="5" class="block_column">
+        <td rowspan="7" class="block_column">
             [<a href="#block_3">#</a>]<br>
             [<a href="/balance/3">b</a>]<br>
             [<a href="/edit_raw/3">e</a>]
         </td>
     </tr>
-    <tr><td>2001-01-02 test&nbsp;</td></tr>
-    <tr><td>  bar  20 €&nbsp;</td></tr>
-    <tr><td>  baz  -20 € ; baz&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
+    <tr><td>2001-01-03 test&nbsp;</td></tr>
+    <tr><td>    foo:x    10 €&nbsp;</td></tr>
+    <tr><td>    foo:x    1 USD&nbsp;</td></tr>
+    <tr><td>    bar:x:y   -10 €&nbsp;</td></tr>
+    <tr><td>    bar:z   -1 USD&nbsp;</td></tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_4">
         <td rowspan="7" class="block_column">
-            <input type="submit" name="ledger_moveup_4" value="^" disabled="">
+            <input type="submit" name="ledger_moveup_4" value="^">
             <br>
-            <input type="submit" name="ledger_movedown_4" value="v">
+            <input type="submit" name="ledger_movedown_4" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_4" value="C">
         </td>
-        <td rowspan="7" class="block_column">
+        <td rowspan="7" class="block_column critical">
             [<a href="#block_4">#</a>]<br>
             [<a href="/balance/4">b</a>]<br>
             [<a href="/edit_raw/4">e</a>]
         </td>
     </tr>
-    <tr><td>2001-01-03 test&nbsp;</td></tr>
-    <tr><td>  foo:x  10 €&nbsp;</td></tr>
-    <tr><td>  foo:x  1 USD&nbsp;</td></tr>
-    <tr><td>  bar:x:y  -10 €&nbsp;</td></tr>
-    <tr><td>  bar:z  -1 USD&nbsp;</td></tr>
     <tr><td>&nbsp;</td></tr>
-    <tr></tr><!-- keep the background-color alternation in proper order -->
-    <tr id="block_5">
-        <td rowspan="7" class="block_column">
-            <input type="submit" name="ledger_moveup_5" value="^">
-            <br>
-            <input type="submit" name="ledger_movedown_5" value="v" disabled="">
-            <br>
-            <input type="submit" name="ledger_copy_5" value="C">
-        </td>
-        <td rowspan="7" class="block_column critical">
-            [<a href="#block_5">#</a>]<br>
-            [<a href="/balance/5">b</a>]<br>
-            [<a href="/edit_raw/5">e</a>]
-        </td>
-    </tr>
     <tr><td>2001-01-03 test&nbsp;</td></tr>
-    <tr><td>  foo:x  10 €&nbsp;</td></tr>
-    <tr><td>  foo:x  3 USD&nbsp;</td></tr>
-    <tr><td>  bar:x:y  -9 €&nbsp;</td></tr>
-    <tr><td>  bar:z  -1 USD&nbsp;</td></tr>
-    <tr><td>&nbsp;</td></tr>
+    <tr><td>    foo:x    10 €&nbsp;</td></tr>
+    <tr><td>    foo:x    3 USD&nbsp;</td></tr>
+    <tr><td>    bar:x:y   -9 €&nbsp;</td></tr>
+    <tr><td>    bar:z   -1 USD&nbsp;</td></tr>
 </tbody>
 </table>
 </form>
index cf0ea78586198f5969b8198118fb81bcd9fab658..6227d8e16ff017b259148eb8aa3c3ed149d5ac92 100644 (file)
@@ -62,14 +62,14 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
 <tbody>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_0">
-        <td rowspan="3" class="block_column">
+        <td rowspan="6" class="block_column">
             <input type="submit" name="ledger_moveup_0" value="^" disabled="">
             <br>
             <input type="submit" name="ledger_movedown_0" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_0" value="C">
         </td>
-        <td rowspan="3" class="block_column">
+        <td rowspan="6" class="block_column">
             [<a href="#block_0">#</a>]<br>
             [<a href="/balance/0">b</a>]<br>
             [<a href="/edit_structured/0">e</a>]
@@ -81,12 +81,28 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
     <tr>
         <td colspan="4">&nbsp;</td>
     </tr>
+    <tr>
+        <td colspan="3">2001-01-01 test</td>
+        <td>foo</td>
+    </tr>
+    <tr>
+        <td class="amount">10.00</td>
+        <td class="currency">€</td>
+        <td>foo</td>
+        <td></td>
+    </tr>
+    <tr>
+        <td class="amount">-10.00</td>
+        <td class="currency">€</td>
+        <td>bar</td>
+        <td></td>
+    </tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_1">
         <td rowspan="5" class="block_column">
             <input type="submit" name="ledger_moveup_1" value="^" disabled="">
             <br>
-            <input type="submit" name="ledger_movedown_1" value="v" disabled="">
+            <input type="submit" name="ledger_movedown_1" value="v">
             <br>
             <input type="submit" name="ledger_copy_1" value="C">
         </td>
@@ -97,30 +113,30 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
         </td>
     </tr>
     <tr>
-        <td colspan="3">2001-01-01 test</td>
-        <td>foo</td>
+        <td colspan="4">&nbsp;</td>
     </tr>
     <tr>
-        <td class="amount">10.00</td>
-        <td class="currency">€</td>
-        <td>foo</td>
+        <td colspan="3">2001-01-02 test</td>
         <td></td>
     </tr>
     <tr>
         <td class="amount">-10.00</td>
         <td class="currency">€</td>
         <td>bar</td>
-        <td></td>
+        <td>bar</td>
     </tr>
     <tr>
-        <td colspan="4">&nbsp;</td>
+        <td class="amount">10.00</td>
+        <td class="currency">€</td>
+        <td>baz</td>
+        <td></td>
     </tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
     <tr id="block_2">
         <td rowspan="6" class="block_column">
-            <input type="submit" name="ledger_moveup_2" value="^" disabled="">
+            <input type="submit" name="ledger_moveup_2" value="^">
             <br>
-            <input type="submit" name="ledger_movedown_2" value="v">
+            <input type="submit" name="ledger_movedown_2" value="v" disabled="">
             <br>
             <input type="submit" name="ledger_copy_2" value="C">
         </td>
@@ -130,43 +146,12 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
             [<a href="/edit_structured/2">e</a>]
         </td>
     </tr>
-    <tr>
-        <td colspan="3">2001-01-02 test</td>
-        <td></td>
-    </tr>
-    <tr>
-        <td class="amount">-10.00</td>
-        <td class="currency">€</td>
-        <td>bar</td>
-        <td>bar</td>
-    </tr>
-    <tr>
-        <td class="amount">10.00</td>
-        <td class="currency">€</td>
-        <td>baz</td>
-        <td></td>
-    </tr>
     <tr>
         <td colspan="4">&nbsp;</td>
     </tr>
     <tr>
         <td colspan="4">&nbsp;</td>
     </tr>
-    <tr></tr><!-- keep the background-color alternation in proper order -->
-    <tr id="block_3">
-        <td rowspan="5" class="block_column">
-            <input type="submit" name="ledger_moveup_3" value="^">
-            <br>
-            <input type="submit" name="ledger_movedown_3" value="v" disabled="">
-            <br>
-            <input type="submit" name="ledger_copy_3" value="C">
-        </td>
-        <td rowspan="5" class="block_column">
-            [<a href="#block_3">#</a>]<br>
-            [<a href="/balance/3">b</a>]<br>
-            [<a href="/edit_structured/3">e</a>]
-        </td>
-    </tr>
     <tr>
         <td colspan="3">2001-01-02 test</td>
         <td></td>
@@ -183,24 +168,24 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
         <td>baz</td>
         <td>baz</td>
     </tr>
-    <tr>
-        <td colspan="4">&nbsp;</td>
-    </tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
-    <tr id="block_4">
+    <tr id="block_3">
         <td rowspan="7" class="block_column">
-            <input type="submit" name="ledger_moveup_4" value="^" disabled="">
+            <input type="submit" name="ledger_moveup_3" value="^" disabled="">
             <br>
-            <input type="submit" name="ledger_movedown_4" value="v">
+            <input type="submit" name="ledger_movedown_3" value="v">
             <br>
-            <input type="submit" name="ledger_copy_4" value="C">
+            <input type="submit" name="ledger_copy_3" value="C">
         </td>
         <td rowspan="7" class="block_column">
-            [<a href="#block_4">#</a>]<br>
-            [<a href="/balance/4">b</a>]<br>
-            [<a href="/edit_structured/4">e</a>]
+            [<a href="#block_3">#</a>]<br>
+            [<a href="/balance/3">b</a>]<br>
+            [<a href="/edit_structured/3">e</a>]
         </td>
     </tr>
+    <tr>
+        <td colspan="4">&nbsp;</td>
+    </tr>
     <tr>
         <td colspan="3">2001-01-03 test</td>
         <td></td>
@@ -229,24 +214,24 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
         <td>bar:z</td>
         <td></td>
     </tr>
-    <tr>
-        <td colspan="4">&nbsp;</td>
-    </tr>
     <tr></tr><!-- keep the background-color alternation in proper order -->
-    <tr id="block_5">
+    <tr id="block_4">
         <td rowspan="7" class="block_column">
-            <input type="submit" name="ledger_moveup_5" value="^">
+            <input type="submit" name="ledger_moveup_4" value="^">
             <br>
-            <input type="submit" name="ledger_movedown_5" value="v" disabled="">
+            <input type="submit" name="ledger_movedown_4" value="v" disabled="">
             <br>
-            <input type="submit" name="ledger_copy_5" value="C">
+            <input type="submit" name="ledger_copy_4" value="C">
         </td>
         <td rowspan="7" class="block_column critical">
-            [<a href="#block_5">#</a>]<br>
-            [<a href="/balance/5">b</a>]<br>
-            [<a href="/edit_structured/5">e</a>]
+            [<a href="#block_4">#</a>]<br>
+            [<a href="/balance/4">b</a>]<br>
+            [<a href="/edit_structured/4">e</a>]
         </td>
     </tr>
+    <tr>
+        <td colspan="4">&nbsp;</td>
+    </tr>
     <tr>
         <td colspan="3">2001-01-03 test</td>
         <td></td>
@@ -275,9 +260,6 @@ Detected redundant empty lines in gaps, <input type="submit" name="remove_redund
         <td>bar:z</td>
         <td></td>
     </tr>
-    <tr>
-        <td colspan="4">&nbsp;</td>
-    </tr>
 </tbody>
 </table>
 <input type="submit" name="add_booking" value="add booking">