Code Monkey home page Code Monkey logo

json-ld-framing's Introduction

W3C Logo

JSON-LD 1.1

This is the repository of the W3C’s specification on JSON-LD 1.1 Framing, developed by the JSON-LD Working Group. The editors’ draft of the specification can also be read directly.

Feature Frozen

We are no longer accepting new feature requests for JSON-LD 1.1 drafts. Please limit issue topics to bugs and clarifications of the existing feature set.

https://www.w3.org/blog/2019/03/json-ld-collaborative-work-and-feature-timeline/

Contributing to the Repository

Use the standard fork, branch, and pull request workflow to propose changes to the specification. Please make branch names informative—by including the issue or bug number for example.

Editorial changes that improve the readability of the spec or correct spelling or grammatical mistakes are welcome.

Please read CONTRIBUTING.md, about licensing contributions.

Code of Conduct

W3C functions under a code of conduct.

json-ld-framing's People

Contributors

azaroth42 avatar bigbluehat avatar davidlehn avatar deniak avatar dependabot[bot] avatar dlongley avatar fsteeg avatar gkellogg avatar iherman avatar lanthaler avatar michaelcpuckett avatar pchampin avatar plehegar avatar ratmice avatar tidoust avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-ld-framing's Issues

Framing and @container:@set for scoped contexts

Playground: http://tinyurl.com/y4ry8o3m

With a very simple identity frame (e.g. give the top node's id and a context), the expected output would be to follow the context's definition for @container: @set and wrap single objects in an array. This works as expected for the context when applied via compaction (see the compaction tab in the playground).

However, in both the javascript and python implementations, the part property does not generate an array from the frame, where it does from compaction. Note that it is not due to Production within Production, as changing the class of either to (e.g.) Activity results in the same structure.

This seems like a bug?

Use a property several time when framing

We are trying to round trip json-ld with framing.

Our input json-ld document is:

{
  "@context": {
    "td": "http://my-url#",
    "name": "td:name",
    "properties": {
      "@id": "td:property",
      "@container": "@index",
      "@index": "name"
    }
  },
  "@id": "urn:toto",
  "@type": "td:Thing",
  "properties": {
    "myprop": {
      "td:prop1": "123",
      "name": "myprop"
    }
  }
}

We obtain the following triples:

<urn:toto> <http://my-url#property> _:b0 .
<urn:toto> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://my-url#Thing> .
_:b0 <http://my-url#name> "myprop" .
_:b0 <http://my-url#prop1> "123" .

On this way, everything is fine since the property "name" is used to generate a single triple.
When we want to frame these data to obtain the exact same json-ld document, the "name" property disappeared since it has been used as an "@Index".

In other words, we obtain this:

  "properties": {
    "myprop": {
      "td:prop1": "123"
    }
  }

And we would like to have this:

"properties": {
    "myprop": {
      "td:prop1": "123",
      "name": "myprop"
    }
  }

Do you know a way to define the frame (or the context) to use the property twice (as "@Index" and as an explicit key-value)?

playground example

Confusion regarding @default and @embed in JSON-LD 1.1?

In this json-ld playground example I believe the 5 @ids for the char property used to be returned given the displayed frame under JSON-LD 1.0 spec, but are dropped under the current spec for reasons I don't entirely understand. I think this has to do with the changed behavior of omitGraph? I am not sure how to update my frame.

I believe the reason has to do with duck typing and the presence of the states property under char in my frame. In this data, I'm not able to declare a specific type for the char object, which can sometimes contain the states property. I need the frame to assert that if it has the states property, it should use "@embed": "@never" so I cannot simply omit that assertion; even though that would in this example allow the char ids to display. I'd greatly appreciate clarification on the possible change in behavior between the spec and the best/right way to address the issue in this example.

Language map with global context

We are trying to round trip json-ld with framing.

Our input json-ld document is:

{
  "@context": [
    {
      "@language": "en"
    },
    {
      "title": {
        "@id": "dct:title"
      },
      "titles": {
        "@id": "dct:title",
        "@container": "@language"
      }
    }
  ],
  "title": "myTitle"
}

We obtain the following triple:

_:b0 <dct:title> "myTitle"@en .

When we try to frame the data back, with round tripping, we get this result :

{
  "@context": [
    {
      "@language": "en"
    },
    {
      "title": {
        "@id": "dct:title"
      },
      "titles": {
        "@id": "dct:title",
        "@container": "@language"
      }
    }
  ],
  "titles": {
    "en": "myTitle"
  }
}

You can observe that title is transformed into titles since the input triple contain a language tag. Even though the context contains a global @language. We would expect the output to be the same as the input. It means that if there is a global @language defined in the context, the value should be defined with title and not a language map.

jsonld playground

Possible typos

Hello from Tokyo.

I am translating the "JSON-LD 1.1 Framing" specification into Japanese now.
Thank you for the great specification!

I found some possible typos:

Sec. 5.1, "14.9)" might be unnecessary.
Sec. 5.2, "and" might be missing before "the JSON-LD 1.1 API".
Sec. D and E, a period might be missing after "defaulting to false".

Best regards,
KAMITSUNA Shuji,

Keywords for options

Why isn't there a keyword for all options systematically? There is @embed, @explicit (although I am not sure its choice is the best, but that is bike shedding), but there isn't any @omit-default, @omit-graph, @require-all.

I think the reason may be that if, say, requireAll is an API flag, then it is global and not per frame. However, if that is the reason, the question becomes: why can't those flags be frame specific?

Modify the fist sentence in section 1

In section 1. introduction,

A JSON-LD document is a representation of a directed graph.

It looks like a definition of JSON LD. But JSON LD is not also a representation of a directed graph, but also a representation of other Linked Data.
So, how about changing the first sentence like below :
A JSON-LD document can be used as a representation of a directed graph.

Provide an option for all terms to get a default "@container"

I would like to have all my relational data come back as arrays of IDs.

Right now I have to add the following to @context for each term:

      "foo": {
        "@container": "@set",
        "@type": "@id"
      },

I propose a processor option (similar to embed) that would allow a default container.

Can frames produce id maps?

I would like to use framing to produce an id map, but this does not seem to work very well with the JSON-LD processors I’ve tried.

Take for example the following graph:

{
  "@graph": [
    {
      "@id": "http://n2t.net/ark:/39333/ncg/dataset",
      "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag",
      "member": [
        "http://n2t.net/ark:/39333/ncg/place/NCG11248",
        "http://n2t.net/ark:/39333/ncg/place/NCG07554",
        "http://n2t.net/ark:/39333/ncg/place/NCG03755"
      ]
    },
    {
      "@id": "http://n2t.net/ark:/39333/ncg/place/NCG03755",
      "@type": "http://n2t.net/ark:/39333/ncg/type#Mountain",
      "county": "http://n2t.net/ark:/39333/ncg/place/NCG11248",
      "label": "Crawford Mountain"
    },
    {
      "@id": "http://n2t.net/ark:/39333/ncg/place/NCG07554",
      "@type": "http://n2t.net/ark:/39333/ncg/type#Community",
      "county": "http://n2t.net/ark:/39333/ncg/place/NCG11248",
      "label": "Ichley"
    },
    {
      "@id": "http://n2t.net/ark:/39333/ncg/place/NCG11248",
      "@type": "http://n2t.net/ark:/39333/ncg/type#County",
      "label": "Orange County",
      "description": "Not to be confused with Orange County, CA"
    }
  ],
  "@context": {
    "label": {
      "@id": "http://www.w3.org/2004/02/skos/core#label"
    },
    "description": {
      "@id": "http://www.w3.org/2004/02/skos/core#note"
    },
    "county": {
      "@id": "http://n2t.net/ark:/39333/ncg/vocab#county",
      "@type": "@id"
    },
    "member": {
      "@id": "http://www.w3.org/2000/01/rdf-schema#member",
      "@type": "@id"
    }
  }
}

And this frame:

{
  "@context": {
    "@base": "http://n2t.net/ark:/39333/ncg/place/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "ncv": "http://n2t.net/ark:/39333/ncg/vocab#",
    "nct": "http://n2t.net/ark:/39333/ncg/type#",
    "skos": "http://www.w3.org/2004/02/skos/core#",
    "records": {
      "@container": "@set",
      "@type": "@id",
      "@id": "rdfs:member"
    },
    "county": {
      "@container": "@set",
      "@type": "@id",
      "@id": "ncv:county"
    }
  },
  "@type": "rdf:Bag",
  "records": {
    "@id": {},
    "county": {
      "@embed": "@always",
      "@explicit": true,
      "skos:label": {}
    }
  }
}

Which produces:

{
  "@context": {
    "@base": "http://n2t.net/ark:/39333/ncg/place/",
    "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "ncv": "http://n2t.net/ark:/39333/ncg/vocab#",
    "nct": "http://n2t.net/ark:/39333/ncg/type#",
    "skos": "http://www.w3.org/2004/02/skos/core#",
    "records": {
      "@container": "@set",
      "@type": "@id",
      "@id": "rdfs:member"
    },
    "county": {
      "@container": "@set",
      "@type": "@id",
      "@id": "ncv:county"
    }
  },
  "@id": "../dataset",
  "@type": "rdf:Bag",
  "records": [
    {
      "@id": "NCG11248",
      "@type": "nct:County",
      "county": [],
      "skos:label": "Orange County",
      "skos:note": "Not to be confused with Orange County, CA"
    },
    {
      "@id": "NCG07554",
      "@type": "nct:Community",
      "county": [
        {
          "@id": "NCG11248",
          "@type": "nct:County",
          "skos:label": "Orange County"
        }
      ],
      "skos:label": "Ichley"
    },
    {
      "@id": "NCG03755",
      "@type": "nct:Mountain",
      "county": [
        {
          "@id": "NCG11248",
          "@type": "nct:County",
          "skos:label": "Orange County"
        }
      ],
      "skos:label": "Crawford Mountain"
    }
  ]
}

(See the above on the playground).

So far so good.

Now, I would like to change the records container from a @set to an @id map. But when I do that I get the error jsonld.SyntaxError: Invalid JSON-LD syntax; a JSON-LD frame must be a single object. (I’m not sure what that error means, since the frame is still a single object.)

Should this work? I can’t find any mention of id maps in the framing spec. Some simpler examples seem to work, but I can’t get anything to work that involves specifying anything (property matches or processing directives) below the level of the id map.

How to use specific value inside a frame to filter out credentials those do not contain that value

This is more of a question instead of an issue.

I was reading the doc here https://www.w3.org/TR/json-ld11-framing/#matching-on-values. In this section, the Frame "location": {"@value": {}, "@language": "el-Latn"}, was used to match the language from the following section
"location": [ {"@value": "Athens", "@language": "en"}, {"@value": "Αθήνα", "@language": "grc"}, {"@value": "Athína", "@language": "el-Latn"} ],

I was wondering if it is possible to define the frame like this "location": {"@value": "Athens", "@language": {}}, and whether it would return "location": {"@value": "Athens", "@language": "en"}, from the above location array.

And if I use a frame like this "location": {"@value": "Sydney", "@language": {}},, then it WILL NOT return anything from the above location array (something similar to a db query where we don't return the records those do not match the filter criteria)

Is my understanding correct? Can someone please advise on this?

Framing and Arrays

Framing Recommendation claims:

Framing is used to shape the data in a JSON-LD document, using an example frame document which is used to both match the flattened data and show an example of how the resulting data should be shaped.

This sounds to me as if JSON-LD-Parsing + JSON-LD-Framing may be meant to help with mapping back-and-forth between data models carrying semantically equivalent data but having chosen different syntactic models for it. At least this is a common problem I often see in practical data integration and data exchange scenarios. So I tried to test this hypothesis with a pretty simple example of putting the Library input data from the JSON-LD v1.1 Framing Recommendation into a different shape.

I began with this frame:

Frame

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@type": "Library",
  "contains": {}
}

It produces

Framed Output

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@id": "http://example.org/library",
  "@type": "Library",
  "contains": {
    "@id": "http://example.org/library/the-republic",
    "@type": "Book",
    "contains": {
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "Chapter",
      "description": "An introductory chapter on The Republic.",
      "title": "The Introduction"
    },
    "creator": "Plato",
    "title": "The Republic"
  },
  "location": "Athens"
}

Basically the output seems to me like just being a different way to render the tree model in the input @graph adjacency list. However the purpose was to map the input model onto some slightly different one. So what I looked for was a frame which maps the input model onto a model which chooses to have a books array and a chapters array rather than scalar contains properties:

Desired Framed output

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@id": "http://example.org/library",
  "@type": "Library",
  "books": [{
    "@id": "http://example.org/library/the-republic",
    "@type": "Book",
    "chapters": [{
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "Chapter",
      "description": "An introductory chapter on The Republic.",
      "title": "The Introduction"
    }],
    "creator": "Plato",
    "title": "The Republic"
  }],
  "location": "Athens"
}

However, this is the closest frame I could get to after hours of trial and error:

{
  "@context": {
    "@vocab": "http://example.org/",
    "books": {
      "@id": "contains",
      "@context": {
        "chapters": {
          "@id": "contains", 
          "@container": "@set"
        }
      }
    }
  },
  "@type": "Library",
  "contains": {}
}

It produces a result

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@id": "http://example.org/library",
  "@type": "Library",
  "books": {
    "@id": "http://example.org/library/the-republic",
    "@type": "Book",
    "chapters": [{
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "Chapter",
      "description": "An introductory chapter on The Republic.",
      "title": "The Introduction"
    }],
    "creator": "Plato",
    "title": "The Republic"
  },
  "location": "Athens"
}

which obviously misses the books array, though. So logically one would conclude: what's left missing is some "@container": "@set" in the mapping which maps "contains" onto "books". So let's do it:

That Frame should do it:

{
  "@context": {
    "@vocab": "http://example.org/",
    "books": {
      "@id": "contains",
      "@container": "@set",    // <= let's make books an array
      "@context": {
        "chapters": {
          "@id": "contains", 
          "@container": "@set"
        }
      }
    }
  },
  "@type": "Library",
  "contains": {}
}

Failed: for some reason now the output changes to

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@id": "http://example.org/library",
  "@type": "Library",
  "books": [{
    "@id": "http://example.org/library/the-republic",
    "@type": "Book",
    "books": [{
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "Chapter",
      "description": "An introductory chapter on The Republic.",
      "title": "The Introduction"
    }],
    "creator": "Plato",
    "title": "The Republic"
  }],
  "location": "Athens"
}

wiping out chapters. That's where I gave up. I know this is not a support forum, but after so much time spent on a dozen different frames I am not even sure anymore the recommendation provides any solution to that problem. If so, what's the solution I don't see? Or is this just a nasty bug in json-ld.js used on the JSON-LD playground?

Thanks in advance for any response.

Add more framing examples

  • value pattern matching (wildcarding/match none)
  • match none
  • @included
  • Use of scoped contexts
  • merged vs default graph framing
  • match on @id

Framing blank node unnamed graphs

I'm trying to create an "identity frame" for some data that uses "@container": "@graph". The data looks like this:

{
  "@context": {
    "@version": 1.1,
    "id": "@id",
    "claim": {"@id": "ex:claim", "@container": "@graph"},
    "name": "ex:name",
    "proof": {"@id": "ex:proof", "@type": "@id", "@container": "@graph"},
    "signer": {"@id": "ex:signer", "@type": "@id"},
    "subject": {"@id": "ex:subject", "@type": "@id"},
    "knows": {"@id": "ex:knows", "@type": "@id"}
  },
  "id": "ex:cred",
  "issuer": {
    "id": "ex:issuer",
    "name": "Foo"
  },
  "subject": {
    "id": "ex:subject",
    "name": "the subject",
    "knows": {
      "id": "ex:issuer",
      "name": "Someone else"
    }
  },
  "proof": {
    "@type": "ex:Proof",
    "name": "the proof",
    "signer": {
      "id": "ex:subject",
      "name": "something different"
    }
  }
}

And the frame like this:

{
  "@context": {
    "@version": 1.1,
    "id": "@id",
    "claim": {"@id": "ex:claim"},
    "name": "ex:name",
    "proof": {"@id": "ex:proof", "@type": "@id"},
    "signer": {"@id": "ex:signer", "@type": "@id"},
    "subject": {"@id": "ex:subject", "@type": "@id"},
    "knows": {"@id": "ex:knows", "@type": "@id"}
  },
  "subject": {
    "@embed": "@always"
  },
  "proof": {}
}

A link to the playground is here: http://tinyurl.com/yaewmkk5

The goal is for the output to match the input, but it does not. Does anyone know what tweaks are necessary to accomplish this? Do we have proper support for framing blank node named graphs? From looking at the jsonld.js implementation, it seemed like only non-blank node named graphs were supported... and the spec doesn't seem to give any examples with blank nodes. It seems we have both a spec and an implementation gap here. If not, could someone share a working example?

requireAll does not require @type and should

From discussion on the mailing list, it was noted that the requireAll flag does not actually require all, it requires everything other than @id and @type.

The proposal arising is to make it actually require all of the asserted features, including @type and @id.

Consistent use of the 'informative' class

For a more general discussion, see w3c/json-ld-syntax#294.

If we make section §1.4 Terminology informative (as proposed in the syntax document),
we need to lowercase the two MUSTs in §1.4.1.

I think this is safe, because I'm assuming those constraints are enforced by the algorithms, which are normative.

Explore supporting `"@embed": "@first"`

My understanding is that the use of @last is intended to ensure that all data related to whatever a frame filters on is not omitted (or duplicated) from the result of a framing operation. The embed location ("last") is actually not important. One use case for this feature is framing subgraphs in JSON-LD documents prior to verifying digital signatures on them.

This form of embedding was the only type available when framing was invented: the choice was to embed this way or not to embed at all; @always came later. I can't remember a good reason why the choice was made to place the only embed for a node wherever it is referenced "last" -- and at this point it feels arbitrary. Certainly the framing user doesn't care because they can't know where "last" is a priori. In fact, in some implementations, the keyword @once was used before @last was adopted instead.

If the case is that it is arbitrary, using "last" clearly has some drawbacks that might be avoided if we supported @first instead for this use case. Using @last requires some post processing that removes previous embeds to ensure that only the last one is used. This is costly in current implementations. I would think that using @first would cause all subsequent occurrences to just use a reference and to add any additional data collected to the first embedded node object, eliminating the need for any post processing.

Of course, not having looked into the framing algorithms in a while, this could also be naive. Therefore, I recommend that implementers (such as me) explore @first as it may be the case that existing implementations can be very easily adapted to support it -- and its simplicity could address a number of issues (for example: performance). If nothing else, a good explanation for why "last" was chosen should come out of this and could be placed into the spec.

Note: The first public description of framing I could find did not help me remember anything: https://lists.w3.org/Archives/Public/public-linked-json/2011Aug/0078.html

Recursion catch fails at top level

The following graph produces what I believe is incorrect output in both PyLD and the Ruby Distiller:

<https://example.org/what> <https://example.org/ns/sameAs> <https://example.org/what> .
<https://example.org/what> <https://example.org/ns/age> "42"^^<http://www.w3.org/2001/XMLSchema#integer> .
parsed = from_rdf(what, {'format': 'application/nquads', 'useNativeTypes': True})
framing = {
    "@context": context,
    "@id": "https://example.org/what"
}
js = frame(parsed, framing)

js is now, with the obvious context:

    {
      "id": "https://example.org/what",
      "age": 42, 
      "sameAs": {
        "id": "https://example.org/what",
        "age": 42, 
        "sameAs": "https://example.org/what"
      }
    }

I would have expected:

    {
      "id": "https://example.org/what",
      "age": 42, 
      "sameAs":  "https://example.org/what"
    }

Reframing Relationships

I have the following data structure:

{
  "@context": {
    "ex": "http://example.org/",
    "exv": "http://example.org/vocab#",
    "exv:source": {"@type": "@id"},
    "exv:target": {"@type": "@id"}
  },
  "@graph": [
  { "@id": "ex:relationship-12345",
    "@type": "exv:Relationship",
    "exv:relationshipType": {"@id": "exv:created"},
    "exv:source": {
      "@id": "ex:actor-23456",
      "@type": "exv:Actor",
      "exv:description": "Some odd actor."
    },
    "exv:target": {
      "@id": "ex:event-34567",
      "@type": "exv:Event",
      "exv:description": "Some odd event."
    }
  }]
}

I would like to restructure it as:

{
  "@context": {
    "ex": "http://example.org/",
    "exv": "http://example.org/vocab#",
    "exv:source": {"@type": "@id"},
    "exv:target": {"@type": "@id"}
  },
  "@graph": [
  { "@id": "ex:actor-23456",
    "@type": "exv:Actor",
    "exv:description": "Some odd actor.",
    "exv:created": {
      "@id": "ex:event-34567",
      "@type": "exv:Event",
      "exv:description": "Some odd event."
    }
  },
  { "@id": "ex:relationship-12345",
    "@type": "exv:Relationship",
    "exv:source": "ex:actor-23456",
    "exv:relationshipType": {"@id": "exv:created"},
    "exv:target": "ex:event-34567"
  }]
}

In other words, the structure can be viewed as reifed data where:

exv:Relationship subclass of rdf:Statement
exv:source subproperty of rdf:subject
exv:relationshipType subproperty of rdf:predicate
exv:target subproperty of rdf:object

and I need to instantiate its triple:
ex:actor-23456 -- exv:created --> ex:event-34567

Some framing issues are:

  1. Referencing the value of a property for later use, like the "exv:relationshipType" value.
  2. Using a referenced value as a property, like the value of "exv:relationshipType" used as the property of the "exv:source" value.
  3. Matching node patterns like "ex:relationship-" + variable info
    It seems wildcard matching is an all or nothing affair: match specific IRIs, everything {}, or nothing [], but not generic string matching. It would be useful for the frame matching to use regex patterns like "ex:relationship-.+". This is helpful when I don't have @type, but can create type based on the @id match.

Then, I can validate some pattern while framing. The framing could be:

{
  "@context": {
    "ex": "http://example.org/",
    "exv": "http://example.org/vocab#",
    "exv:source": {"@type": "@id"},
    "exv:target": {"@type": "@id"}
  },
  "@graph": [
  { "@requireAll": true,
    "@id": {"@regex": "ex:relationship-.+"},      <-- verifies a proper string match for a Relationship
    "@type": {"@default": "exv:Relationship"},    <-- new type if it doesn't exist
    "exv:relationshipType": {"@id": ?prop},       <-- reference for property
    "exv:source": {
      ?prop: {"@default": {"@id": ?obj}}          <-- new key-value pair
    },
    "exv:target": {"@id": ?obj},                  <-- reference for value, will order matter (target before source)?
  }]
}

to produce:

{
  "@context": {
    "ex": "http://example.org/",
    "exv": "http://example.org/vocab#",
    "exv:source": {"@type": "@id"},
    "exv:target": {"@type": "@id"}
  },
  "@graph": [
  { "@id": "ex:relationship-12345",
    "@type": "exv:Relationship",
    "exv:relationshipType": {"@id": "exv:created"},
    "exv:source": {
      "@id": "ex:actor-23456",
      "@type": "exv:Actor",
      "exv:description": "Some odd actor.",
      "exv:created": "ex:event-34567"             <------ new key-value pair 
    },
    "exv:target": {
      "@id": "ex:event-34567",
      "@type": "exv:Event",
      "exv:description": "Some odd event."
    }
  }]
}

Yeah, I hate it too. It looks ugly, but I currently don't see a way around it.

Allow class-scoped framing

It would be useful to allow individual classes to have their own frames, such that a class which can appear at many points in the structure can be defined only once and then the definition inherited.

For example, a class like Type / Concept / Tag might appear anywhere in a structure associated with any other class. Currently (I believe) you would need to define all possible structures to ensure that the Type was framed consistently.

Ex. 41 Playground doesn't contain `@omitGraph: false` + playground does not apply `@omitGraph`

Example 41 on the document has the following description: EXAMPLE 41: Framed library objects with @omitGraph set to false, which indeed has the correct result output on the document.

However, upon clicking on "Open in playground" the frame does not contain the property @omitGraph. Interestingly the result is correct, i.e. contains @graph.

The playground has the following frame, note that @omitGraph is missing:

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@type": "Library",
  "contains": {
    "@type": "Book",
    "contains": {
      "@type": "Chapter"
    }
  }
}

and the following output:

{
  "@graph": [
    {
      "@id": "http://example.org/library",
      "@type": "http://example.org/Library",
      "http://example.org/contains": {
        "@id": "http://example.org/library/the-republic",
        "@type": "http://example.org/Book",
        "http://example.org/contains": {
          "@id": "http://example.org/library/the-republic#introduction",
          "@type": "http://example.org/Chapter",
          "http://example.org/description": "An introductory chapter on The Republic.",
          "http://example.org/title": "The Introduction"
        },
        "http://example.org/creator": "Plato",
        "http://example.org/title": "The Republic"
      },
      "http://example.org/location": "Athens"
    },
    {
      "@id": "http://example.org/library/the-republic",
      "@type": "http://example.org/Book",
      "http://example.org/contains": {
        "@id": "http://example.org/library/the-republic#introduction",
        "@type": "http://example.org/Chapter",
        "http://example.org/description": "An introductory chapter on The Republic.",
        "http://example.org/title": "The Introduction"
      },
      "http://example.org/creator": "Plato",
      "http://example.org/title": "The Republic"
    },
    {
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "http://example.org/Chapter",
      "http://example.org/description": "An introductory chapter on The Republic.",
      "http://example.org/title": "The Introduction"
    }
  ]
}

But if one touches the frame and initiates a recompilation e.g. by adding a space and removing, the output does not have @graph anymore. So the following output is generated:

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@id": "http://example.org/library",
  "@type": "Library",
  "contains": {
    "@id": "http://example.org/library/the-republic",
    "@type": "Book",
    "contains": {
      "@id": "http://example.org/library/the-republic#introduction",
      "@type": "Chapter",
      "description": "An introductory chapter on The Republic.",
      "title": "The Introduction"
    },
    "creator": "Plato",
    "title": "The Republic"
  },
  "location": "Athens"
}

I wasn't also able to apply the @omitGraph rule by manually adding it to the frame. I might be placing the property in the wrong place but the following frame produced an output without a @graph.

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@omitGraph": false,
  "@type": "Library",
  "contains": {
    "@type": "Book",
    "contains": {
      "@type": "Chapter"
    }
  }
}

Several frames in the same frame document?

Looking at 2.3.1 I tested the core library example of the document on playground with the following frame

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@graph" : [
      {
        "@type": "Library",
        "contains": {
            "@type": "Book",
            "@embed": "@never"
        }
      },
      {
        "@type": "Book",
        "contains": {
            "@type": "Chapter",
            "@embed": "@last"
        }
      }
  ]
}

And I got the reply that a frame document must have only one frame object.

O.k., playground is playing per spec, but I was a bit surprised: why can't I have a frame like the one above? In the result, the 'library' would just list the books by ID, and the rest of the graph would include each book separately, including the relevant chapters. Isn't that a viable use case?

Fix invalid WebIDL

From #135

The JSON-LD Framing API specification extends interfaces of the JSON-LD API but does not use the partial extension keyword, meaning that interfaces from both specs cannot be automatically merged into one.

The JSON-LD Framing API specification also re-defines interfaces that are already defined in the JSON-LD API for no apparent reason, which is bad practice as it creates two normative definitions of the same object.

This update makes the following changes to drop duplicate definitions and improve cross-reference links between the JSON-LD Framing API and the JSON-LD API:

  • Dropped duplicate definition of JsonLd interface
  • Defined JsonLdProcessor as partial (and dropped constructor member since it is already defined in the JSON-LD API)
  • Dropped duplicate definitions of JsonLdRecord and JsonLdInput
  • Defined JsonLdOptions as partial (and dropped ordered since it is already defined in the JSON-LD API)
  • Replaced data-cite links with {{xx}} links where possible
  • Dropped self-reference from xref ReSpec config array (useless, local definitions are always available)

cc/@tidoust

Pattern Matching

Modify the "Value Pattern Matching Algorithm" to match on regular expressions.

NOTE: I've split this off from #73 as I believe this is a useful framing issue on its own.

From the framing specification:

4.3 Value Pattern Matching Algorithm

The Value Pattern Matching Algorithm is used as part of the Framing and Frame Matching algorithms. A value object matches a value pattern using the match none and wildcard patterns on @value, @type, and @language, in addition to allowing a specific value to match a set of values defined using the array form for each value object property.

It seems matching is an all or nothing affair: match anything {}, nothing [], or everything (a specific value). There is no middle ground for generic string matching. It would be useful for matching to use regex patterns. Example:

"ex:relationship-.+"

This is helpful for a wide range of use cases. For example, when there is no @type in the input, but the @id may contain information that can be used to infer type, then a partial string match within the @id can identify the default type. It can be very useful for matching on properties (2.1.1). Then, 4.3 Value Pattern Matching Algorithm becomes much more robust.

RELATED:
The JSON Schema specification that uses the pattern keyword for regular expressions:
https://json-schema.org/understanding-json-schema/reference/regular_expressions.html

OWL2 also reserves xsd:pattern for regex and uses it in restrictions.

PROPOSITION: Extend JSON-LD Framing with the @pattern keyword.

[FRAME]
{
  "@context": {"@vocab": "http://example.org/"},
  "@id": {"@pattern": ".*\/[Ll]ibrary\/.*"},
  "@type": {"@default": "Library"},
  "contains": {
    "@id": {"@pattern": ".*\/[Bb]ook\/.*"},
    "@type": {"@default": "Book"},
    "contains": {
      "@id": {"@pattern": ".*\/[Cc]hapter\/.*"}
      "@type": {"@default": "Chapter"}
    }
  }
}

@pattern should accept an array of patterns.

[FRAME]
{
  "@context": {"@vocab": "http://example.org/"},
  "@id": {"@pattern": [
    ".*\/[Ll]ibrary\/.*",
    ".*\/[Aa]thenaeum\/.*",
    ".*\/[Bb]ook_?[Cc]ollection\/.*"]
  }
  "@type": {"@default": "Library"},
  "contains": {
    "@id": {"@pattern": ".*\/[Bb]ook\/.*"},
    "@type": {"@default": "Book"},
    "contains": {
      "@id": {"@pattern": ".*\/[Cc]hapter\/.*"}
      "@type": {"@default": "Chapter"}
    }
  }
}

or we could just use regex or'ing, |, but it might be nice to include such constructs.

[FRAME]
...
  "@id": {"@pattern": ".*\/([Ll]ibrary|[Aa]thenaeum|[Bb]ook_?[Cc]ollection)\/.*"}
...

How about matching property names, not just the values? Then, 2.1 Framing becomes much more robust and we can do some interesting things like shaping based on property patterns. In the following case, typing based on property patterns and relations:

[FRAME]
{
  "@context": {"@vocab": "http://example.org/"},
  "@type": {"@default": "Library"},
  "location": {"@pattern": "[Aa]thens(, (Greece|Tennesee, USA))?"},
  "contains": [
    {
      "@type": {"@default": "Book"},
      {"@pattern": ".*([Cc]reator|[Aa]uthor).*"}: {},
      "contains": {
        "@id": {"@pattern": ".*\/[Cc]hapter\/.*"},
        "@type": {"@default": "Chapter"}
      }
    },
    {
      "@type": {"@default": "Periodical"},
      {"@pattern": ".*([Cc]reator|[Pp]ublisher).*"}: {},
      "contains": {
        "@id": {"@pattern": ".*\/[Aa]rticle\/.*"},
        "@type": {"@default": "Article"}
      }
    }
  ]
}

Framing on nested graphs

Hi wonderful people from the JSON-LD Framing group!

I have a question regarding framing on nested JSON-LD data.

Background

My question is in relation to Verifiable Credentials. I'm a maintainer of an open source credential wallet. We are now starting with the implementation of the new OIDC4VCI which supports a flow where the Issuer can ask the Holder for proof of ownership of a credential (in the form of a presentation). This can be done by the DIF Presentation exchange. In there is a Future which allows the Relying Party to query by 'frame': https://identity.foundation/presentation-exchange/#json-ld-framing-feature.
This is I think so much more elegant than the json-schema filters. Since all of our credentials are in JSON-LD anyway, it seems the way to go. But I'm running into issues here.

Assumption

One can use JSON-LD framing to "query" over a set over credentials, stored as a list of graphs.

Problem

I would like to use framing to query a set of Verifiable Credentials. I made a simpler example to illustrate the problem:
Input:

{
  "@context":{
    "@vocab":"http://example.org#",
    "schema":"http://schema.org/"    
  },
  "@graph":[
    {
      "@type":["Type1", "Type2"],
      "schema:name":"John"
    },
    {
      "@type":["Type2"],
      "schema:name":"John"
    },
    {
      "@type":["Type1", "Type2"],
      "schema:name":"John",
      "schema:address": {
        "@id":"uri:1",
        "schema:street":"Oneway"
      }
    },
    {
      "@type":["Type1", "Type3"],
      "schema:name":"John",
      "schema:address": {
        "@id":"uri:2",
        "schema:street":"Middleroad"
      }
    }
  ]
}

I want to query for a "credential" of Type1, name is John and address with street Oneway:

Frame:

{
  "@context":{
    "@vocab":"http://example.org#",
    "schema":"http://schema.org/"
  },
  "@type": ["Type1"],
  "schema:name": "John",
  "schema:address":{
    "schema:street":"Oneway",
    "@requireAll": true
  },
  "@requireAll": true
}

This is the output I get from the JSON-LD Playground:

{
  "@context": {
    "@vocab": "http://example.org#",
    "schema": "http://schema.org/"
  },
  "@graph": [
    {
      "@type": [
        "Type1",
        "Type2"
      ],
      "schema:address": {
        "@id": "uri:1",
        "schema:street": "Oneway"
      },
      "schema:name": "John"
    },
    {
      "@type": [
        "Type1",
        "Type3"
      ],
      "schema:address": null,
      "schema:name": "John"
    }
  ]
}

As you can see, the address of the second entry is null. I expected the result not to have this entry at all. That is also what happens when I frame on @id:

Input on @id:

{
  "@context":{
    "@vocab":"http://example.org#",
    "schema":"http://schema.org/"
  },
  "@type": ["Type1"],
  "schema:name": "John",
  "schema:address":{
    "@id":"uri:1"
  },
  "@requireAll": true
}

Output:

{
  "@context": {
    "@vocab": "http://example.org#",
    "schema": "http://schema.org/"
  },
  "@type": [
    "Type1",
    "Type2"
  ],
  "schema:address": {
    "@id": "uri:1",
    "schema:street": "Oneway"
  },
  "schema:name": "John"
}

So my questions are:

  1. Is my assumption correct?
  2. What is the difference of framing by @id and framing by value?
  3. If this is the expected behavior, is framing the logical mechanism to use in the DIF presentation exchange?
  4. Could it be that there is an example missing from the spec which gives more clarity about framing in nested structures?

Thanks for taking the time to look at this issue!

Change "Lexicographical Order" (and related) to "Unicode code point order".

This was raised against another spec in w3c/rdf-canon#18, and a similar change should be made here and in Framing. Note that this shouldn't affect any actual test results.

The definition from rdf-canon is the following:

Unicode code point order
This refers to determining the order of two Unicode strings (A and B), using Unicode Codepoint Collation, as defined in [XPATH-FUNCTIONS], which defines a total ordering of strings comparing code points.

Also defines other terms related to "lexical".

See w3c/json-ld-api#552.

Default value for @type

Currently, @type cannot accept @default in the playground. For framing, the documentation seems to indicate that @type (a keyword) must be a definitive resource for matching and not definable.

So, how is type added via framing?

I assume the answer would be either:

  1. "@type": {"@default": "ex:Book"}
  2. "@type": {"@default": {"@id": "ex:Book"}}

Since "@type": "@id" is the usual specification, 2 seems redundant.

NOTE: I know, I've bugged about this quite a bit in the main JSON-LD area. Since framing was proposed as the solution, I'm officially posting the issue here.

Frame Matching & Blank Nodes

The current draft for JSON-LD framing (January 2018) does not mention blank nodes in the frame matching algorithm specification and a strict interpretation of the first test goes a bit against the semantics of RDF in case a frame includes blank nodes:

1 Node matches if it has an @id property value which is also a value of the @id property in frame.

According to its definition, a frame is a JSON-LD document, meaning it can include blank nodes. if it happens, blank nodes in the frame will match blank nodes in a document only if they have the same ID and I believe that the Ruby implementation performs simple string comparison.

In RDF, shared blank nodes require a special handling and we loose that specificity here. It would be good to either redefine JSON-LD frames such that blank nodes are not allowed or precise the specification of frame matching. I would be in favor of the latter approach.

Blank nodes in JSON-LD frames might be useful when nodes have multiple relations to each other. For instance, nodes matching the following frame represent all alumni of a university who still work for that university:

{
  "@context": "http://schema.org",
  "@type": "Person",
  "alumniOf": {
    "@id": "_:univ",
    "@type": "CollegeOrUniversity"
  },
  "worksFor": { "@id": "_:univ" }
}

Original issue json-ld/json-ld.org#579.

Remove @omitDefault?

The @omitDefault flag can be added to a frame to change the default value for the omit default flag, which might be set to true through an API call. This keyword is of dubious value, since the frame can simply add @default at all.

Propose removing the keyword. We may also want to consider how important the runtime flag is.

(Editorial) visually separate the different examples?

At the moment, the document uses example boxes for the frames, the raw JSON-LD, and the processed/shaped JSON-LD. Because they are all JSON-LD, it is difficult for first time readers to easily distinguish among these three different roles. It would be very helpful, IMHO, if we used three different styles (probably the simplest is to use a different background colors) for the three cases.

Possible bug with `@json` being treated as invalid `type` in frame

This issue stems from: digitalbazaar/jsonld.js#506

It relates to step 1.3 in the Framing Algorithm where a frame's validity is being checked.

It seems that either that step doesn't appropriately allow for @json (which is a valid JSON-LD type) or that the algorithm should have stopped recursing when @json was detected and just accepted whatever the value was (since it cannot recurse into @json datatypes, presumably). I didn't look more closely to determine which way to go here with the algorithm (whether it's the former simple fix or not), but I expect that some test cases could help shake it out.

infinite recursion in @reverse properties

From json-ld/json-ld.org#653

It would be nice to have the same possiblity of infinite recursion in the @reverse properties as there are in non-reverse ones (example), currently recursion only works as many times as the frame defines it (example).

Copy/pasting the examples (and removing @contexts):

in the working case, I have

{
  "@graph": [
    {
      "@id": "bdr:O9TAXTBRC201605",
      "@type": "Taxonomy",
      "taxHasSubClass": [
        {
          "@id": "bdr:O9TAXTBRC201605_0001"
        },
        {
          "@id": "bdr:O9TAXTBRC201605_0010"
        }
      ]
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0001",
      "@type": "Taxonomy",
      "taxHasSubClass": {
        "@id": "bdr:O9TAXTBRC201605_0002"
      }
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0002",
      "@type": "Taxonomy"
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0010",
      "@type": "Taxonomy"
    }
  ]
}

and frame

{ 
  "@id" : "bdr:O9TAXTBRC201605",
  "@context" : {
    "children": { "@reverse": "http://purl.bdrc.io/ontology/core/taxSubclassOf" }, 
    "taxSubclassOf" : {
      "@id" : "http://purl.bdrc.io/ontology/core/taxSubclassOf",
      "@type" : "@id"
    },
    "@vocab" : "http://purl.bdrc.io/ontology/core/",
    "bdr" : "http://purl.bdrc.io/resource/"
  }
}

that produces the nice

{
  "@graph": [
    {
      "@id": "bdr:O9TAXTBRC201605",
      "@type": "Taxonomy",
      "taxHasSubClass": [
        {
          "@id": "bdr:O9TAXTBRC201605_0001",
          "@type": "Taxonomy",
          "taxHasSubClass": {
            "@id": "bdr:O9TAXTBRC201605_0002",
            "@type": "Taxonomy"
          }
        },
        {
          "@id": "bdr:O9TAXTBRC201605_0010",
          "@type": "Taxonomy"
        }
      ]
    }
  ]
}

but for the opposite:

{
  "@graph": [
    {
      "@id": "bdr:O9TAXTBRC201605",
      "@type": "Taxonomy"
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0001",
      "@type": "Taxonomy",
      "taxSubclassOf": "bdr:O9TAXTBRC201605"
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0002",
      "@type": "Taxonomy",
      "taxSubclassOf": "bdr:O9TAXTBRC201605_0001"
    },
    {
      "@id": "bdr:O9TAXTBRC201605_0010",
      "@type": "Taxonomy",
      "taxSubclassOf": "bdr:O9TAXTBRC201605"
    }
  ]
}

and the frame

{
  "@id": "bdr:O9TAXTBRC201605",
  "@context": {
    "children": {
      "@reverse": "http://purl.bdrc.io/ontology/core/taxSubclassOf"
    },
    "taxSubclassOf": {
      "@id": "http://purl.bdrc.io/ontology/core/taxSubclassOf",
      "@type": "@id"
    },
    "@vocab": "http://purl.bdrc.io/ontology/core/",
    "bdr": "http://purl.bdrc.io/resource/"
  },
  "children": {}
}

I'm not getting all the recursion, only

{
  "@graph": [
    {
      "@id": "bdr:O9TAXTBRC201605",
      "children": [
        {
          "@id": "bdr:O9TAXTBRC201605_0001",
          "@type": "Taxonomy",
          "taxSubclassOf": "bdr:O9TAXTBRC201605"
        },
        {
          "@id": "bdr:O9TAXTBRC201605_0010",
          "@type": "Taxonomy",
          "taxSubclassOf": "bdr:O9TAXTBRC201605"
        }
      ],
      "@type": "Taxonomy"
    }
  ]
}

(Mostly) Editorial issues Part I

  • I think adding the same choice of example syntaxes as in the syntax document would be good (for the framing results).
  • 2.3.1. It is a bit unclear why one has to use the value of "@last" and "@never" rather than using boolean values. Those two terms do not look very intuitive for me...
  • 2.3.2, first paragraph: for the purpose of readability I would switch the last two sentences.
  • Last sentence of 2.3.2: "fram" -> "frame"
  • An example for the omit default flag should be added to to 2.3.3.

how to use the `frame` and `framed` profiles?

#132 cites the text of two specs regarding frame and framed profiles:

https://www.w3.org/TR/json-ld11-framing/#iana-considerations:

http://www.w3.org/ns/json-ld#framed
To specify a JSON-LD Frame.
The http://www.w3.org/ns/json-ld#framed SHOULD be used when serving and requesting a JSON-LD frame document.

https://w3c.github.io/json-ld-syntax/#application-ld-json

This specification defines six values for the profile parameter.
http://www.w3.org/ns/json-ld#frame
To request or specify a JSON-LD frame document.
http://www.w3.org/ns/json-ld#framed
To request or specify framed JSON-LD document form.

The third spec https://w3c.github.io/json-ld-api/, as far as I can see, does not specify where the frame and context parameters come from in HTTP exchange.


So it would be nice to give some examples on correct use of HTTP headers regarding the use of specific context and frame.
From what I could glean by googling (please comment whether that's correct!)

REQUEST

I1. To request a particular profile/context for jsonld,
according to https://www.rubydoc.info/gems/triannon#get-a-particular-anno:

Accept: application/ld+json; profile="http://www.w3.org/ns/oa-context-20130208.json"
Accept: application/ld+json; profile="http://iiif.io/api/presentation/2/context.json"

I2. To request a particular context for "jsonld as json" (note: type pertains to the context document, not the payload document):

Accept: application/json
Link: http://www.w3.org/ns/oa.json; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"

I3. To request jsonld with a particular context and frame

Accept: application/ld+json; profile="http://www.w3.org/ns/json-ld#framed"
Link: http://example.org/context.jsonld; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"
Link: http://example.org/frame.jsonld;   rel="http://www.w3.org/ns/json-ld#frame";   type="application/ld+json"

RESPONSE

O1. jsonld as json with a particular context:

Content-Type: application/json
Link: https://example.org/context.jsonld; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"

O2. jsonld that is framed and uses a particular context (the Links are redundant)

Content-Type: application/ld+json; profile="http://www.w3.org/ns/json-ld#framed"
Link: http://example.org/context.jsonld; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"
Link: http://example.org/frame.jsonld;   rel="http://www.w3.org/ns/json-ld#frame";   type="application/ld+json"

O3. jsonld that uses a particular context,
according to https://iiif.io/api/presentation/3.0/#63-responses:

Content-Type: application/ld+json;profile="http://iiif.io/api/presentation/3/context.json"

Questions

  • Q1. Is profile used to specify the kind of jsonld (eg framed, compacted, expanded),
    • or the context (i.e. are the iiif and triannon examples wrong?)
  • Q2. Can one use multiple Link headers as per I3, O2?
  • Q3. (!) How can one specify which version to fetch, 1.0 or 1.1? The version may have significant performance impact, at least for Java-based repos, because jsonld-java (old) supports only 1.0 but is 4.6x faster than titanium (new) that supports 1.1: eclipse-rdf4j/rdf4j#3654

"Framing" is an unfortunate choice of verb

In reviewing the 1.1 spec I was surprised to discover that "framing" is not the process of surrounding JSON-LD data with a "frame". In my experience this is the most common definition of framing in a technical context.

i.e. Using special delimiters or length prefixes around a chunk of data that "frames" that data and differentiates one chunk from another when streamed between processes.

This is the definition I am accustomed to and I wonder if I am alone in being surprised that JSON-LD framing appears to be used to define a structure as opposed to a frame.

Correction for 2.3.2 Explicit inclusion flag

The documentation for the exclusion flag lists Example 12 with the pair "creator": "Plato",. However, the exclusion flag should have removed this pair. The playground produces the following corrected output on the Example 3 input and Example 11 framing:

{
  "@context": {
    "@vocab": "http://example.org/"
  },
  "@graph": [
    {
      "@id": "http://example.org/library",
      "@type": "Library",
      "contains": {
        "@id": "http://example.org/library/the-republic",
        "@type": "Book",
        "contains": {
          "@id": "http://example.org/library/the-republic#introduction",
          "@type": "Chapter",
          "description": "An introductory chapter on The Republic.",
          "title": "The Introduction"
        },
        "title": "The Republic"
      },
      "description": null
    }
  ]
}

IANA profile should be `frame` not `framed`

https://www.w3.org/TR/json-ld11-framing/#iana-considerations:

http://www.w3.org/ns/json-ld#framed
To specify a JSON-LD Frame.
The http://www.w3.org/ns/json-ld#framed SHOULD be used when serving and requesting a JSON-LD frame document.

https://w3c.github.io/json-ld-syntax/#application-ld-json

This specification defines six values for the profile parameter.
http://www.w3.org/ns/json-ld#frame
To request or specify a JSON-LD frame document.
http://www.w3.org/ns/json-ld#framed
To request or specify framed JSON-LD document form.

  • I think that in json-ld11-framing, the correct profile to use is frame not framed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.