GithubHelp home page GithubHelp logo

rubensworks / rdfa-streaming-parser.js Goto Github PK

View Code? Open in Web Editor NEW
19.0 5.0 5.0 728 KB

A fast and lightweight streaming RDFa parser for JavaScript

License: MIT License

TypeScript 98.87% JavaScript 1.13%
rdf rdfa linked-data rdfjs parser streaming hacktoberfest

rdfa-streaming-parser.js's Introduction

RDFa Streaming Parser

Build status Coverage Status npm version

A fast and lightweight streaming and 100% spec-compliant RDFa 1.1 parser, with RDFJS representations of RDF terms, quads and triples.

The streaming nature allows triples to be emitted as soon as possible, and documents larger than memory to be parsed.

Installation

$ npm install rdfa-streaming-parser

or

$ yarn add rdfa-streaming-parser

This package also works out-of-the-box in browsers via tools such as webpack and browserify.

Require

import {RdfaParser} from "rdfa-streaming-parser";

or

const RdfaParser = require("rdfa-streaming-parser").RdfaParser;

Usage

RdfaParser is a Node Transform stream that takes in chunks of RDFa data, and outputs RDFJS-compliant quads.

It can be used to pipe streams to, or you can write strings into the parser directly.

While not required, it is advised to specify the profile of the parser by supplying a contentType or profile constructor option.

Print all parsed triples from a file to the console

const myParser = new RdfaParser({ baseIRI: 'https://www.rubensworks.net/', contentType: 'text/html' });

fs.createReadStream('index.html')
  .pipe(myParser)
  .on('data', console.log)
  .on('error', console.error)
  .on('end', () => console.log('All triples were parsed!'));

Manually write strings to the parser

const myParser = new RdfaParser({ baseIRI: 'https://www.rubensworks.net/', contentType: 'text/html' });

myParser
  .on('data', console.log)
  .on('error', console.error)
  .on('end', () => console.log('All triples were parsed!'));

myParser.write('<?xml version="1.0"?>');
myParser.write(`<!DOCTYPE html>
<html>

<head prefix="foaf: http://xmlns.com/foaf/0.1/">`);
myParser.write(`<link rel="foaf:primaryTopic foaf:maker" href="https://www.rubensworks.net/#me" />`);
myParser.write(`</head>`);
myParser.write(`<body>`);
myParser.write(`</body>`);
myParser.write(`</html>`);
myParser.end();

Import streams

This parser implements the RDFJS Sink interface, which makes it possible to alternatively parse streams using the import method.

const myParser = new RdfaParser({ baseIRI: 'https://www.rubensworks.net/', contentType: 'text/html' });

const myTextStream = fs.createReadStream('index.html');

myParser.import(myTextStream)
  .on('data', console.log)
  .on('error', console.error)
  .on('end', () => console.log('All triples were parsed!'));

Configuration

Optionally, the following parameters can be set in the RdfaParser constructor:

  • dataFactory: A custom RDFJS DataFactory to construct terms and triples. (Default: require('@rdfjs/data-model'))
  • baseIRI: An initial default base IRI. (Default: '')
  • language: A default language for string literals. (Default: '')
  • vocab: The initial vocabulary. (Default: '')
  • defaultGraph: The default graph for constructing quads. (Default: defaultGraph())
  • features: A hash of features that should be enabled. Defaults to the features defined by the profile. (Default: all features enabled)
  • profile: The RDFa profile to use. (Default: profile with all features enabled)
  • contentType: The content type of the document that should be parsed. This can be used as an alternative to the 'profile' option. (Default: profile with all features enabled)
  • htmlParseListener: An optional listener for the internal HTML parse events, should implement IHtmlParseListener (Default: null)
new RdfaParser({
  dataFactory: require('@rdfjs/data-model'),
  baseIRI: 'http://example.org/',
  language: 'en-us',
  vocab: 'http://example.org/myvocab',
  defaultGraph: namedNode('http://example.org/graph'),
  features: { langAttribute: true },
  profile: 'html',
  htmlParseListener: new MyHtmlListener(),
});

Profiles

On top of RDFa Core 1.1, there are a few RDFa variants that add specific sets of rules, which are all supported in this library:

  • HTML+RDFa 1.1: Internally identified as the 'html' profile with 'text/html' as content type.
  • XHTML+RDFa 1.1: Internally identified as the 'xhtml' profile with 'application/xhtml+xml' as content type.
  • SVG Tiny 1.2: Internally identified as the 'xml' profile with 'application/xml', 'text/xml' and 'image/svg+xml' as content types.

This library offers three different ways to define the RDFa profile or setting features:

  • Content type: Passing a content type such as 'text/html' to the contentType option in the constructor.
  • Profile string: Passing '', 'core', 'html', 'xhtml' or 'svg' to the profile option in the constructor.
  • Features object: A custom combination of features can be defined by passing a features option in the constructor.

The table below lists all possible RDFa features and in what profile they are available:

Feature Core HTML XHTML XML Description
baseTag If the baseIRI can be set via the <base> tag.
xmlBase If the baseIRI can be set via the xml:base attribute.
langAttribute If the language can be set via the language attribute.
onlyAllowUriRelRevIfProperty If non-CURIE and non-URI rel and rev have to be ignored if property is present.
inheritSubjectInHeadBody If the new subject can be inherited from the parent object if we're inside <head> or <body> if the resource defines no new subject.
datetimeAttribute If the datetime attribute must be interpreted as datetimes.
timeTag If the <time> tag contents should be interpreted as datetimes.
htmlDatatype If rdf:HTML as datatype should cause tag contents to be serialized to text.
copyRdfaPatterns If rdfa:copy property links can refer to rdfa:Pattern's for copying.
xmlnsPrefixMappings If prefixes should be extracted from xmlns.
skipHandlingXmlLiteralChildren If children of rdf:XMLLiteral should not be handled as RDFa anymore. This is not part of the RDFa spec.
xhtmlInitialContext If the XHTML initial context should be included in the initial prefixes.
roleAttribute If the role attribute should be handled.

How it works

This tool makes use of the highly performant htmlparser2 library for parsing HTML in a streaming way. It listens to tag-events, and maintains the required tag metadata in a stack-based datastructure, which can then be emitted as triples as soon as possible.

Our algorithm closely resembles the suggested processing sequence, with a few minor changes to make it work in a streaming way.

If you want to make use of a different HTML/XML parser, you can create a regular instance of RdfaParser, and just call the following methods yourself directly:

  • onTagOpen(name: string, attributes: {[s: string]: string})
  • onText(data: string)
  • onTagClose()

Specification Compliance

This parser passes all tests from the RDFa 1.1 test suite. More specifically, the following manifests are explicitly tested:

  • HTML+RDFa 1.1 (HTML4)
  • HTML+RDFa 1.1 (HTML5)
  • HTML+RDFa 1.1 (XHTML5)
  • SVGTiny+RDFa 1.1
  • XHTML+RDFa 1.1
  • XML+RDFa 1.1

The following optional features for RDFa processors are supported:

The following optional features for RDFa processors are not supported (yet):

License

This software is written by Ruben Taelman.

This code is released under the MIT license.

rdfa-streaming-parser.js's People

Contributors

greenkeeper[bot] avatar renovate-bot avatar renovate[bot] avatar rubensworks avatar tpt avatar

Stargazers

 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

rdfa-streaming-parser.js's Issues

Allow empty baseIRI

Currently, relative IRIs without a defined baseIRI will be ignored.
In some cases, it may be useful to have relative IRIs without a defined baseIRI.
As such, an undefined baseIRI should result in the creation of relative IRIs in NamedNodes.

TODO: check what the spec says about this.

See discussion in rdfjs/N3.js#182

Do not preserve markup of elements with the `property` attribute and without markup preserving `datatype`

Elements with the property attribute and without the datatype attribute, datatype="", datatype="rdf:HTML", or datatype="rdf:XMLLiteral" should not have the parser preserve the markup in the content of the element and add all namespaces and prefixes.

For example, given input:

<dd about="#foo" property="skos:definition">foo <em>bar</em> baz</dd>

the following is given:

<#foo> skos:definition "foo <em xmlns=\"http://www.w3.org/1999/xhtml\".......\">bar</em> baz" .

but the expected RDF is:

<#foo> skos:definition "foo bar baz" .

Extracting RDFa from existing HTML DOM

In this use case, the JavaScript is directly embedded in the HTML document, and RDFa needs to be extracted once the user has performed some action.

I believe that extracting RDFa from parsed DOM has two advantages:
(1) no need for parsing the same HTML twice
(2) include input values from form elements, as entered by the user, in the extracted RDF

Currently, this use case requires something like rdfaParser.write($("body").html());, which parses the original HTML (body) string - this requires manually looking up input values and inserting them into the extracted RDF (e.g., using rdfjs/N3.js).

Extracting RDFa from current HTML document

I'm working on extracting RDF-annotated HTML form data, with RDFa providing the annotations within form elements. The JS code is directly embedded within the HTML document.

For instance:
<input type='number' min='1' max='10' step='1' property='fhir:Observation.valueInteger' />

To that end, I'm using the rdfa-streaming-parser library as follows: rdfaParser.write($("body").html()); But, this requires manually looking up the input values and inserting them into the extracted RDF (not very difficult, I'm using rdfjs/N3.js for this purpose).

I don't think the RDFa parser is currently able to extract RDF from an already-parsed HTML DOM? This could support for these kinds of use cases.

An in-range update of @types/rdf-js is breaking the build 🚨

The dependency @types/rdf-js was updated from 2.0.9 to 2.0.10.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/rdf-js is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

npm
package.json
  • @rdfjs/types *
  • htmlparser2 ^9.0.0
  • rdf-data-factory ^1.1.0
  • relative-to-absolute-iri ^1.0.2
  • readable-stream ^4.0.0
  • @types/jest ^28.0.0
  • @types/jest-each ^24.3.0
  • @types/readable-stream ^4.0.0
  • arrayify-stream ^2.0.0
  • coveralls ^3.0.0
  • jest ^28.0.0
  • jest-each ^28.0.0
  • jest-rdf ^1.7.0
  • manual-git-changelog ^1.0.1
  • pre-commit ^1.2.2
  • rdf-quad ^1.5.0
  • rdf-test-suite ^1.13.4
  • streamify-string ^1.0.1
  • ts-jest ^28.0.0
  • ts-loader ^9.3.1
  • tslint ^6.0.0
  • tslint-eslint-rules ^5.3.1
  • typescript ^4.0.0
  • webpack ^5.73.0
  • webpack-cli ^4.10.0

  • Check this box to trigger a request for Renovate to run again on this repository

Namespaced rdf attributes in xhtml?

Is it possible to namespace rdf attributes in xhtml?

If I understand everything correctly, the snippet below should be valid RDFa in xhtml. When I feed this into the parser, the articleBody does not get parsed as an html datatype. It does, when I remove the rdf: namespace.

In the project I'm working on, I need the rdf: namespace, because another library serializes data* attributes as kebab case. (I also filed an issue there).

Your code doesn't seem to do any kind of normalization on attribute names (neither does htmlparser2). I wonder if support for this use case is missing, or if I misunderstand something about (rdf) namespaces.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns">
<head><title>Test namespace</title></head>
<body vocab="http://schema.org/">
<article typeof="Article">
  <p property="articleBody" rdf:datatype="rdf:HTML">
    <strong>Rich</strong>
    <em>Text</em>
  </p>
</article>
</body
</html>

Literals that are the concatination of all descendant text nodes

For the case of Local Decisions as Linked Open Data (LBLOD), municipalities publish the content of their decisions using deeper nested Articles as follows:

<div prefix="eli: http://data.europa.eu/eli/ontology# foaf: http://xmlns.com/foaf/0.1/ besluit: http://data.vlaanderen.be/ns/besluit# prov: http://www.w3.org/ns/prov#" resource="http://data.lblod.info/id/besluiten/72b89f05-7398-4c12-890c-a130decac4f8" typeof="besluit:Besluit">
  <h5>Beslissing</h5>
  <div property="prov:value" datatype="xsd:string">
    <div property="eli:has_part" resource="http://data.lblod.info/artikels/f3366b82-3751-4333-8531-b9b58b6ccb7f" typeof="besluit:Artikel">
      <div property="eli:number" datatype="xsd:string">Artikel 1</div>
      <div property="prov:value" datatype="xsd:string">
        Goedkeuring werd verleend aan...
      </div>
    </div>
    <br>
    <br>
  </div>
</div>

Using the RDFa playground, this returns following triple:

<http://data.lblod.info/id/besluiten/72b89f05-7398-4c12-890c-a130decac4f8>
   <http://www.w3.org/ns/prov#value> "
    
      Artikel 1
      
        Goedkeuring werd verleend aan...
      
    
    
    
  "^^xsd:string;

However, with RDF play, I receive this triple:

<http://data.lblod.info/id/besluiten/72b89f05-7398-4c12-890c-a130decac4f8> <http://www.w3.org/ns/prov#value> "\n      \n        \n        \n      \n      \n      \n    "

According to the RDFa spec (step 11), this should be the concatination of the values of all descendant text nodes.

Provide ready to use file for browsers

Currently, the creation of a browser-usable script requires npm, typescript, and compiler (e.g. browserify) to generate a standalone file ready for usage in the browser. By providing a dist version in a single-file, the library can be used in any webpage without backend requirements. This process is trivial (e.g. add commands to build process to generate file and put in dist folder) and would save time (e.g. for every single download and compilation of file for browsers).

P.S. Thanks for this work : )

Ensure backpressure is maintained in streams

There may be some places where we are not adhering to Node's backpressure conventions with regards to streams.

Concretely, we seem to be creating new streams (such as Readable, PassThrough and Transform), and push-ing into them (via a 'data' handler on another stream). Node handles backpressuring via the return value of push, which we are ignoring in this manner.

A better solution would be to simply pipe instead of calling push on each data element.

Related to rubensworks/rdf-parse.js@269c757

feat: Emit prefix events

I have content negotiation on my website done by rdf-transform. Because this library is being used for the parsing of my website under the hood; it would be nice if it could emit a prefix event when it encounters new prefixes so that serializers such as that in N3.js can make use of them to prettify the result.

Add RDFa 1.0 option

RDFa 1.0 processing is slightly different, see spec-1-svg, spec-1-xhtml1 and spec-1-xml.

An option should be available to set the version to 1.0 to enable this kind of processing.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

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.