X-Git-Url: http://git.squeep.com/?p=squeep-web-linking;a=blobdiff_plain;f=lib%2Frfc8288-web-linking.peggy;fp=lib%2Frfc8288-web-linking.peggy;h=95b47923eb307fb6b36e4c790cead737208442d1;hp=0000000000000000000000000000000000000000;hb=3436c07c25324507228f3d538d345ea35751c623;hpb=b36198e0a3d21413d75a501ffd52f0fb20188a31 diff --git a/lib/rfc8288-web-linking.peggy b/lib/rfc8288-web-linking.peggy new file mode 100644 index 0000000..95b4792 --- /dev/null +++ b/lib/rfc8288-web-linking.peggy @@ -0,0 +1,122 @@ +{{ +/* Generated code is not pretty, ignore a lot of this horrorstyle. */ +/* eslint-disable quotes */ +/* eslint-disable vars-on-top */ +/* eslint-disable no-control-regex */ +/* eslint-disable security/detect-object-injection */ +/* eslint-disable vars-on-top */ +/* eslint-disable brace-style */ +/* eslint-disable comma-dangle */ +/* eslint-disable no-unused-vars */ + +function makeString(o) { + return o.join(''); +} + +const onlyFirstAttributes = [ + 'media', + 'rel', + 'title', + 'title*', + 'type', +]; + +}} + +{ +// Per-parsing tracking of attributes which should be ignored after first occurrence. +let seenAttributes = []; +} + +links 'links' + = links:linkValue+ { + return links; + } + +linkValue 'link-value' + = uriReference:uriReference OWS attributes:attributes ','? OWS { + seenAttributes = []; + return { + target: uriReference, + attributes, + }; + } + +uriReference 'uri-reference' + = '<' uri:uri '>' ';' { + return uri; + } + +uri 'uri' + = uri:[^>]+ { + return makeString(uri); + } + +attributes 'attributes' + = attrs:linkParam+ { + return attrs.filter((a) => a); + } + +linkParam 'link-param' + = name:name BWS '=' BWS value:value ';'? OWS { + if (onlyFirstAttributes.includes(name.name)) { + if (seenAttributes.includes(name.name)) { + // Repeat of singleton attribute, ignore it. + return; + } + seenAttributes.push(name.name); + } + return { + ...name, + ...value, + }; + } + / name:name BWS ';'? OWS { + return { + ...name, + value: null, + } + } + +name 'name' + = name:[a-zA-Z]+ extended:'*'? { + return { + name: makeString(name.concat(extended)).toLowerCase(), + extended: !!extended, + }; + } + +value 'value' + = ["] value:[^"]+ ["] { + return { + value: makeString(value), + }; + } + / value:[^";,]+ { + return { + value: makeString(value), + }; + } + +OWS 'whitespace' + = spaces:[ ]* + +BWS 'bad whitespace' + = OWS + +// This is also an alternate startRule. +extendedValue 'extended-value' + = encoding:[^']* ['] language:[^']* ['] value:.* { + return { + encoding: encoding.length ? makeString(encoding) : 'UTF-8', + language: language.length ? makeString(language) : null, + value: decodeURIComponent(makeString(value)), + }; + } + / value:.* { + return { + encoding: null, + language: null, + value: makeString(value), + }; + }