Skip to content

Commit

Permalink
Improve sandbox samples
Browse files Browse the repository at this point in the history
  • Loading branch information
popematt committed Sep 8, 2023
1 parent e6354f1 commit 495bbca
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 69 deletions.
250 changes: 184 additions & 66 deletions assets/ion-schema-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,53 @@ const validateButton = document.getElementById("validate");
const shareButton = document.getElementById("share");
const dropDownSelection = document.getElementById("examples");

function loadPage(schemaInputValue, valueInputValue, schemaTypeInputValue) {
function initPage() {
let sampleIds = Object.keys(SAMPLES);

// Check for data in the URL and add it to "SAMPLES"
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});

// If there are any query params in the URL, then use those and skip all the default values
const SHARED_ID = "shared_in_url"
if (params.schema || params.value || params.type) {
schemaInputValue = params.schema ?? "";
valueInputValue = params.value ?? "";
schemaTypeInputValue = params.type ?? "";
sampleIds.unshift(SHARED_ID) // Add the "Shared in URL" to the top of the list
SAMPLES[SHARED_ID] = {
displayName: "(Shared in URL)",
schema: params.schema ?? "",
value: params.value ?? "",
type: params.type ?? "",
};
}

// Set up the "samples" dropdown
for (let i = 0; i < sampleIds.length; ++i) {
let id = sampleIds[i]
dropDownSelection.add(new Option(SAMPLES[id].displayName, id));
}
if (SAMPLES[SHARED_ID]) {
dropDownSelection.selectedIndex = sampleIds.indexOf(SHARED_ID)
}
dropDownSelection.onchange()
}

function populateInputFields(sample) {
let { schema, value, type } = sample;

ace.edit("schema").setOptions({
mode: 'ace/mode/ion',
theme: 'ace/theme/cloud9_day',
showPrintMargin: false,
tabSize: 2,
value: schemaInputValue,
value: trimIndent(schema),
});
ace.edit("value").setOptions({
mode: 'ace/mode/ion',
theme: 'ace/theme/cloud9_day',
showPrintMargin: false,
tabSize: 2,
value: valueInputValue,
value: trimIndent(value),
});
document.getElementById("schema_type").value = schemaTypeInputValue;

document.getElementById("schema_type").value = type;

// clear any previous validation results
const pre = document.getElementById('result');
Expand All @@ -41,14 +60,6 @@ function loadPage(schemaInputValue, valueInputValue, schemaTypeInputValue) {
_set_output_style(resultDiv, "primary")
}

loadPage("type::{\n" +
" name: short_string,\n" +
" type: string,\n" +
" codepoint_length: range::[1, 10],\n" +
"}",
"\"Hello World!\"",
"short_string");

function _set_output_style(resultDiv, styleName) {
var toRemove = [];
resultDiv.classList.forEach(value => {
Expand Down Expand Up @@ -146,52 +157,159 @@ const copyUrl = () => {
shareButton.addEventListener("click", copyUrl);

dropDownSelection.onchange = function() {
var e = document.getElementById("examples");
var value = e.value;
if (value === "simpleTypeDefinition") {
// Default values for populating the input fields
let schemaInputValue = "type::{\n" +
" name: short_string,\n" +
" type: string,\n" +
" codepoint_length: range::[1, 10],\n" +
"}";
let valueInputValue = "\"Hello World!\"";
let schemaTypeInputValue = "short_string"

loadPage(schemaInputValue, valueInputValue, schemaTypeInputValue)
} else if (value === "typeDefinitionWithFields") {
// Default values for populating the input fields
let schemaInputValue = "type::{\n" +
" name: customer,\n" +
" type: struct,\n" +
" fields: {\n" +
" firstName: { type: string, occurs: required },\n" +
" middleName: string,\n" +
" lastName: { type: string, codepoint_length: range::[min, 7], occurs: required },\n" +
" age: { type: int, valid_values: range::[1, max] },\n" +
" }\n" +
"}";
let valueInputValue = "{\n" +
" firstName: \"John\",\n" +
" lastName: \"Doe\",\n" +
" age: -5,\n" +
" }";
let schemaTypeInputValue = "customer"

loadPage(schemaInputValue, valueInputValue, schemaTypeInputValue)
} else if (value === "typeDefinitionWithLogicConstraints") {
// Default values for populating the input fields
let schemaInputValue = "type::{\n" +
" name: any_of_core_types,\n" +
" any_of: [\n" +
" bool,\n" +
" int,\n" +
" string,\n" +
" ],\n" +
"}";
let valueInputValue = "hi";
let schemaTypeInputValue = "any_of_core_types"

loadPage(schemaInputValue, valueInputValue, schemaTypeInputValue)
}
let sample = SAMPLES[dropDownSelection.value];
populateInputFields(sample)
};

/**
* Detects a common minimal indent of all the input lines, removes it from every line.
* Note that blank lines do not affect the detected indent level.
*/
function trimIndent(str) {
let lines = str.split("\n").filter((l) => l.length > 0)
let indentLength = Math.min(...lines.filter((l) => l.trim().length > 0).map((l) => l.length - l.trimStart().length))
return lines.map((l) => l.substring(indentLength)).join("\n")
}

const SAMPLES = {
simpleTypeDefinition: {
displayName: "Simple Type Definition",
schema: `
$ion_schema_2_0
type::{
name: short_string,
type: string,
codepoint_length: range::[1, 10],
}
`,
type: "short_string",
value: `"Hello World!"`
},
typeDefinitionWithFields: {
displayName: "Type Definition with fields",
schema: `
$ion_schema_2_0
type::{
name: customer,
type: struct,
fields: closed::{
firstName: { type: string, occurs: required },
middleName: string,
lastName: { type: string, occurs: required },
age: { type: int, valid_values: range::[1, max], }
}
}`,
type: "customer",
value: `{ firstName: "John", lastName: "Doe", age: -5 }`,
},
typeDefinitionWithLogicConstraints: {
displayName: "Type Definition with logic constraints",
schema: `
$ion_schema_2_0
type::{
name: string_or_bool,
any_of: [string, bool],
}`,
type: "string_or_bool",
value: `hi`
},
versionedType: {
displayName: "Versioned Type",
schema: `
$ion_schema_2_0
type::{
// The 'widget' type includes all versions of widgets
name: widget,
any_of: [widget_v1, widget_v2],
}
type::{
// The 'widget_latest' type is an alias that always points to the latest version of widget
name: widget_latest,
type: widget_v2,
}
type::{
name: widget_v1,
fields: closed::{
name: string,
part_id: int,
component_ids: { type: list, element: int }
}
}
type::{
name: widget_v2,
fields: closed::{
name: string,
// widget_v2 has a string for the part_id
part_id: string,
component_ids: {
type: list,
// widget_v2s can still be constructed using v1 components,
// so this can be either a string or an int
element: { one_of: [string, int] }
}
}
}
`,
type: "widget",
value: `
// Try validating this as widget, widget_latest, widget_v1, and widget_v2
{
name: "WidgetFoo",
part_id: "177bfe43-e702-44a6-9625-f5eec025ec94",
component_ids: [
1843,
623,
"a890c9ca-1ed4-4f82-b1c7-272a50e256d1"
],
}
`,
},
nestedStructs: {
displayName: "Nested structs",
schema: `
$ion_schema_2_0
type::{
name: non_negative_int,
valid_values: range::[0, max],
}
type::{
name: package_metadata,
fields: closed::{
component_namespace: {
occurs: required,
type: string,
},
component_name: {
occurs: required,
type: string,
},
version: {
fields: closed::{
major: non_negative_int,
minor: non_negative_int,
patch: non_negative_int,
}
},
licenses: {
// Expected to be a list of SPDX license identifiers
occurs: required,
type: list,
container_length: range::[1, max],
element: string,
}
}
}`,
type: "package_metadata",
value: `
{
component_namespace: "com.amazon.ion",
component_name: "ion-schema-kotlin",
version: { major: 1, minor: 6, patch: 1 },
licenses: ["Apache-2.0"],
}
`
},
}

initPage();
4 changes: 1 addition & 3 deletions sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ title: Give Ion Schema a Try!

Predefined examples:
<select name="examples" id="examples">
<option value="simpleTypeDefinition">Simple Type Definition</option>
<option value="typeDefinitionWithFields">Type Definition with fields</option>
<option value="typeDefinitionWithLogicConstraints">Type Definition with logic constraint</option>
<!-- These are loaded dynamically in ion-schema-widget.js --/>
</select>
Enter one or more type definitions. No Authority is configured, so imports are not available.
Expand Down

0 comments on commit 495bbca

Please sign in to comment.