/ lib / enhanceable.js
enhanceable.js
 1  import { bablr, Source, Context } from '@bablr/bablr-vm';
 2  import { createParseStrategy } from '@bablr/bablr-vm-strategy-parse';
 3  import { sourceFromQuasis } from '@bablr/helpers/source';
 4  import { evaluateReturnSync, getCooked, getRoot } from '@bablr/agast-helpers/tree';
 5  import {
 6    buildBasicNodeMatcher,
 7    buildOpenNodeMatcher,
 8    buildPropertyMatcher,
 9  } from '@bablr/helpers/builders';
10  
11  export { treeFromStreamSync, treeFromStreamAsync, streamFromTree } from '@bablr/agast-helpers/tree';
12  
13  export { Context };
14  
15  export function streamParse(language, matcher, sourceText, props, options = {}) {
16    const { enhancers = {} } = options;
17  
18    const source = Source.from(sourceText);
19  
20    const context = language instanceof Context ? language : Context.from(language);
21  
22    let bablr_ = bablr;
23    let createParseStrategy_ = createParseStrategy;
24  
25    if (enhancers.bablr) {
26      bablr_ = enhancers.bablr(bablr);
27    }
28  
29    if (enhancers.createBablrStrategy) {
30      createParseStrategy_ = enhancers.createBablrStrategy(createParseStrategy);
31    }
32  
33    return bablr_(context, source, createParseStrategy_(matcher, props), options);
34  }
35  
36  export const buildEmbeddedTag = (context, defaultMatcher, props, options = {}) => {
37    const defaultTag = (quasis, ...expressions) => {
38      return evaluateReturnSync(
39        streamParse(context, defaultMatcher, sourceFromQuasis(quasis), props, {
40          ...options,
41          expressions,
42        }),
43      );
44    };
45  
46    return new Proxy(defaultTag, {
47      apply(defaultTag, receiver, argsList) {
48        return defaultTag.apply(receiver, argsList);
49      },
50  
51      get(_, type) {
52        return (quasis, ...expressions) => {
53          const matcher = buildPropertyMatcher(
54            null,
55            buildBasicNodeMatcher(
56              buildOpenNodeMatcher(
57                {},
58                getCooked(
59                  getRoot(defaultMatcher).properties.nodeMatcher.node.properties.open.node.properties
60                    .language.node.properties.content.node,
61                ),
62                type,
63              ),
64            ),
65          );
66  
67          return evaluateReturnSync(
68            streamParse(context, matcher, sourceFromQuasis(quasis), props, {
69              ...options,
70              expressions,
71            }),
72          );
73        };
74      },
75    });
76  };
77  
78  export const buildRawTag = (context, defaultMatcher, props, options = {}) => {
79    const embeddedTag = buildEmbeddedTag(context, defaultMatcher, props, options);
80  
81    const defaultTag = (quasis, ...exprs) => {
82      return embeddedTag(quasis.raw, ...exprs);
83    };
84  
85    return new Proxy(defaultTag, {
86      apply(defaultTag, receiver, argsList) {
87        return defaultTag.apply(receiver, argsList);
88      },
89  
90      get(_, type) {
91        return (quasis, ...exprs) => {
92          return embeddedTag[type](quasis, ...exprs);
93        };
94      },
95    });
96  };
97  
98  export const buildTag = buildRawTag;