magic_string

String editing by byte offset, with a source map as a byproduct.

Keep the original source, record overwrite/remove/insert edits keyed by UTF-8 byte offset, then to_string and generate_map replay the log. Surviving slices of the original produce mapping segments; inserted text does not.

Types

A concatenation of edited sources. Materializes to the joined output text and a single Source Map v3 spanning every source.

pub opaque type Bundle

Why an edit was rejected.

pub type EditError {
  Overlap(existing: #(Int, Int), attempted: #(Int, Int))
  SwallowedInsert(at: Int, range: #(Int, Int))
  OutOfBounds(offset: Int, source_length: Int)
  InvertedRange(start: Int, end: Int)
}

Constructors

  • Overlap(existing: #(Int, Int), attempted: #(Int, Int))

    attempted shares at least one byte with an existing range.

  • SwallowedInsert(at: Int, range: #(Int, Int))

    An insert at at falls strictly inside range (range.0 < at < range.1). Boundaries are fine.

  • OutOfBounds(offset: Int, source_length: Int)

    offset is outside [0, source_length].

  • InvertedRange(start: Int, end: Int)

    end < start.

Immutable string editor. Keeps the original source plus a sorted edit log and is materialized lazily by to_string / generate_map.

  • intro / outro accumulate prepend / append content wrapping the whole string.
  • edits maps an edit’s start offset to the overwrite/remove at that point.
  • left_inserts / right_inserts map a byte offset to text inserted just left of (after the preceding content) or right of (before the following content) that offset.
pub opaque type MagicString

Options shared by generate_map and bundle_generate_map.

pub type MapOptions {
  MapOptions(
    file: option.Option(String),
    source_root: option.Option(String),
    include_content: Bool,
  )
}

Constructors

Values

pub fn add_source(
  b: Bundle,
  filename: String,
  content: String,
  ms: MagicString,
) -> Bundle

Append a source to the bundle. filename is the name recorded in the map’s sources; content is the original text; ms is its edit log.

pub fn append(ms: MagicString, content: String) -> MagicString

Append content to the very end of the output.

pub fn append_left(
  ms: MagicString,
  index: Int,
  content: String,
) -> Result(MagicString, EditError)

Insert content just LEFT of index: after the content that ends at index, before anything inserted to the right of index. Repeated calls at the same index append in call order.

Returns Error(SwallowedInsert) if index falls strictly inside an existing overwrite/remove range (the insert would never be visited and so would be silently dropped), or Error(OutOfBounds) if index is outside the source.

pub fn append_right(
  ms: MagicString,
  index: Int,
  content: String,
) -> Result(MagicString, EditError)

Insert content just RIGHT of index: before the content that starts at index, after anything inserted to the left of index. Repeated calls at the same index append in call order.

Returns Error for the same reasons as append_left.

pub fn bundle() -> Bundle

An empty bundle.

pub fn bundle_generate_map(
  b: Bundle,
  opts: MapOptions,
) -> codec.SourceMap

Generate one Source Map v3 spanning every source in output order.

Walks each source’s pieces, offsetting their segments into chunk-space: the generated line/column accumulates across the whole output, and the newline joining each source to the next advances the generated line by one (and resets the column). Each source is assigned its index in sources.

pub fn bundle_to_string(b: Bundle) -> String

Materialize the bundle output: each source’s edited text, joined by newlines (one line break between sources).

pub fn default_map_options() -> MapOptions

Sensible defaults: no file, no sourceRoot, embed original content.

pub fn describe_error(err: EditError) -> String

Human-readable description of an EditError.

pub fn generate_map(
  ms: MagicString,
  filename: String,
  opts: MapOptions,
) -> codec.SourceMap

Generate a Source Map v3 for a single edited source. filename is recorded as the sole entry of sources; include_content controls whether the original text is embedded in sourcesContent.

pub fn new(source: String) -> MagicString

Create an editor over source with no edits.

pub fn overwrite(
  ms: MagicString,
  start: Int,
  end: Int,
  with content: String,
) -> Result(MagicString, EditError)

Replace the original byte range [start, end) with with. The replacement is inserted text and produces no mapping segment.

Returns Error if [start, end) overlaps an existing range, would swallow an existing insert, or is out of bounds. Same-start is last-write-wins; adjacent ranges that only share a boundary are fine.

pub fn prepend(ms: MagicString, content: String) -> MagicString

Prepend content to the very start of the output. Repeated calls stack so the most recent prepend ends up first.

pub fn remove(
  ms: MagicString,
  start: Int,
  end: Int,
) -> Result(MagicString, EditError)

Delete the original byte range [start, end). Returns Error for the same reasons as overwrite (it is overwrite with an empty replacement).

pub fn to_string(ms: MagicString) -> String

Materialize the edited output as a string.

Search Document