-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[tyson] Implicitly export a single top-level object literal (#72)
- Loading branch information
Showing
11 changed files
with
144 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// When there are several expressions in a file, how does TySON choose which one | ||
// to evaluate as JSON? | ||
// Simple: it always uses the default export | ||
|
||
var one = { | ||
one: 1 | ||
} | ||
|
||
var two = { | ||
two: 2 | ||
} | ||
|
||
var three = { | ||
three: 3 | ||
} | ||
|
||
export default two; // This is the default export | ||
|
||
// This file evaluates to the following JSON: | ||
// { | ||
// "two": 2 | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// If TySON always uses the default export, how does it handle simple JSON-like cases | ||
// where there are no exports? | ||
// | ||
// The answer is that while TySON uses standard TypeScript syntax, it does apply | ||
// a single non-standard transformation to the input file: if a file has a single | ||
// top-level object literal, then that object literal is implicitly treated as the | ||
// default export. | ||
// | ||
// This transformation is important, because it makes it possible to read standard | ||
// .json files as valid .tson files. | ||
|
||
// In this example, the following object literal is interpreted as the default export: | ||
{ | ||
foo: 'bar', | ||
} | ||
|
||
// In other words, it's the same as if we had written: | ||
// export default { | ||
// foo: 'bar', | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package tsembed | ||
|
||
import ( | ||
"bytes" | ||
"os" | ||
"strings" | ||
"text/scanner" | ||
|
||
"github.com/evanw/esbuild/pkg/api" | ||
) | ||
|
||
var TsonTransform = api.Plugin{ | ||
Name: "tsonTransform", | ||
Setup: func(build api.PluginBuild) { | ||
build.OnLoad( | ||
api.OnLoadOptions{Filter: `\.tson$`}, | ||
loadTSON, | ||
) | ||
}, | ||
} | ||
|
||
func loadTSON(args api.OnLoadArgs) (api.OnLoadResult, error) { | ||
original, err := os.ReadFile(args.Path) | ||
if err != nil { | ||
return api.OnLoadResult{}, err | ||
} | ||
|
||
offset := findImplicitExport(original) | ||
var builder strings.Builder | ||
|
||
if offset != -1 { | ||
builder.Write(original[:offset]) | ||
builder.WriteString("export default ") | ||
builder.Write(original[offset:]) | ||
} else { | ||
builder.Write(original) | ||
} | ||
|
||
result := builder.String() | ||
return api.OnLoadResult{ | ||
Contents: &result, | ||
Loader: api.LoaderTS, | ||
}, nil | ||
} | ||
|
||
// If there are no exports, but there is an top-level object, we identify it | ||
// as an object that should be implicitly exported. | ||
func findImplicitExport(data []byte) int { | ||
buf := bytes.NewReader(data) | ||
var tokenizer scanner.Scanner | ||
tokenizer.Init(buf) | ||
tokenizer.Error = func(_ *scanner.Scanner, _ string) {} // ignore errors | ||
|
||
var offset = -1 | ||
nestingLevel := 0 | ||
existingObject := false | ||
for tok := tokenizer.Scan(); tok != scanner.EOF; tok = tokenizer.Scan() { | ||
switch token := tokenizer.TokenText(); token { | ||
case "{": | ||
// We found a top-level object: | ||
if nestingLevel == 0 { | ||
if !existingObject { | ||
// This is the first one we find, so save the offset as we might want to | ||
// implicitly export it. | ||
offset = tokenizer.Offset | ||
existingObject = true | ||
} else { | ||
// If we've found more than one top-level object, we don't want to implicitly | ||
// export any of them. | ||
return -1 | ||
} | ||
} | ||
nestingLevel++ | ||
case "}": | ||
nestingLevel-- | ||
default: | ||
// We've run into another expression, so we don't want to implicitly export anything. | ||
if nestingLevel == 0 { | ||
return -1 | ||
} | ||
} | ||
} | ||
return offset | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters