1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-26 04:00:43 +03:00

Kits now use JSON metadata

This commit is contained in:
Graham Nelson 2022-06-03 12:24:07 +01:00
parent 97dd0b9eda
commit b010ef8984
23 changed files with 411 additions and 99 deletions

View file

@ -1,6 +1,6 @@
# Inform 7
v10.1.0-beta+6V19 'Krypton' (1 June 2022)
v10.1.0-beta+6V20 'Krypton' (3 June 2022)
## About Inform 7

View file

@ -1,3 +1,3 @@
Prerelease: beta
Build Date: 1 June 2022
Build Number: 6V19
Build Date: 3 June 2022
Build Number: 6V20

View file

@ -69,7 +69,7 @@ to specifying |-kit BasicInformKit|.
@ Kits have the ability to specify that other kits are automatically added to
the project in an ITTT, "if-this-then-that", way. As we shall see, every kit
contains a file called |kit_metadata.txt| describing its needs. The metadata
contains a file called |kit_metadata.json| describing its needs. The metadata
for CommandParserKit includes:
= (text)
dependency: if CommandParserKit then WorldModelKit
@ -84,7 +84,7 @@ It follows that if WorldModelKit is not present, then BasicInformExtrasKit is
automatically added instead.
@ Kits can also use their metadata to specify that associated extensions should
automatically be loaded into the project.[1] For example, the |kit_metadata.txt|
automatically be loaded into the project.[1] For example, the |kit_metadata.json|
for BasicInformKit includes the lines:
= (text)
extension: Basic Inform by Graham Nelson
@ -193,7 +193,7 @@ an example of the result.) It is simple because it provides only a |Contents.w|
page and a |Sections| subdirectory -- it has no manual, chapters, figures,
sounds or other paraphernalia.
(*) A file called |kit_metadata.txt| describing the kit, its version and its
(*) A file called |kit_metadata.json| describing the kit, its version and its
dependencies.
(*) Compiled binary Inter files -- but only once the kit has been built. These
@ -245,7 +245,7 @@ very legible, and it is highly verbose.
[2] At some point it may be developed out a little, but there's no great need.
@ The metadata file at |BalloonKit/kit_metadata.txt| is going to be simple:
@ The metadata file at |BalloonKit/kit_metadata.json| is going to be simple:
= (text)
extension: Party Balloons by Joseph-Michel Montgolfier
=

View file

@ -0,0 +1,11 @@
{
"is": {
"type": "kit",
"title": "CastrovalvaKit",
"version": "2.7.1"
},
"compatibility": "not for 32-bit",
"kit-details": {
"has-priority": 1
}
}

View file

@ -1,3 +0,0 @@
version: 2.7.1
compatibility: not for 32-bit
priority: 1

View file

@ -479,9 +479,8 @@ just plain old files.
=
pathname *Supervisor::installed_files(void) {
inbuild_nest *I = Supervisor::internal();
if (I == NULL) Errors::fatal("Did not set -internal when calling");
return I->location;
if (shared_internal_nest) return shared_internal_nest->location;
return Pathnames::from_text(I"inform7/Internal");
}
@ As noted above, the transient area is used for ephemera such as dynamically

View file

@ -19,6 +19,7 @@ typedef struct inbuild_copy {
struct filename *location_if_file;
general_pointer metadata; /* the type of which depends on the work's genre */
struct JSON_value *metadata_record; /* where read in from a JSON file */
struct build_vertex *vertex; /* head vertex of build graph for this copy */
int source_text_read; /* have we attempted to read Inform source text from this? */
struct wording source_text; /* the source text we read, if so */
@ -38,6 +39,7 @@ inbuild_copy *Copies::new_p(inbuild_edition *edition) {
copy->location_if_path = NULL;
copy->location_if_file = NULL;
copy->metadata = NULL_GENERAL_POINTER;
copy->metadata_record = NULL;
copy->vertex = Graphs::copy_vertex(copy);
copy->source_text_read = FALSE;
copy->source_text = EMPTY_WORDING;

View file

@ -0,0 +1,141 @@
[JSONMetadata::] JSON Metadata.
Managing JSON-encoded metadata files for resources such as kits.
@ Every //inbuild_copy// can optionally contain a pointer to a JSON value called
|metadata_record|. The code in this section reads a file of JSON metadata into
that record, validating it (a) as syntactically correct JSON, (b) as JSON which
matches the Inbuild schema for what copy metadata should look like, and (c) as
identifying the copy which it purports to identify.
In practice, (a) and (b) are delegated to the //foundation: JSON// library.
=
void JSONMetadata::read_metadata_file(inbuild_copy *C, filename *F) {
JSON_requirement *req = JSONMetadata::requirements();
TEMPORARY_TEXT(contents)
TextFiles::read(F, FALSE, "unable to read file of JSON metadata", TRUE,
&JSONMetadata::read_metadata_file_helper, NULL, contents);
text_file_position tfp = TextFiles::at(F, 1);
JSON_value *value = JSON::decode(contents, &tfp);
if ((value) && (value->JSON_type == ERROR_JSONTYPE)) {
@<Report a syntax error in JSON@>;
return;
} else {
@<Validate the JSON read in@>;
}
DISCARD_TEXT(contents)
C->metadata_record = value;
@<Examine the "is" member of the metadata object@>;
}
void JSONMetadata::read_metadata_file_helper(text_stream *text, text_file_position *tfp,
void *v_state) {
text_stream *contents = (text_stream *) v_state;
WRITE_TO(contents, "%S\n", text);
}
@<Report a syntax error in JSON@> =
TEMPORARY_TEXT(err)
WRITE_TO(err, "the metadata contains a syntax error: '%S'", value->if_error);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
@<Validate the JSON read in@> =
linked_list *validation_errors = NEW_LINKED_LIST(text_stream);
if (JSON::validate(value, req, validation_errors) == FALSE) {
text_stream *err;
LOOP_OVER_LINKED_LIST(err, text_stream, validation_errors) {
TEMPORARY_TEXT(msg)
WRITE_TO(msg, "the metadata did not validate: '%S'", err);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, msg));
DISCARD_TEXT(msg)
}
return;
}
@<Examine the "is" member of the metadata object@> =
JSON_value *is = JSON::look_up_object(C->metadata_record, I"is");
JSON_value *type = JSON::look_up_object(is, I"type");
if (type) @<Make sure the type is correct@>;
JSON_value *title = JSON::look_up_object(is, I"title");
if (title) @<Make sure the title is correct@>;
JSON_value *author = JSON::look_up_object(is, I"author");
if (author) @<Make sure the author is correct@>;
JSON_value *version = JSON::look_up_object(is, I"version");
if (version) @<Read the version number and apply it@>;
JSON_value *version_range = JSON::look_up_object(is, I"version-range");
if (version_range) @<Forbid the use of a version range@>;
@ So, for example, if this file is from what we think is a kit, then it needs
to say that |is.type| is |"kit"|.
@<Make sure the type is correct@> =
text_stream *type_text = type->if_string;
text_stream *required_text = I"<unknown";
if (C->edition->work->genre == kit_genre) required_text = I"kit";
if (C->edition->work->genre == extension_genre) required_text = I"extension";
if (C->edition->work->genre == language_genre) required_text = I"language";
if (Str::ne(type_text, required_text)) {
TEMPORARY_TEXT(msg)
WRITE_TO(msg, "the metadata misidentifies the type as '%S', but it should be '%S'",
type_text, required_text);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, msg));
DISCARD_TEXT(msg)
}
@<Make sure the title is correct@> =
if (Str::ne(title->if_string, C->edition->work->title)) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "the metadata says the title is '%S' when it should be '%S'",
title->if_string, C->edition->work->title);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
@<Make sure the author is correct@> =
if (Str::ne(author->if_string, C->edition->work->author_name)) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "the metadata says the author is '%S' when it should be '%S'",
author->if_string, C->edition->work->author_name);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
@ Unlike those tests, here we simply trust the metadata to be correctly supplying
a version number.
@<Read the version number and apply it@> =
semantic_version_number V = VersionNumbers::from_text(version->if_string);
if (VersionNumbers::is_null(V)) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "cannot read version number '%S'", version->if_string);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
} else {
C->edition->version = VersionNumbers::from_text(version->if_string);
}
@<Forbid the use of a version range@> =
TEMPORARY_TEXT(err)
WRITE_TO(err, "the metadata should specify an exact version, not a range");
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
@ The following returns the schema needed for (b); we will load it in from a file
in the Inform/Inbuild installation, but will then cache the result so that it
loads only once.
=
dictionary *JSON_resource_metadata_requirements = NULL;
JSON_requirement *JSONMetadata::requirements(void) {
if (JSON_resource_metadata_requirements == NULL) {
filename *F = InstalledFiles::filename(JSON_REQUIREMENTS_IRES);
JSON_resource_metadata_requirements = JSON::read_requirements_file(NULL, F);
}
JSON_requirement *req =
JSON::look_up_requirements(JSON_resource_metadata_requirements, I"resource-metadata");
if (req == NULL) internal_error("JSON metadata file did not define <resource-metadata>");
return req;
}

View file

@ -5,7 +5,7 @@ Inter code.
@h Genre definition.
The |kit_genre| can be summarised as follows. Kits consist of directories,
containing metadata in |D/kit_metadata.txt|, but which are also valid Inweb
containing metadata in |D/kit_metadata.json|, but which are also valid Inweb
webs of Inform 6 source text. They are recognised by having directory names
ending in |Kit|, and by having a metadata file in place. They are stored in
nests, in |N/Inter/Title-vVersion|. Their build graphs are quite extensive,
@ -91,7 +91,7 @@ void KitManager::claim_as_copy(inbuild_genre *gen, inbuild_copy **C,
}
inbuild_copy *KitManager::claim_folder_as_copy(pathname *P) {
filename *canary = Filenames::in(P, I"kit_metadata.txt");
filename *canary = Filenames::in(P, I"kit_metadata.json");
if (TextFiles::exists(canary))
return KitManager::new_copy(Pathnames::directory_name(P), P);
return NULL;
@ -136,7 +136,7 @@ pathname *KitManager::pathname_in_nest(inbuild_nest *N, inbuild_edition *E) {
void KitManager::copy_to_nest(inbuild_genre *gen, inbuild_copy *C, inbuild_nest *N,
int syncing, build_methodology *meth) {
pathname *dest_kit = KitManager::pathname_in_nest(N, C->edition);
filename *dest_kit_metadata = Filenames::in(dest_kit, I"kit_metadata.txt");
filename *dest_kit_metadata = Filenames::in(dest_kit, I"kit_metadata.json");
if (TextFiles::exists(dest_kit_metadata)) {
if (syncing == FALSE) { Copies::overwrite_error(C, N); return; }
} else {

View file

@ -70,61 +70,108 @@ void Kits::scan(inbuild_copy *C) {
K->defines_Main = FALSE;
K->supports_nl = FALSE;
filename *F = Filenames::in(C->location_if_path, I"kit_metadata.txt");
TextFiles::read(F, FALSE,
NULL, FALSE, Kits::read_metadata, NULL, (void *) C);
filename *F = Filenames::in(C->location_if_path, I"kit_metadata.json");
JSONMetadata::read_metadata_file(C, F);
if (C->metadata_record) @<Extract what we need@>;
}
@ The following reads line by line through the |kit_metadata.txt| file:
=
void Kits::read_metadata(text_stream *text, text_file_position *tfp, void *state) {
inbuild_copy *C = (inbuild_copy *) state;
inform_kit *K = KitManager::from_copy(C);
match_results mr = Regexp::create_mr();
if ((Str::is_whitespace(text)) || (Regexp::match(&mr, text, L" *#%c*"))) {
;
} else if (Regexp::match(&mr, text, L"version: (%C+)"))
C->edition->version = VersionNumbers::from_text(mr.exp[0]);
else if (Regexp::match(&mr, text, L"compatibility: (%c+)")) @<Add compatibility@>
else if (Regexp::match(&mr, text, L"defines Main: yes")) K->defines_Main = TRUE;
else if (Regexp::match(&mr, text, L"defines Main: no")) K->defines_Main = FALSE;
else if (Regexp::match(&mr, text, L"natural language: yes")) K->supports_nl = TRUE;
else if (Regexp::match(&mr, text, L"natural language: no")) K->supports_nl = FALSE;
else if (Regexp::match(&mr, text, L"insert: (%c*)")) @<Add early source@>
else if (Regexp::match(&mr, text, L"priority: (%d*)"))
K->priority = Str::atoi(mr.exp[0], 0);
else if (Regexp::match(&mr, text, L"kinds: (%C+)"))
ADD_TO_LINKED_LIST(Str::duplicate(mr.exp[0]), text_stream, K->kind_definitions);
else if (Regexp::match(&mr, text, L"extension: version (%c+?) of (%c+) by (%c+)"))
@<Add versioned extension@>
else if (Regexp::match(&mr, text, L"extension: (%c+) by (%c+)"))
@<Add unversioned extension@>
else if (Regexp::match(&mr, text, L"activate: (%c+)"))
Kits::activation(K, mr.exp[0], TRUE);
else if (Regexp::match(&mr, text, L"deactivate: (%c+)"))
Kits::activation(K, mr.exp[0], FALSE);
else if (Regexp::match(&mr, text, L"dependency: if (%C+) then (%C+)"))
Kits::dependency(K, mr.exp[0], TRUE, mr.exp[1]);
else if (Regexp::match(&mr, text, L"dependency: if not (%C+) then (%C+)"))
Kits::dependency(K, mr.exp[0], FALSE, mr.exp[1]);
else if (Regexp::match(&mr, text, L"index from: (%c*)"))
K->index_structure = Str::duplicate(mr.exp[0]);
else {
TEMPORARY_TEXT(err)
WRITE_TO(err, "unreadable instruction '%S'", text);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
@<Extract what we need@> =
JSON_value *compatibility = JSON::look_up_object(C->metadata_record, I"compatibility");
if (compatibility) @<Add compatibility@>;
JSON_value *activate = JSON::look_up_object(C->metadata_record, I"activates");
if (activate) {
JSON_value *E;
LOOP_OVER_LINKED_LIST(E, JSON_value, activate->if_list)
Kits::activation(K, E->if_string, TRUE);
}
JSON_value *deactivate = JSON::look_up_object(C->metadata_record, I"deactivates");
if (deactivate) {
JSON_value *E;
LOOP_OVER_LINKED_LIST(E, JSON_value, deactivate->if_list)
Kits::activation(K, E->if_string, FALSE);
}
JSON_value *kit_details = JSON::look_up_object(C->metadata_record, I"kit-details");
if (kit_details) {
JSON_value *priority = JSON::look_up_object(kit_details, I"has-priority");
if (priority) K->priority = priority->if_integer;
JSON_value *defines_Main = JSON::look_up_object(kit_details, I"defines-Main");
if (defines_Main) K->defines_Main = defines_Main->if_boolean;
JSON_value *is_language_kit = JSON::look_up_object(kit_details, I"is-language-kit");
if (is_language_kit) K->supports_nl = is_language_kit->if_boolean;
JSON_value *index = JSON::look_up_object(kit_details, I"indexes-with-structure");
if (index) K->index_structure = index->if_string;
JSON_value *kinds = JSON::look_up_object(kit_details, I"provides-kinds");
if (kinds) {
JSON_value *E;
LOOP_OVER_LINKED_LIST(E, JSON_value, kinds->if_list)
ADD_TO_LINKED_LIST(E->if_string, text_stream, K->kind_definitions);
}
}
JSON_value *dependencies = JSON::look_up_object(C->metadata_record, I"needs");
if (dependencies) {
JSON_value *E;
LOOP_OVER_LINKED_LIST(E, JSON_value, dependencies->if_list) {
int loaded = TRUE;
JSON_value *if_clause = JSON::look_up_object(E, I"if");
JSON_value *unless_clause = JSON::look_up_object(E, I"unless");
if ((if_clause) && (unless_clause)) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "cannot give both 'if' and 'unless' in same requirement");
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
if (unless_clause) {
if_clause = unless_clause; loaded = FALSE;
}
JSON_value *then_clause = JSON::look_up_object(E, I"need");
if (then_clause) {
JSON_value *type = JSON::look_up_object(then_clause, I"type");
JSON_value *title = JSON::look_up_object(then_clause, I"title");
JSON_value *author = JSON::look_up_object(then_clause, I"author");
JSON_value *then_version = JSON::look_up_object(then_clause, I"version");
if (Str::eq(type->if_string, I"extension")) {
if (if_clause) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "a kit can only have an extension as a dependency unconditionally");
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
text_stream *extension_title = title->if_string;
text_stream *extension_author = author?(author->if_string):NULL;
if (then_version) @<Add versioned extension@>
else @<Add unversioned extension@>;
} else if (Str::eq(type->if_string, I"kit")) {
text_stream *if_kit = C->edition->work->title;
if (if_clause) {
JSON_value *if_type = JSON::look_up_object(if_clause, I"type");
if (Str::eq(if_type->if_string, I"kit") == FALSE) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "a kit dependency can only be conditional on other kits");
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
} else {
JSON_value *if_title = JSON::look_up_object(if_clause, I"title");
if (if_title) if_kit = if_title->if_string; /* a line for IF fans */
}
}
Kits::dependency(K, if_kit, loaded, title->if_string);
} else {
TEMPORARY_TEXT(err)
WRITE_TO(err, "a kit can only have extensions and kits as dependencies");
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
}
}
}
Regexp::dispose_of(&mr);
}
@<Add compatibility@> =
compatibility_specification *CS = Compatibility::from_text(mr.exp[0]);
compatibility_specification *CS = Compatibility::from_text(compatibility->if_string);
if (CS) C->edition->compatibility = CS;
else {
TEMPORARY_TEXT(err)
WRITE_TO(err, "cannot read compatibility '%S'", mr.exp[0]);
WRITE_TO(err, "cannot read compatibility '%S'", compatibility->if_string);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
}
@ -134,11 +181,11 @@ void Kits::read_metadata(text_stream *text, text_file_position *tfp, void *state
WRITE_TO(K->early_source, "\n\n");
@<Add versioned extension@> =
inbuild_work *work = Works::new(extension_genre, mr.exp[1], mr.exp[2]);
semantic_version_number V = VersionNumbers::from_text(mr.exp[0]);
inbuild_work *work = Works::new(extension_genre, extension_title, extension_author);
semantic_version_number V = VersionNumbers::from_text(then_version->if_string);
if (VersionNumbers::is_null(V)) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "cannot read version number '%S'", mr.exp[0]);
WRITE_TO(err, "cannot read version number '%S'", then_version->if_string);
Copies::attach_error(C, CopyErrors::new_T(KIT_MISWORDED_CE, -1, err));
DISCARD_TEXT(err)
} else {
@ -148,7 +195,7 @@ void Kits::read_metadata(text_stream *text, text_file_position *tfp, void *state
}
@<Add unversioned extension@> =
inbuild_work *work = Works::new(extension_genre, mr.exp[0], mr.exp[1]);
inbuild_work *work = Works::new(extension_genre, extension_title, extension_author);
inbuild_requirement *req = Requirements::any_version_of(work);
ADD_TO_LINKED_LIST(req, inbuild_requirement, K->extensions);

View file

@ -19,6 +19,7 @@ Chapter 2: Conceptual Framework
Copy Errors
Requirements
Nests
JSON Metadata
Chapter 3: Incremental Builds
Build Graphs

View file

@ -0,0 +1,10 @@
{
"is": {
"type": "kit",
"title": "BasicInformExtrasKit",
"version": "1"
},
"kit-details": {
"has-priority": 1
}
}

View file

@ -1 +0,0 @@
priority: 1

View file

@ -0,0 +1,36 @@
{
"is": {
"type": "kit",
"title": "BasicInformKit",
"version": "1"
},
"needs": [ {
"unless": {
"type": "kit",
"title": "WorldModelKit"
},
"need": {
"type": "kit",
"title": "BasicInformExtrasKit"
}
}, {
"need": {
"type": "extension",
"title": "Basic Inform",
"author": "Graham Nelson"
}
}, {
"need": {
"type": "extension",
"title": "English Language",
"author": "Graham Nelson"
}
} ],
"activates": [ "glulx external files" ],
"kit-details": {
"has-priority": 0,
"defines-Main": false,
"provides-kinds": [ "Macros.neptune", "Protocols.neptune", "Core.neptune", "Punctuation.neptune", "Files.neptune" ],
"indexes-with-structure": "Basic.indext"
}
}

View file

@ -1,12 +0,0 @@
priority: 0
extension: Basic Inform by Graham Nelson
extension: English Language by Graham Nelson
dependency: if not WorldModelKit then BasicInformExtrasKit
kinds: Macros.neptune
kinds: Protocols.neptune
kinds: Core.neptune
kinds: Punctuation.neptune
kinds: Files.neptune
activate: glulx external files
defines Main: no
index from: Basic.indext

View file

@ -0,0 +1,24 @@
{
"is": {
"type": "kit",
"title": "CommandParserKit",
"version": "1"
},
"needs": [ {
"need": {
"type": "kit",
"title": "WorldModelKit"
}
}, {
"need": {
"type": "extension",
"title": "Standard Rules",
"author": "Graham Nelson"
}
} ],
"activates": [ "command" ],
"kit-details": {
"has-priority": 3,
"provides-kinds": [ "Parsing.neptune" ]
}
}

View file

@ -1,5 +0,0 @@
priority: 3
extension: Standard Rules by Graham Nelson
dependency: if CommandParserKit then WorldModelKit
activate: command
kinds: Parsing.neptune

View file

@ -0,0 +1,17 @@
{
"is": {
"type": "kit",
"title": "EnglishLanguageKit",
"version": "1"
},
"needs": [ {
"need": {
"type": "extension",
"title": "English Language",
"author": "Graham Nelson"
}
} ],
"kit-details": {
"has-priority": 1
}
}

View file

@ -1,3 +0,0 @@
priority: 1
extension: English Language by Graham Nelson
natural language: yes

View file

@ -0,0 +1,21 @@
{
"is": {
"type": "kit",
"title": "WorldModelKit",
"version": "1"
},
"needs": [ {
"need": {
"type": "extension",
"title": "Standard Rules",
"author": "Graham Nelson"
}
} ],
"activates": [ "interactive fiction", "multimedia" ],
"kit-details": {
"has-priority": 2,
"defines-Main": true,
"provides-kinds": [ "Actions.neptune", "Times.neptune", "Scenes.neptune", "Figures.neptune", "Sounds.neptune" ],
"indexes-with-structure": "Standard.indext"
}
}

View file

@ -1,11 +0,0 @@
priority: 2
extension: Standard Rules by Graham Nelson
kinds: Actions.neptune
kinds: Times.neptune
kinds: Scenes.neptune
kinds: Figures.neptune
kinds: Sounds.neptune
activate: interactive fiction
activate: multimedia
defines Main: yes
index from: Standard.indext

View file

@ -0,0 +1,35 @@
<resource> ::= {
"type": ( "kit" | "extension" | "language" ),
"title": string,
?"author": string,
?"version": string,
?"version-range": string
}
<kit-metadata> ::= {
?"has-priority": number,
?"provides-kinds": [ string* ],
?"defines-Main": boolean,
?"indexes-with-structure": string
}
<extension-metadata> ::= {
}
<language-metadata> ::= {
}
<resource-metadata> ::= {
"is": <resource>,
?"compatibility": string,
?"activates": [ string* ],
?"deactivates": [ string* ],
?"needs": [ {
?"if": <resource>,
?"unless": <resource>,
"need": <resource>
}* ],
?"kit-details": <kit-metadata>,
?"extension-details": <extension-metadata>,
?"language-details": <language-metadata>
}

View file

@ -21,6 +21,7 @@ but they're just plain old files, and are not managed by Inbuild as "copies".
@e CSS_SET_BY_PLATFORM_IRES
@e CSS_FOR_STANDARD_PAGES_IRES
@e EXTENSION_DOCUMENTATION_MODEL_IRES
@e JSON_REQUIREMENTS_IRES
=
filename *InstalledFiles::filename(int ires) {
@ -38,6 +39,8 @@ filename *InstalledFiles::filename(int ires) {
return Filenames::in(misc, I"DefaultCover.jpg");
case SMALL_DEFAULT_COVER_ART_IRES:
return Filenames::in(misc, I"Small Cover.jpg");
case JSON_REQUIREMENTS_IRES:
return Filenames::in(misc, I"metadata.jsonr");
case CBLORB_REPORT_MODEL_IRES:
return InstalledFiles::varied_by_platform(models, I"CblorbModel.html");