@gjsify/gtksource-core 0.0.0-stage → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0});export{__name};
@@ -0,0 +1 @@
1
+ import"./types.js";import{UnsupportedRegexError as e,translateRegex as t}from"./regex.js";import{XmlParseError as n,childElements as r,decodeEntities as i,parseXml as a,textContent as o}from"./xml.js";import{keywordPattern as s,parseLanguage as c}from"./lang.js";import{parseStyleScheme as l,resolveStyle as u}from"./style.js";import{INITIAL_STATE as d,Tokenizer as f,schemeStyleName as p}from"./tokenizer.js";export{d as INITIAL_STATE,f as Tokenizer,e as UnsupportedRegexError,n as XmlParseError,r as childElements,i as decodeEntities,s as keywordPattern,c as parseLanguage,l as parseStyleScheme,a as parseXml,u as resolveStyle,p as schemeStyleName,o as textContent,t as translateRegex};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{UnsupportedRegexError as e,translateRegex as t}from"./regex.js";import{childElements as n,parseXml as r,textContent as i}from"./xml.js";const a=[`id`,`name`,`_name`,`version`,`_section`],o=[`id`,`name`,`_name`,`map-to`],s=[`id`,`style-ref`,`end-at-line-end`,`sub-pattern`,`ref`],c=[`extended`],l=[`match`,`start`,`end`,`keyword`,`prefix`,`suffix`,`include`];function keywordPattern(e){let t=e.prefix??`\\%[`,n=e.suffix??`\\%]`;return`${t}(?:${e.keywords.join(`|`)})${n}`}function describe(e){let t=e.attributes.id??e.attributes.ref;return t===void 0?e.name:`${e.name}[${e.attributes.id===void 0?`ref`:`id`}=${t}]`}var Reader=class{constructor(){this.unsupported=[],this.styleIds=new Set,this.contextIds=new Set,this.styleRefs=[],this.refs=[]}flag(e,t){this.unsupported.push({construct:e,where:t})}attributes(e,t,n){for(let r of Object.keys(e.attributes))t.includes(r)||this.flag(`attribute ${r}`,n)}pattern(n,r){this.attributes(n,c,r);let a=i(n),o=n.attributes.extended===`true`;try{t(a,{extended:o})}catch(t){if(t instanceof e)this.flag(`regex: ${t.construct}`,r);else if(t instanceof SyntaxError)this.flag(`regex: ${t.message}`,r);else throw t}return{source:a,extended:o}}context(e,t){let r=`${t}/${describe(e)}`;this.attributes(e,s,r);let a=e.attributes.id;a!==void 0&&this.contextIds.add(a);let o=e.attributes[`style-ref`];o!==void 0&&this.styleRefs.push({value:o,where:r});let c=e.attributes.ref;c!==void 0&&this.refs.push({value:c,where:r});let u=e.attributes[`sub-pattern`],d,f,p,m,h,g=[],_=[];for(let t of n(e)){let e=`${r}/${t.name}`;if(!l.includes(t.name))this.flag(`element ${t.name}`,r);else if(t.name===`match`)d=this.pattern(t,e);else if(t.name===`start`)f=this.pattern(t,e);else if(t.name===`end`)p=this.pattern(t,e);else if(t.name===`keyword`)g.push(i(t).trim());else if(t.name===`prefix`)m=i(t).trim();else if(t.name===`suffix`)h=i(t).trim();else{this.attributes(t,[],e);for(let r of n(t))r.name===`context`?_.push(this.context(r,e)):this.flag(`element ${r.name}`,e)}}return{id:a,styleRef:o,endAtLineEnd:e.attributes[`end-at-line-end`]===`true`,subPattern:u===void 0?void 0:Number.parseInt(u,10),ref:c,match:d,start:f,end:p,keywords:g,prefix:m,suffix:h,include:_}}};function parseLanguage(e,t={}){let s=r(e),c=new Reader;if(s.name!==`language`)throw Error(`parseLanguage: root element is <${s.name}>, not <language>`);c.attributes(s,a,`language`);let l={},u=[],d=[];for(let e of n(s))if(e.name===`metadata`)for(let t of n(e)){let e=t.attributes.name;t.name!==`property`||e===void 0?c.flag(`element ${t.name}`,`language/metadata`):l[e]=i(t).trim()}else if(e.name===`styles`)for(let t of n(e)){let e=`language/styles/${describe(t)}`;c.attributes(t,o,e);let n=t.attributes.id;if(t.name!==`style`||n===void 0){c.flag(`element ${t.name}`,`language/styles`);continue}c.styleIds.add(n),u.push({id:n,name:t.attributes.name??t.attributes._name,mapTo:t.attributes[`map-to`]})}else if(e.name===`definitions`)for(let t of n(e))t.name===`context`?d.push(c.context(t,`language/definitions`)):c.flag(`element ${t.name}`,`language/definitions`);else c.flag(`element ${e.name}`,`language`);for(let{value:e,where:t}of c.styleRefs)e.includes(`:`)?e.startsWith(`def:`)||c.flag(`cross-language style-ref ${e}`,t):c.styleIds.has(e)||c.flag(`style-ref ${e} names no style`,t);for(let{value:e,where:t}of c.refs)e.includes(`:`)?c.flag(`cross-language ref ${e}`,t):c.contextIds.has(e)||c.flag(`ref ${e} names no context`,t);let f=s.attributes.id;if(f===void 0)throw Error(`parseLanguage: <language> has no id`);if(t.strict&&c.unsupported.length>0){let e=c.unsupported.map(e=>`${e.construct} at ${e.where}`).join(`; `);throw Error(`parseLanguage(${f}): unsupported constructs: ${e}`)}return{id:f,name:s.attributes.name??s.attributes._name,version:s.attributes.version,section:s.attributes._section,metadata:l,styles:u,definitions:d,unsupported:c.unsupported}}export{keywordPattern,parseLanguage};
@@ -0,0 +1,2 @@
1
+ import"./_virtual/_rolldown/runtime.js";var UnsupportedRegexError=class extends Error{constructor(e,t){super(`${e} is not supported (at offset ${t})`),this.construct=e,this.offset=t,this.name=`UnsupportedRegexError`}};const e={A:`\\A (start of subject)`,Z:`\\Z (end of subject)`,z:`\\z (end of subject)`,G:`\\G (match start anchor)`,K:`\\K (reset match start)`,Q:`\\Q…\\E quoting`,h:`\\h (horizontal space)`,H:`\\H (not horizontal space)`,R:`\\R (newline sequence)`},t=/^\{\d+(?:,\d*)?\}/,isGroupRefDelimiter=e=>e===`<`||e===`{`||e===`'`;function translateRegex(n,r){let i=r.extended,a=`m`;for(let e of r.flags??``)a.includes(e)||(a+=e);let o=``,s=0,c=!1,l=/^\(\?([isx]+)\)/.exec(n);if(l){for(let e of l[1])e===`x`?i=!0:a.includes(e)||(a+=e);s=l[0].length}let emit=e=>{o+=e,c=!1};for(;s<n.length;){let r=n[s];if(r===`\\`){let t=n[s+1];if(t===void 0)throw new UnsupportedRegexError(`a trailing backslash`,s);if(t in e)throw new UnsupportedRegexError(e[t],s);if(t===`%`){let e=n[s+2];if(e===`[`||e===`]`){emit(`\\b`),s+=3;continue}throw new UnsupportedRegexError(`\\%{id} regex reference`,s)}if(t===`x`&&n[s+2]===`{`)throw new UnsupportedRegexError(`braced \\x{…} escape`,s);if((t===`p`||t===`P`)&&n[s+2]===`{`)throw new UnsupportedRegexError(`\\p{…}/\\P{…} (Unicode property)`,s);if(t===`e`)throw new UnsupportedRegexError(`\\e (ESC character)`,s);if(t===`g`&&isGroupRefDelimiter(n[s+2]))throw new UnsupportedRegexError(`\\g<…>/\\g{…} (PCRE group reference)`,s);if(t===`N`&&n.slice(s+2,s+5)===`{U+`)throw new UnsupportedRegexError(`\\N{U+…} (Unicode codepoint)`,s);emit(r+t),s+=2;continue}if(r===`[`){let t=s+1,r=`[`;for(n[t]===`^`&&(r+=`^`,t++),n[t]===`]`&&(r+=`\\]`,t++);;){let i=n[t];if(i===void 0)throw new UnsupportedRegexError(`an unterminated character class`,s);if(i===`]`)break;if(i===`[`&&n[t+1]===`:`)throw new UnsupportedRegexError(`a POSIX character class`,t);if(i===`\\`){let a=n[t+1];if(a===void 0)throw new UnsupportedRegexError(`an unterminated character class`,s);if(a in e)throw new UnsupportedRegexError(e[a],t);if(a===`x`&&n[t+2]===`{`)throw new UnsupportedRegexError(`braced \\x{…} escape`,t);if((a===`p`||a===`P`)&&n[t+2]===`{`)throw new UnsupportedRegexError(`\\p{…}/\\P{…} (Unicode property)`,t);if(a===`e`)throw new UnsupportedRegexError(`\\e (ESC character)`,t);if(a===`g`&&isGroupRefDelimiter(n[t+2]))throw new UnsupportedRegexError(`\\g<…>/\\g{…} (PCRE group reference)`,t);if(a===`N`&&n.slice(t+2,t+5)===`{U+`)throw new UnsupportedRegexError(`\\N{U+…} (Unicode codepoint)`,t);r+=i+a,t+=2;continue}r+=i,t++}emit(`${r}]`),s=t+1;continue}if(r===`(`&&n[s+1]===`?`){let e=n.slice(s+2);if(e.startsWith(`>`))throw new UnsupportedRegexError(`an atomic group (?>…)`,s);if(e.startsWith(`(`))throw new UnsupportedRegexError(`a conditional group (?(…)`,s);if(e.startsWith(`|`))throw new UnsupportedRegexError(`a branch reset group (?|…)`,s);if(e.startsWith(`#`)){let e=n.indexOf(`)`,s);if(e===-1)throw new UnsupportedRegexError(`an unterminated (?#…) comment`,s);s=e+1;continue}if(e.startsWith(`P<`)){emit(`(?<`),s+=4;continue}let t=/^P=(\w+)\)/.exec(e);if(t){emit(`\\k<${t[1]}>`),s+=2+t[0].length;continue}if(/^(?:R|[0-9]|[+-][0-9]|&|P>)/.test(e))throw new UnsupportedRegexError(`recursion or a subroutine call`,s);if(/^[imsxUJ-]+[:)]/.test(e))throw new UnsupportedRegexError(`an inline flag group`,s);emit(`(?`),s+=2;continue}if(r===`{`){let e=t.exec(n.slice(s));if(e){emit(e[0]),c=!0,s+=e[0].length;continue}}if(r===`+`&&c)throw new UnsupportedRegexError(`a possessive quantifier`,s);if(r===`*`||r===`+`||r===`?`){let e=r===`?`&&c;emit(r),c=!e,s++;continue}if(i){if(/\s/.test(r)){s++;continue}if(r===`#`){for(;s<n.length&&n[s]!==`
2
+ `;)s++;continue}}emit(r),s++}return new RegExp(o,a)}export{UnsupportedRegexError,translateRegex};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{childElements as e,parseXml as t,textContent as n}from"./xml.js";const r=[`id`,`name`,`_name`,`parent-scheme`,`version`],i=[`name`,`foreground`,`background`,`line-background`,`bold`,`italic`,`strikethrough`,`underline`],asBoolean=e=>e===void 0?void 0:e===`true`;function parseStyleScheme(a){let o=t(a);if(o.name!==`style-scheme`)throw Error(`parseStyleScheme: root element is <${o.name}>, not <style-scheme>`);let s=o.attributes.id;if(s===void 0)throw Error(`parseStyleScheme: <style-scheme> has no id`);let c=[];for(let e of Object.keys(o.attributes))r.includes(e)||c.push({construct:`attribute ${e}`,where:`style-scheme`});let l=[],u=[],d=[];for(let t of e(o))if(t.name===`author`)l.push(n(t).trim());else if(t.name===`description`)continue;else if(t.name===`color`){let{name:e,value:n}=t.attributes;e===void 0||n===void 0?c.push({construct:`color without name or value`,where:`style-scheme/color`}):u.push({name:e,value:n})}else if(t.name===`style`){let e=t.attributes.name;if(e===void 0){c.push({construct:`style without name`,where:`style-scheme/style`});continue}let n={};for(let[e,r]of Object.entries(t.attributes))i.includes(e)||(n[e]=r);let r=t.attributes;d.push({name:e,foreground:r.foreground,background:r.background,lineBackground:r[`line-background`],bold:asBoolean(r.bold),italic:asBoolean(r.italic),strikethrough:asBoolean(r.strikethrough),underline:r.underline,extra:n})}else c.push({construct:`element ${t.name}`,where:`style-scheme`});return{id:s,name:o.attributes.name??o.attributes._name,parentScheme:o.attributes[`parent-scheme`],version:o.attributes.version,authors:l,colors:u,styles:d,unsupported:c}}function resolveStyle(e,t,n){let r=[];for(let t=e;t;){if(r.some(e=>e.id===t?.id))throw Error(`style scheme ${e.id}: parent-scheme loop through ${t.id}`);if(r.push(t),t.parentScheme===void 0)break;if(t=n(t.parentScheme),t===void 0)throw Error(`style scheme ${r[r.length-1].id}: parent-scheme ${r[r.length-1].parentScheme} not found`)}let i=r.findIndex(e=>e.styles.some(e=>e.name===t));if(i===-1)return;let a=r[i].styles.find(e=>e.name===t);if(a===void 0)return;let color=e=>{if(e!==void 0){for(let t of r.slice(i)){let n=t.colors.find(t=>t.name===e);if(n)return n.value}return e}};return{name:t,foundIn:r[i].id,foreground:color(a.foreground),background:color(a.background),lineBackground:color(a.lineBackground),bold:a.bold,italic:a.italic,strikethrough:a.strikethrough,underline:a.underline}}export{parseStyleScheme,resolveStyle};
@@ -0,0 +1,2 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{translateRegex as e}from"./regex.js";import{keywordPattern as t}from"./lang.js";const n={stack:[]};function search(e,t,n,r=!1){for(e.lastIndex=n;;){let n=e.exec(t);if(!n)return null;if(r||n[0].length>0)return n;if(e.lastIndex=n.index+1,e.lastIndex>t.length)return null}}const compile=(t,n)=>e(t.source,{extended:t.extended,flags:n});var Tokenizer=class{constructor(e){this.byId=new Map,this.candidatesOf=new Map,this.endOf=new Map;let index=e=>{for(let t of e)t.id!==void 0&&this.byId.set(t.id,t),index(t.include)};index(e.definitions);let t=this.byId.get(e.id)??e.definitions[0];if(t===void 0)throw Error(`Tokenizer: language ${e.id} has no definitions`);this.root=t}tokenize(e,t=n){let r=[...t.stack],i=[],a=0,emit=(e,t,n)=>{if(t<=e||n===void 0)return;let r=i[i.length-1];r&&r.end===e&&r.style===n?i[i.length-1]={start:r.start,end:t,style:n}:i.push({start:e,end:t,style:n})},baseStyle=()=>{for(let e=r.length-1;e>=0;e--){let t=r[e].styleRef;if(t!==void 0)return t}};for(;;){let t=r.length>0?r[r.length-1]:this.root,n=r.length>0?this.endRegex(t):void 0,i=n?search(n,e,a,!0):null,o;for(let n of this.candidates(t)){let t=search(n.regex,e,a);t&&(!o||t.index<o.found.index)&&(o={candidate:n,found:t})}if(i&&(!o||i.index<=o.found.index)){emit(a,i.index,baseStyle()),emit(i.index,i.index+i[0].length,t.styleRef??baseStyle()),r.pop(),a=i.index+i[0].length;continue}if(!o){emit(a,e.length,baseStyle());break}let{candidate:s,found:c}=o,l=baseStyle(),u=s.node.styleRef??l,d=c.index,f=d+c[0].length;emit(a,d,l),s.kind===`span`?(emit(d,f,u),r.push(s.node)):this.emitMatch(c,u,s.subPatterns,emit),a=f}for(;r.length>0&&r[r.length-1].endAtLineEnd;)r.pop();return{tokens:i,state:{stack:r}}}tokenizeText(e){let t=[],r=n;for(let n of e.split(`
2
+ `)){let e=this.tokenize(n,r);t.push(e),r=e.state}return t}emitMatch(e,t,n,r){let i=e.index,a=i+e[0].length,o=e.indices,s=[];for(let e of n){let n=e.subPattern===void 0?void 0:e.subPattern===0?[i,a]:o?.[e.subPattern];n&&s.push({start:n[0],end:n[1],style:e.styleRef??t})}s.sort((e,t)=>e.start-t.start);let c=i;for(let e of s)e.start<c||(r(c,e.start,t),r(e.start,e.end,e.style),c=e.end);r(c,a,t)}endRegex(e){let t=this.endOf.get(e);if(!t){if(!e.end)throw Error(`Tokenizer: span context ${e.id??`(anonymous)`} has no <end>`);t=compile(e.end,`g`),this.endOf.set(e,t)}return t}candidates(n){let r=this.candidatesOf.get(n);if(r)return r;let i=[],a=new Set,visit=n=>{for(let r of n){let n=r;if(r.ref!==void 0){let e=this.byId.get(r.ref);if(!e)continue;n={...e,styleRef:r.styleRef??e.styleRef}}if(n.subPattern!==void 0&&!n.match&&!n.start&&n.keywords.length===0)continue;let o=n.include.filter(e=>e.subPattern!==void 0);if(n.match)i.push({node:n,kind:`match`,regex:compile(n.match,`gd`),subPatterns:o});else if(n.keywords.length>0)i.push({node:n,kind:`match`,regex:e(t(n),{extended:!1,flags:`gd`}),subPatterns:o});else if(n.start)i.push({node:n,kind:`span`,regex:compile(n.start,`g`),subPatterns:[]});else{let e=r.ref===void 0?n:this.byId.get(r.ref)??n;if(a.has(e))continue;a.add(e),visit(n.include),a.delete(e)}}};return visit(n.include),this.candidatesOf.set(n,i),i}};function schemeStyleName(e,t){return t.startsWith(`def:`)?t:e.styles.find(e=>e.id===t)?.mapTo??`${e.id}:${t}`}export{n as INITIAL_STATE,Tokenizer,schemeStyleName};
File without changes
package/lib/esm/xml.js ADDED
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";const e={lt:`<`,gt:`>`,amp:`&`,quot:`"`,apos:`'`};var XmlParseError=class extends Error{constructor(e,t){super(`${e} (at offset ${t})`),this.offset=t,this.name=`XmlParseError`}};function decodeEntities(t,n=0){return t.replace(/&(#x[0-9a-fA-F]+|#[0-9]+|[A-Za-z][A-Za-z0-9]*);/g,(t,r)=>{if(r.startsWith(`#`)){let e=r[1]===`x`?Number.parseInt(r.slice(2),16):Number.parseInt(r.slice(1),10);if(!(e>=1&&e<=1114111)||e>=55296&&e<=57343)throw new XmlParseError(`invalid character reference ${t}`,n);return String.fromCodePoint(e)}let i=e[r];if(i===void 0)throw new XmlParseError(`unknown entity ${t}`,n);return i})}const t=`[A-Za-z_][\\w.:-]*`,n=RegExp(`\\s+(${t})\\s*=\\s*(?:"([^"]*)"|'([^']*)')`,`y`);function parseXml(e){let r=0,i=[],a=null,closeElement=e=>{let t=i[i.length-1];if(t)t.children.push(e);else if(a)throw new XmlParseError(`more than one root element`,e.offset);else a=e};for(;r<e.length;){let a=e.indexOf(`<`,r),o=a===-1?e.length:a;if(o>r){let t=e.slice(r,o),n=i[i.length-1];if(n)n.children.push(decodeEntities(t,r));else if(t.trim()!==``)throw new XmlParseError(`text outside the root element`,r)}if(a===-1)break;if(r=a,e.startsWith(`<!--`,r)){let t=e.indexOf(`-->`,r+4);if(t===-1)throw new XmlParseError(`unterminated comment`,r);r=t+3}else if(e.startsWith(`<![CDATA[`,r)){let t=e.indexOf(`]]>`,r+9);if(t===-1)throw new XmlParseError(`unterminated CDATA section`,r);let n=i[i.length-1];if(!n)throw new XmlParseError(`CDATA outside the root element`,r);n.children.push(e.slice(r+9,t)),r=t+3}else if(e.startsWith(`<?`,r)){let t=e.indexOf(`?>`,r+2);if(t===-1)throw new XmlParseError(`unterminated processing instruction`,r);r=t+2}else if(e.startsWith(`<!`,r))if(/^<!DOCTYPE[^[>]*>/i.test(e.slice(r)))r=e.indexOf(`>`,r)+1;else throw new XmlParseError(`unsupported markup declaration`,r);else if(e.startsWith(`</`,r)){let n=RegExp(`</(${t})\\s*>`,`y`);n.lastIndex=r;let a=n.exec(e);if(!a)throw new XmlParseError(`malformed closing tag`,r);let o=i.pop();if(!o||o.name!==a[1])throw new XmlParseError(`closing tag </${a[1]}> does not match <${o?.name??`nothing`}>`,r);closeElement({name:o.name,attributes:o.attributes,children:o.children,offset:o.offset}),r=n.lastIndex}else{let a=RegExp(`<(${t})`,`y`);a.lastIndex=r;let o=a.exec(e);if(!o)throw new XmlParseError(`malformed opening tag`,r);let s={},c=a.lastIndex;for(;;){n.lastIndex=c;let t=n.exec(e);if(!t)break;if(t[1]in s)throw new XmlParseError(`duplicate attribute ${t[1]}`,c);s[t[1]]=decodeEntities(t[2]??t[3]??``,c),c=n.lastIndex}let l=/^\s*(\/?)>/.exec(e.slice(c));if(!l)throw new XmlParseError(`malformed attributes on <${o[1]}>`,c);r=c+l[0].length,l[1]===`/`?closeElement({name:o[1],attributes:s,children:[],offset:o.index}):i.push({name:o[1],offset:o.index,attributes:s,children:[]})}}if(i.length>0)throw new XmlParseError(`unclosed element <${i[i.length-1].name}>`,e.length);if(!a)throw new XmlParseError(`no root element`,0);return a}function childElements(e,t){return e.children.filter(e=>typeof e!=`string`&&(t===void 0||e.name===t))}function textContent(e){return e.children.map(e=>typeof e==`string`?e:textContent(e)).join(``)}export{XmlParseError,childElements,decodeEntities,parseXml,textContent};
@@ -0,0 +1,4 @@
1
+ export declare const sixAssemblerLang = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<language id=\"6502-assembler\" name=\"6502 Assembler\" version=\"2.0\" _section=\"Source\">\n <metadata>\n <property name=\"mimetypes\">text/x-asm;text/x-assembler</property>\n <property name=\"globs\">*.asm;*.s</property>\n <property name=\"line-comment-start\">;</property>\n </metadata>\n\n <styles>\n <style id=\"comment\" name=\"Comment\" map-to=\"def:comment\"/>\n <style id=\"string\" name=\"String\" map-to=\"def:string\"/>\n <style id=\"preprocessor\" name=\"Preprocessor\" map-to=\"def:preprocessor\"/>\n <style id=\"instruction\" name=\"Instruction\" map-to=\"def:keyword\"/>\n <style id=\"number\" name=\"Number\" map-to=\"def:number\"/>\n <style id=\"constant\" name=\"Constant\" map-to=\"def:constant\"/>\n <style id=\"operator\" name=\"Operator\" map-to=\"def:operator\"/>\n <style id=\"label\" name=\"Label\" map-to=\"def:type\"/>\n <style id=\"variable\" name=\"Variable\" map-to=\"def:identifier\"/>\n </styles>\n \n <definitions>\n <context id=\"6502-assembler\">\n <include>\n <!-- Comments -->\n <context id=\"comment\" style-ref=\"comment\">\n <start>;</start>\n <end>$</end>\n </context>\n \n <!-- Strings -->\n <context id=\"string\" style-ref=\"string\" end-at-line-end=\"true\">\n <start>\"</start>\n <end>\"</end>\n <include>\n <context id=\"escape\" style-ref=\"def:special-char\">\n <match>\\\\.</match>\n </context>\n </include>\n </context>\n \n <!-- Numbers -->\n <context id=\"number\" style-ref=\"number\">\n <match extended=\"true\">\n (\\$[0-9a-fA-F]+\\b)|\n (\\@[0-1]+\\b)|\n (\\b[0-9]+\\b)\n </match>\n </context>\n \n <!-- Instructions -->\n <context id=\"instructions\" style-ref=\"instruction\">\n <keyword>LDA</keyword>\n <keyword>lda</keyword>\n <keyword>LDX</keyword>\n <keyword>ldx</keyword>\n <keyword>LDY</keyword>\n <keyword>ldy</keyword>\n <keyword>STA</keyword>\n <keyword>sta</keyword>\n <keyword>STX</keyword>\n <keyword>stx</keyword>\n <keyword>STY</keyword>\n <keyword>sty</keyword>\n <keyword>TXA</keyword>\n <keyword>txa</keyword>\n <keyword>TAX</keyword>\n <keyword>tax</keyword>\n <keyword>TYA</keyword>\n <keyword>tya</keyword>\n <keyword>TAY</keyword>\n <keyword>tay</keyword>\n <keyword>TXS</keyword>\n <keyword>txs</keyword>\n <keyword>TSX</keyword>\n <keyword>tsx</keyword>\n <keyword>ADC</keyword>\n <keyword>adc</keyword>\n <keyword>SBC</keyword>\n <keyword>sbc</keyword>\n <keyword>INC</keyword>\n <keyword>inc</keyword>\n <keyword>DEC</keyword>\n <keyword>dec</keyword>\n <keyword>INX</keyword>\n <keyword>inx</keyword>\n <keyword>DEX</keyword>\n <keyword>dex</keyword>\n <keyword>INY</keyword>\n <keyword>iny</keyword>\n <keyword>DEY</keyword>\n <keyword>dey</keyword>\n <keyword>AND</keyword>\n <keyword>and</keyword>\n <keyword>ORA</keyword>\n <keyword>ora</keyword>\n <keyword>EOR</keyword>\n <keyword>eor</keyword>\n <keyword>CLC</keyword>\n <keyword>clc</keyword>\n <keyword>SEC</keyword>\n <keyword>sec</keyword>\n <keyword>CLD</keyword>\n <keyword>cld</keyword>\n <keyword>SED</keyword>\n <keyword>sed</keyword>\n <keyword>CLV</keyword>\n <keyword>clv</keyword>\n <keyword>CLI</keyword>\n <keyword>cli</keyword>\n <keyword>SEI</keyword>\n <keyword>sei</keyword>\n <keyword>CMP</keyword>\n <keyword>cmp</keyword>\n <keyword>CPX</keyword>\n <keyword>cpx</keyword>\n <keyword>CPY</keyword>\n <keyword>cpy</keyword>\n <keyword>BIT</keyword>\n <keyword>bit</keyword>\n <keyword>ASL</keyword>\n <keyword>asl</keyword>\n <keyword>LSR</keyword>\n <keyword>lsr</keyword>\n <keyword>ROL</keyword>\n <keyword>rol</keyword>\n <keyword>ROR</keyword>\n <keyword>ror</keyword>\n <keyword>PHA</keyword>\n <keyword>pha</keyword>\n <keyword>PLA</keyword>\n <keyword>pla</keyword>\n <keyword>PHP</keyword>\n <keyword>php</keyword>\n <keyword>PLP</keyword>\n <keyword>plp</keyword>\n <keyword>JMP</keyword>\n <keyword>jmp</keyword>\n <keyword>JSR</keyword>\n <keyword>jsr</keyword>\n <keyword>NOP</keyword>\n <keyword>nop</keyword>\n <keyword>BEQ</keyword>\n <keyword>beq</keyword>\n <keyword>BNE</keyword>\n <keyword>bne</keyword>\n <keyword>BCS</keyword>\n <keyword>bcs</keyword>\n <keyword>BCC</keyword>\n <keyword>bcc</keyword>\n <keyword>BMI</keyword>\n <keyword>bmi</keyword>\n <keyword>BPL</keyword>\n <keyword>bpl</keyword>\n <keyword>BVS</keyword>\n <keyword>bvs</keyword>\n <keyword>BVC</keyword>\n <keyword>bvc</keyword>\n <keyword>RTS</keyword>\n <keyword>rts</keyword>\n <keyword>RTI</keyword>\n <keyword>rti</keyword>\n <keyword>BRK</keyword>\n <keyword>brk</keyword>\n </context>\n \n <!-- Preprocessor directives -->\n <context id=\"preprocessor\" style-ref=\"preprocessor\">\n <prefix>^\\s*\\.</prefix>\n <keyword>BASE</keyword>\n <keyword>ORG</keyword>\n <keyword>DEF</keyword>\n <keyword>IF</keyword>\n <keyword>INCLUDE</keyword>\n <keyword>INCBIN</keyword>\n <keyword>ELSEIF</keyword>\n <keyword>ELSE</keyword>\n <keyword>ENDIF</keyword>\n <keyword>IFDEF</keyword>\n <keyword>IFNDEF</keyword>\n <keyword>DB</keyword>\n <keyword>DW</keyword>\n <keyword>DBG</keyword>\n <keyword>DWG</keyword>\n <keyword>ENDD</keyword>\n <keyword>REPEAT</keyword>\n <keyword>ENDR</keyword>\n <keyword>MACRO</keyword>\n <keyword>ENDM</keyword>\n <keyword>MSG</keyword>\n <keyword>HEX</keyword>\n </context>\n\n <!-- Define constants -->\n <context id=\"define-constant\" style-ref=\"constant\">\n <match>^\\s*(define)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s+(.+)$</match>\n <include>\n <context sub-pattern=\"1\" style-ref=\"preprocessor\"/>\n <context sub-pattern=\"2\" style-ref=\"variable\"/>\n </include>\n </context>\n\n <!-- Operators -->\n <context id=\"operator\" style-ref=\"operator\">\n <match>[\\+\\-\\*\\/\\&gt;\\&lt;\\(\\)\\,\\#\\=\\!\\[\\]]</match>\n </context>\n\n <!-- Labels -->\n <context id=\"label\" style-ref=\"label\">\n <match>^[a-zA-Z_][a-zA-Z0-9_]*:</match>\n </context>\n\n <!-- Variables -->\n <context id=\"variable\" style-ref=\"variable\">\n <match>[a-zA-Z_][a-zA-Z0-9_]*</match>\n </context>\n </include>\n </context>\n </definitions>\n</language>";
2
+ export declare const hexLang = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<language id=\"hex\" name=\"Hex\" version=\"2.0\" _section=\"Other\">\n <metadata>\n <property name=\"mimetypes\">text/x-hex</property>\n <property name=\"globs\">*.hex</property>\n </metadata>\n <styles>\n <style id=\"zero\" name=\"Zero\" map-to=\"def:comment\"/>\n </styles>\n <definitions>\n <context id=\"hex\">\n <include>\n <context id=\"zero\" style-ref=\"zero\">\n <match>00</match>\n </context>\n </include>\n </context>\n </definitions>\n</language>";
3
+ export declare const learnStyle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<style-scheme id=\"Learn6502\" _name=\"Learn6502\" parent-scheme=\"Adwaita\" version=\"1.0\">\n <!--\n Only override current line background; inherit everything else from Adwaita\n Docs:\n - https://gnome.pages.gitlab.gnome.org/gtksourceview/gtksourceview5/style-reference.html\n -->\n <style name=\"current-line\" background=\"#00000018\"/>\n <style name=\"current-line-number\" background=\"#00000018\"/>\n</style-scheme>\n";
4
+ export declare const learnStyleDark = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<style-scheme id=\"Learn6502-dark\" _name=\"Learn6502 Dark\" parent-scheme=\"Adwaita-dark\" version=\"1.0\">\n <!--\n Only override current line background; inherit everything else from Adwaita-dark\n Docs:\n - https://gnome.pages.gitlab.gnome.org/gtksourceview/gtksourceview5/style-reference.html\n -->\n <style name=\"current-line\" background=\"#ffffff10\"/>\n <style name=\"current-line-number\" background=\"#ffffff10\"/>\n</style-scheme>\n";
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,6 @@
1
+ export * from './types.js';
2
+ export * from './lang.js';
3
+ export * from './style.js';
4
+ export * from './regex.js';
5
+ export * from './xml.js';
6
+ export * from './tokenizer.js';
@@ -0,0 +1,17 @@
1
+ import type { ContextNode, LanguageDefinition } from './types.js';
2
+ export interface ParseLanguageOptions {
3
+ /** Throw, listing every unsupported construct, instead of returning them in `unsupported`. */
4
+ readonly strict?: boolean;
5
+ }
6
+ /**
7
+ * The regex GtkSourceView puts before and after a `<keyword>` list when the context gives no
8
+ * `<prefix>`/`<suffix>`: `\%[` and `\%]`, a word boundary on each side.
9
+ */
10
+ export declare function keywordPattern(context: ContextNode): string;
11
+ /**
12
+ * Parses a GtkSourceView 5 `.lang` file into a tree. What it does not model (`extend-parent`,
13
+ * `once-only`, `<define-regex>`, `<replace>`, cross-language references, patterns the JS regex
14
+ * engine cannot run, a `ref` or `style-ref` with no target, …) lands in `unsupported` with its
15
+ * path — or throws with `strict`. Nothing is ever dropped without a trace.
16
+ */
17
+ export declare function parseLanguage(xml: string, options?: ParseLanguageOptions): LanguageDefinition;
@@ -0,0 +1,25 @@
1
+ export interface TranslateRegexOptions {
2
+ /** The `extended="true"` attribute of the pattern element (PCRE `x`): whitespace and `#` comments are not part of the pattern. */
3
+ readonly extended: boolean;
4
+ /** Flags to add to the always-set `m` (GtkSourceView matches `^`/`$` per line), e.g. `y` for the engine. */
5
+ readonly flags?: string;
6
+ }
7
+ /** A construct GRegex (PCRE) has and a JavaScript `RegExp` cannot express; refused, never approximated. */
8
+ export declare class UnsupportedRegexError extends Error {
9
+ readonly construct: string;
10
+ readonly offset: number;
11
+ constructor(construct: string, offset: number);
12
+ }
13
+ /**
14
+ * Translates one GtkSourceView pattern (GRegex/PCRE dialect) into a JS `RegExp`.
15
+ *
16
+ * One scanner owns the escape and character-class state, so a lookalike inside a class or
17
+ * behind a backslash (`[\+\-\*]`, `a\+\+`, `\\A`) is never mistaken for the construct. It handles:
18
+ * extended mode, `\%[`/`\%]` (GtkSourceView's word boundaries), a leading `(?i)`/`(?s)`/`(?x)`,
19
+ * `(?P<n>…)`/`(?P=n)`, `(?#…)` comments, and the POSIX-less `[]…]` literal bracket.
20
+ * It refuses, by name: possessive quantifiers, atomic groups, conditionals `(?(…)`, branch
21
+ * reset `(?|…)`, recursion and subroutine calls, `\A \Z \z \G \K \Q \h \H \R`,
22
+ * `\p{…}`/`\P{…}`, `\e`, `\g<…>`/`\g{…}` group references, `\N{U+…}`, `\%{id}` regex
23
+ * references, braced `\x{…}`, POSIX classes and inline flags anywhere but the very start.
24
+ */
25
+ export declare function translateRegex(source: string, options: TranslateRegexOptions): RegExp;
@@ -0,0 +1,13 @@
1
+ import type { ResolvedStyle, StyleSchemeDefinition } from './types.js';
2
+ /** Parses a GtkSourceView 5 style scheme. Attributes it does not interpret are kept in `extra`; unknown elements are reported. */
3
+ export declare function parseStyleScheme(xml: string): StyleSchemeDefinition;
4
+ /** Where {@link resolveStyle} finds the scheme a `parent-scheme` id names. */
5
+ export type SchemeLookup = (id: string) => StyleSchemeDefinition | undefined;
6
+ /**
7
+ * Resolves `styleName` the way GtkSourceView does: the scheme's own style wins, otherwise the
8
+ * `parent-scheme` chain is walked; a colour value that names a `<color>` is replaced by it
9
+ * (looked up in the scheme the style was found in, then its ancestors). A language style's
10
+ * `map-to="def:keyword"` resolves by passing `def:keyword` as the name. A `parent-scheme` loop,
11
+ * or a parent the lookup does not know, throws: it is a broken install, not a missing style.
12
+ */
13
+ export declare function resolveStyle(scheme: StyleSchemeDefinition, styleName: string, lookup: SchemeLookup): ResolvedStyle | undefined;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import type { ContextNode, LanguageDefinition } from './types.js';
2
+ /** A styled run of one line. `style` is the context's `style-ref`: a language style id or a `def:` name. */
3
+ export interface Token {
4
+ readonly start: number;
5
+ readonly end: number;
6
+ readonly style: string;
7
+ }
8
+ /** What carries from one line to the next: the span contexts still open, outermost first. */
9
+ export interface LineState {
10
+ readonly stack: readonly ContextNode[];
11
+ }
12
+ export declare const INITIAL_STATE: LineState;
13
+ export interface LineResult {
14
+ readonly tokens: readonly Token[];
15
+ readonly state: LineState;
16
+ }
17
+ /**
18
+ * Highlights a language line by line, the way GtkSourceView's context engine reads a `.lang`:
19
+ * inside a span the earliest of its end and its children wins (the end first on a tie), at the
20
+ * top level the earliest child wins (the one defined first on a tie), a `<context ref>` and an
21
+ * id-less container are flattened into their parent, text inside a span keeps the span's style
22
+ * unless a child overrides it, and `sub-pattern` children colour a capture group of their parent.
23
+ *
24
+ * Deliberately not modelled (see {@link parseLanguage}'s `unsupported`): `extend-parent`,
25
+ * `once-only`, `\%{id@start}` back references, case-insensitive contexts.
26
+ */
27
+ export declare class Tokenizer {
28
+ readonly root: ContextNode;
29
+ private readonly byId;
30
+ private readonly candidatesOf;
31
+ private readonly endOf;
32
+ constructor(language: LanguageDefinition);
33
+ /** Tokenizes one line (without its newline) from the state the previous line ended in. */
34
+ tokenize(line: string, state?: LineState): LineResult;
35
+ /** Tokenizes a whole text, line by line, carrying the state; the result has one entry per line. */
36
+ tokenizeText(text: string): readonly LineResult[];
37
+ private emitMatch;
38
+ private endRegex;
39
+ private candidates;
40
+ }
41
+ /**
42
+ * The scheme style a token takes: a `def:` name is looked up as it stands, a language style id goes
43
+ * through its `map-to`, and a style with neither is addressed as `<language>:<id>` like GtkSourceView.
44
+ */
45
+ export declare function schemeStyleName(language: LanguageDefinition, style: string): string;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,88 @@
1
+ /** Something in a data file this package does not model; reported with where it sits, never dropped silently. */
2
+ export interface Unsupported {
3
+ readonly construct: string;
4
+ /** A readable path, e.g. `definitions/context[id=string]/include/context[id=escape]`. */
5
+ readonly where: string;
6
+ }
7
+ /** A `<match>`, `<start>` or `<end>` pattern, still in GRegex dialect; see {@link translateRegex}. */
8
+ export interface PatternSource {
9
+ readonly source: string;
10
+ readonly extended: boolean;
11
+ }
12
+ /**
13
+ * One `<context>`. Exactly one of these shapes, as in GtkSourceView:
14
+ * a simple match (`match`), a start/end span (`start` + `end`, children in `include`),
15
+ * a keyword list (`keywords`, with `prefix`/`suffix`), a container (only `include`),
16
+ * or a reference to another context (`ref`).
17
+ */
18
+ export interface ContextNode {
19
+ readonly id?: string;
20
+ readonly styleRef?: string;
21
+ readonly endAtLineEnd: boolean;
22
+ /** Capture group a sub-pattern context colours instead of the whole parent match. */
23
+ readonly subPattern?: number;
24
+ readonly ref?: string;
25
+ readonly match?: PatternSource;
26
+ readonly start?: PatternSource;
27
+ readonly end?: PatternSource;
28
+ readonly keywords: readonly string[];
29
+ readonly prefix?: string;
30
+ readonly suffix?: string;
31
+ readonly include: readonly ContextNode[];
32
+ }
33
+ export interface LanguageStyle {
34
+ readonly id: string;
35
+ readonly name?: string;
36
+ /** `def:keyword` and the like: the scheme style this language style falls back to. */
37
+ readonly mapTo?: string;
38
+ }
39
+ export interface LanguageDefinition {
40
+ readonly id: string;
41
+ readonly name?: string;
42
+ readonly version?: string;
43
+ readonly section?: string;
44
+ readonly metadata: Readonly<Record<string, string>>;
45
+ readonly styles: readonly LanguageStyle[];
46
+ /** The top-level `<definitions>` contexts; the one whose id equals the language id is the entry point. */
47
+ readonly definitions: readonly ContextNode[];
48
+ readonly unsupported: readonly Unsupported[];
49
+ }
50
+ export interface SchemeColor {
51
+ readonly name: string;
52
+ readonly value: string;
53
+ }
54
+ export interface SchemeStyle {
55
+ readonly name: string;
56
+ readonly foreground?: string;
57
+ readonly background?: string;
58
+ readonly lineBackground?: string;
59
+ readonly bold?: boolean;
60
+ readonly italic?: boolean;
61
+ readonly strikethrough?: boolean;
62
+ readonly underline?: string;
63
+ /** Attributes this package does not interpret (`scale`, `underline-color`, `use-style`, …), kept verbatim. */
64
+ readonly extra: Readonly<Record<string, string>>;
65
+ }
66
+ export interface StyleSchemeDefinition {
67
+ readonly id: string;
68
+ readonly name?: string;
69
+ readonly parentScheme?: string;
70
+ readonly version?: string;
71
+ readonly authors: readonly string[];
72
+ readonly colors: readonly SchemeColor[];
73
+ readonly styles: readonly SchemeStyle[];
74
+ readonly unsupported: readonly Unsupported[];
75
+ }
76
+ /** A scheme style with its colour names replaced by the colour values. */
77
+ export interface ResolvedStyle {
78
+ readonly name: string;
79
+ /** The id of the scheme the style was found in (the requested one or an ancestor). */
80
+ readonly foundIn: string;
81
+ readonly foreground?: string;
82
+ readonly background?: string;
83
+ readonly lineBackground?: string;
84
+ readonly bold?: boolean;
85
+ readonly italic?: boolean;
86
+ readonly strikethrough?: boolean;
87
+ readonly underline?: string;
88
+ }
@@ -0,0 +1,23 @@
1
+ /** One element of a parsed XML document. Text and element children keep their source order in `children`. */
2
+ export interface XmlElement {
3
+ readonly name: string;
4
+ readonly attributes: Readonly<Record<string, string>>;
5
+ readonly children: readonly (XmlElement | string)[];
6
+ /** Offset of the opening `<` in the source, for error messages. */
7
+ readonly offset: number;
8
+ }
9
+ export declare class XmlParseError extends Error {
10
+ readonly offset: number;
11
+ constructor(message: string, offset: number);
12
+ }
13
+ /** Decodes the five predefined entities and numeric references; an unknown entity is an error, not passed through. */
14
+ export declare function decodeEntities(text: string, offset?: number): string;
15
+ /**
16
+ * Parses the XML subset GtkSourceView's data files use: elements, attributes, text, comments,
17
+ * CDATA, a prolog. DOCTYPE with an internal subset and namespaces are refused rather than guessed.
18
+ */
19
+ export declare function parseXml(source: string): XmlElement;
20
+ /** The child elements, in order, optionally only those named `name`. */
21
+ export declare function childElements(element: XmlElement, name?: string): XmlElement[];
22
+ /** The concatenated text of an element, as the XML spec defines text content. */
23
+ export declare function textContent(element: XmlElement): string;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,70 @@
1
1
  {
2
- "name": "@gjsify/gtksource-core",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@gjsify/gtksource-core",
3
+ "version": "0.56.0",
4
+ "description": "Headless GtkSourceView language/style parsing (renderer-free) — parse .lang and style scheme XML into typed data with JS regex translation, strict unsupported reporting",
5
+ "type": "module",
6
+ "module": "lib/esm/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/types/index.d.ts",
11
+ "default": "./lib/esm/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "lib"
16
+ ],
17
+ "scripts": {
18
+ "clear": "gjsify clear lib tmp dist tsconfig.tsbuildinfo test.gjs.mjs test.node.mjs",
19
+ "check": "gjsify tsc --noEmit",
20
+ "build": "gjsify run build:gjsify && gjsify run build:types",
21
+ "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}' 'src/fixtures.ts'",
22
+ "build:types": "gjsify tsc",
23
+ "build:test": "gjsify run build:test:gjs && gjsify run build:test:node && gjsify run build:test:browser",
24
+ "build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
25
+ "build:test:node": "gjsify build src/test.mts --app node --outfile test.node.mjs",
26
+ "build:test:browser": "gjsify build src/test.browser.mts --app browser --outfile dist/test.browser.mjs",
27
+ "test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:node && gjsify run test:gjs",
28
+ "test:gjs": "gjsify run test.gjs.mjs",
29
+ "test:node": "node test.node.mjs",
30
+ "test:bun": "bun test.node.mjs",
31
+ "test:deno": "deno run -A --no-lock --node-modules-dir=none --min-dep-age=0 test.node.mjs",
32
+ "test:cross-runtime": "gjsify run build:test:node && gjsify run test:node && gjsify run test:bun && gjsify run test:deno"
33
+ },
34
+ "keywords": [
35
+ "gjs",
36
+ "gtk",
37
+ "gtksourceview",
38
+ "language",
39
+ "syntax",
40
+ "highlighting",
41
+ "style-scheme",
42
+ "headless"
43
+ ],
44
+ "devDependencies": {
45
+ "@gjsify/cli": "^0.56.0",
46
+ "@gjsify/unit": "^0.56.0",
47
+ "@types/node": "^25.9.2",
48
+ "typescript": "^6.0.3"
49
+ },
50
+ "gjsify": {
51
+ "runtimes": {
52
+ "gjs": "polyfill",
53
+ "node": "polyfill",
54
+ "browser": "polyfill",
55
+ "nativescript": "polyfill"
56
+ },
57
+ "headless": true,
58
+ "tier": 2
59
+ },
60
+ "license": "MIT",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/gjsify/gjsify.git",
64
+ "directory": "packages/web/gtksource-core"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/gjsify/gjsify/issues"
68
+ },
69
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/web/gtksource-core#readme"
70
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.