Skip to content

Commit

Permalink
Add a Contributing section to the docs, and cite it in error message
Browse files Browse the repository at this point in the history
This change adds a Contributing section to the README.md, and cites it
from the error message we emit when a string is passed to Rope≫Append()
that’s larger than the allowed string size.

Relates to #153.
  • Loading branch information
sideshowbarker committed Aug 16, 2023
1 parent 3b11b2d commit 55035c1
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 1 deletion.
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,59 @@ If you already have XCode installed, you can ensure you have the latest XCode co
```bash
xcode-select --install
```

## Contributing

When contributing code changes to Wattsi, it’s important to understand some particulars about the programming API the code exposes.

## How to work with strings

Many operations in the Wattsi code don’t take normal strings as input but instead (for performance reasons) take custom types of string buffers that are called Rope and CutRopes in the code (but that aren’t the same kind of Rope as what’s described at https://en.wikipedia.org/wiki/Rope_(data_structure)).

The typical cases where you’d need to work with Ropes and CutRopes are when you’re getting text content from the document source, and when you’re setting the values of attributes and text nodes in the output.

Here’s a commented example of setting an attribute value for an element:

```pascal
// Create a new <a> element and assign it to the NewLink variable.
NewLink := ConstructHTMLElement(eA);
// Create a new rope and assign it to the Scratch variable.
Scratch := Default(Rope);
// Get the text content of Element (which happens to be the current
// element being processed) and assign it to the ExtractedData variable
// (which happens to be a cutrope).
ExtractedData := Element.TextContent.ExtractAll();
// Append the literal string “#refs” to the Scratch rope.
Scratch.Append('#refs');
// Append the ExtractedData cutrope to the Scratch rope (“destructively”
// means that the ExtractedData cutrope is destroyed after the Append).
Scratch.AppendDestructively(ExtractedData);
// Set the value of the NewLink <a> element’s href attribute to the
// content of the Scratch rope (“destructively” means that the Scratch
// rope is destroyed after the attribute value is set).
NewLink.SetAttributeDestructively('href', Scratch);
```

And here’s a commented example of creating and appending a new text node:

```pascal
// Create a new <a> element and assign it to the NewLink variable.
NewLink := ConstructHTMLElement(eA);
// Create a new rope and assign it to the Scratch variable.
Scratch := Default(Rope);
// Get the text content of Element (which happens to be the current
// element being processed) and assign it to the ExtractedData variable
// (which happens to be a cutrope).
ExtractedData := Element.TextContent.ExtractAll();
// Append the literal string “[” to the Scratch rope.
Scratch.Append('[');
// Append the ExtractedData cutrope to the Scratch rope (“destructively”
// means that the ExtractedData cutrope is destroyed after the Append).
Scratch.AppendDestructively(ExtractedData);
// Append the literal string “]” to the Scratch rope.
Scratch.Append(']');
// Create a new text node from the Scratch rope (“destructively” means
// that the Scratch rope is destroyed after the text node is created),
// and append it to the NewLink <a> element.
NewLink.AppendChild(TText.CreateDestructively(Scratch));
```
2 changes: 1 addition & 1 deletion src/lib/ropes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ procedure Rope.Append(const NewString: RopeInternals.TInlineString);
if (Length(NewString) > RopeInternals.UTF8InlineSize) then
begin
Writeln('Error: Append() call with string length > UTF8InlineSize: "' + NewString + '"');
Writeln('Call Append() with a string pointer, not a string: Append(@Foo), not Append(Foo)');
Writeln('Use Ropes instead; see https://github.com/whatwg/wattsi/#how-to-work-with-strings');
Halt(1);
end;
if ((not Assigned(FLast)) or (FLast^.Kind <> rfUTF8Inline) or (RopeInternals.UTF8InlineSize - FLast^.InlineLength < Length(NewString))) then
Expand Down

0 comments on commit 55035c1

Please sign in to comment.