Skip to content

Commit

Permalink
Highlight base dialects in the explorer
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Jan 6, 2025
1 parent 9c840bc commit f28911e
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 22 deletions.
30 changes: 28 additions & 2 deletions src/enterprise/enterprise_explorer.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ static auto file_manager(std::ostringstream &html,

assert(entry.defines("type"));
assert(entry.at("type").is_string());
html << "<td>";
html << "<td class=\"text-nowrap\">";
if (entry.at("type").to_string() == "directory") {
if (entry.defines("github")) {
html << "<img src=\"https://github.com/";
Expand All @@ -159,7 +159,33 @@ static auto file_manager(std::ostringstream &html,
html << "<i class=\"bi bi-folder-fill\"></i>";
}
} else {
html << "<i class=\"bi bi-braces\"></i>";
const auto &base_dialect{entry.at("baseDialect").to_string()};
html << "<a "
"href=\"https://www.learnjsonschema.com/";
html << base_dialect;
html << "\">";
html << "<span class=\"align-middle badge ";

// Highlight the latest version in a different manner
if (base_dialect == "2020-12") {
html << "text-bg-primary";
} else {
html << "text-bg-danger";
}

html << "\">";

for (auto iterator = base_dialect.cbegin();
iterator != base_dialect.cend(); ++iterator) {
if (iterator == base_dialect.cbegin()) {
html << static_cast<char>(std::toupper(*iterator));
} else {
html << *iterator;
}
}

html << "</span>";
html << "</a>";
}
html << "</td>";

Expand Down
96 changes: 88 additions & 8 deletions src/enterprise/enterprise_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sourcemeta/jsontoolkit/json.h>

#include <algorithm> // std::sort
#include <cassert> // assert
#include <cstdlib> // EXIT_SUCCESS
#include <filesystem> // std::filesystem
#include <fstream> // std::ofstream
Expand All @@ -17,12 +18,63 @@ static auto trim(const std::string &input) -> std::string {
return copy;
}

static auto base_dialect_id(const std::string &base_dialect) -> std::string {
if (base_dialect == "https://json-schema.org/draft/2020-12/schema" ||
base_dialect == "https://json-schema.org/draft/2020-12/hyper-schema") {
return "2020-12";
}

if (base_dialect == "https://json-schema.org/draft/2019-09/schema" ||
base_dialect == "https://json-schema.org/draft/2019-09/hyper-schema") {
return "2019-09";
}

if (base_dialect == "http://json-schema.org/draft-07/schema#" ||
base_dialect == "http://json-schema.org/draft-07/hyper-schema#") {
return "draft7";
}

if (base_dialect == "http://json-schema.org/draft-06/schema#" ||
base_dialect == "http://json-schema.org/draft-06/hyper-schema#") {
return "draft6";
}

if (base_dialect == "http://json-schema.org/draft-04/schema#" ||
base_dialect == "http://json-schema.org/draft-04/hyper-schema#") {
return "draft4";
}

if (base_dialect == "http://json-schema.org/draft-03/schema#" ||
base_dialect == "http://json-schema.org/draft-03/hyper-schema#") {
return "draft3";
}

if (base_dialect == "http://json-schema.org/draft-02/hyper-schema#") {
return "draft2";
}

if (base_dialect == "http://json-schema.org/draft-01/hyper-schema#") {
return "draft1";
}

if (base_dialect == "http://json-schema.org/draft-00/hyper-schema#") {
return "draft0";
}

// We should never get here
assert(false);
return "Unknown";
}

namespace sourcemeta::registry::enterprise {

auto generate_toc(const sourcemeta::jsontoolkit::JSON &configuration,
const std::filesystem::path &base,
const std::filesystem::path &directory,
sourcemeta::jsontoolkit::JSON &search_index) -> void {
auto generate_toc(
const sourcemeta::jsontoolkit::FlatFileSchemaResolver &resolver,
const sourcemeta::jsontoolkit::URI &server_url,
const sourcemeta::jsontoolkit::JSON &configuration,
const std::filesystem::path &base, const std::filesystem::path &directory,
sourcemeta::jsontoolkit::JSON &search_index) -> void {
const auto server_url_string{server_url.recompose()};
assert(directory.string().starts_with(base.string()));
auto entries{sourcemeta::jsontoolkit::JSON::make_array()};

Expand Down Expand Up @@ -65,6 +117,32 @@ auto generate_toc(const sourcemeta::jsontoolkit::JSON &configuration,
trim(schema.at("description").to_string())});
}

// Calculate base dialect
std::ostringstream absolute_schema_url;
absolute_schema_url << server_url_string;

// TODO: We should have better utilities to avoid these
// URL concatenation edge cases

if (!server_url_string.ends_with('/')) {
absolute_schema_url << '/';
}

if (entry_relative_path.starts_with('/')) {
absolute_schema_url << entry_relative_path.substr(1);
} else {
absolute_schema_url << entry_relative_path;
}

const auto resolved_schema{resolver(absolute_schema_url.str())};
assert(resolved_schema.has_value());
const auto base_dialect{
sourcemeta::jsontoolkit::base_dialect(schema, resolver)};
assert(base_dialect.has_value());
entry_json.assign(
"baseDialect",
sourcemeta::jsontoolkit::JSON{base_dialect_id(base_dialect.value())});

entry_json.assign("url",
sourcemeta::jsontoolkit::JSON{entry_relative_path});

Expand Down Expand Up @@ -134,13 +212,15 @@ auto generate_toc(const sourcemeta::jsontoolkit::JSON &configuration,
stream.close();
}

auto attach(const sourcemeta::jsontoolkit::JSON &configuration,
auto attach(const sourcemeta::jsontoolkit::FlatFileSchemaResolver &resolver,
const sourcemeta::jsontoolkit::URI &server_url,
const sourcemeta::jsontoolkit::JSON &configuration,
const std::filesystem::path &, const std::filesystem::path &output)
-> int {
std::cerr << "-- Indexing directory: " << output.string() << "\n";
const auto base{std::filesystem::canonical(output / "schemas")};
auto search_index{sourcemeta::jsontoolkit::JSON::make_array()};
generate_toc(configuration, base, base, search_index);
generate_toc(resolver, server_url, configuration, base, base, search_index);

for (const auto &entry :
std::filesystem::recursive_directory_iterator{output / "schemas"}) {
Expand All @@ -149,8 +229,8 @@ auto attach(const sourcemeta::jsontoolkit::JSON &configuration,
}

std::cerr << "-- Processing: " << entry.path().string() << "\n";
generate_toc(configuration, base, std::filesystem::canonical(entry.path()),
search_index);
generate_toc(resolver, server_url, configuration, base,
std::filesystem::canonical(entry.path()), search_index);
}

std::ofstream stream{output / "search.json"};
Expand Down
28 changes: 16 additions & 12 deletions src/index/index.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,15 @@ static auto url_join(const std::string &first, const std::string &second,
return result.str();
}

static auto index(const sourcemeta::jsontoolkit::JSON &configuration,
static auto index(sourcemeta::jsontoolkit::FlatFileSchemaResolver &resolver,
const sourcemeta::jsontoolkit::URI &server_url,
const sourcemeta::jsontoolkit::JSON &configuration,
const std::filesystem::path &base,
const std::filesystem::path &output) -> int {
assert(std::filesystem::exists(base));
assert(std::filesystem::exists(output));

const auto server_url{
sourcemeta::jsontoolkit::URI{configuration.at("url").to_string()}
.canonicalize()};

// Popular flat file resolver
sourcemeta::jsontoolkit::FlatFileSchemaResolver resolver{
sourcemeta::jsontoolkit::official_resolver};
for (const auto &schema_entry : configuration.at("schemas").as_object()) {
const auto collection_path{std::filesystem::canonical(
base / schema_entry.second.at("path").to_string())};
Expand Down Expand Up @@ -102,10 +98,12 @@ static auto index(const sourcemeta::jsontoolkit::JSON &configuration,
const auto relative_path{
std::filesystem::relative(entry.path(), collection_path).string()};
assert(!relative_path.starts_with('/'));
assert(!collection_base_uri_string.ends_with('/'));
std::ostringstream default_identifier;
default_identifier << collection_base_uri_string;
default_identifier << '/';
if (!collection_base_uri_string.ends_with('/')) {
default_identifier << '/';
}

default_identifier << relative_path;

const auto &current_identifier{resolver.add(entry.path(), default_dialect,
Expand Down Expand Up @@ -234,13 +232,19 @@ static auto index_main(const std::string_view &program,
sourcemeta::jsontoolkit::prettify(configuration_copy, stream);
stream << "\n";

const auto code{
index(configuration, configuration_path.parent_path(), output)};
sourcemeta::jsontoolkit::FlatFileSchemaResolver resolver{
sourcemeta::jsontoolkit::official_resolver};
const auto server_url{
sourcemeta::jsontoolkit::URI{configuration.at("url").to_string()}
.canonicalize()};
const auto code{index(resolver, server_url, configuration,
configuration_path.parent_path(), output)};

#ifdef SOURCEMETA_REGISTRY_ENTERPRISE
if (code == EXIT_SUCCESS) {
return sourcemeta::registry::enterprise::attach(
configuration, configuration_path.parent_path(), output);
resolver, server_url, configuration, configuration_path.parent_path(),
output);
}
#endif

Expand Down
1 change: 1 addition & 0 deletions test/cli/ee/index/directory-index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ cat << 'EOF' > "$TMP/index-schemas.json"
{
"name": "test.json",
"type": "schema",
"baseDialect": "draft7",
"url": "/example/schemas/test.json"
}
],
Expand Down

0 comments on commit f28911e

Please sign in to comment.