/ lib / stream.js
stream.js
 1  import { Coroutine } from '@bablr/coroutine';
 2  import {
 3    generatePrettyCSTML as agastGeneratePrettyCSTML,
 4    generateCSTML as agastGenerateCSTML,
 5    stringFromStream,
 6    getStreamIterator,
 7    StreamIterable,
 8  } from '@bablr/agast-helpers/stream';
 9  import isString from 'iter-tools-es/methods/is-string';
10  import emptyStack from '@iter-tools/imm-stack';
11  import { DoctypeTag, OpenNodeTag, CloseNodeTag } from './symbols.js';
12  
13  import { unresolveLanguage } from './grammar.js';
14  
15  const { freeze } = Object;
16  
17  function* __resolveTags(ctx, tags) {
18    const co = new Coroutine(getStreamIterator(tags));
19    let languages = emptyStack;
20  
21    for (;;) {
22      co.advance();
23  
24      if (co.current instanceof Promise) {
25        co.current = yield co.current;
26      }
27  
28      if (co.done) break;
29  
30      const tag = co.value;
31  
32      if (tag.type === DoctypeTag) {
33        languages = languages.push(ctx.languages.get(tag.value.attributes.bablrLanguage));
34      }
35  
36      if (tag.type === CloseNodeTag) {
37        languages = languages.pop();
38      }
39  
40      if (tag.type === OpenNodeTag) {
41        if (isString(tag.value.language)) {
42          const currentLanguage = languages.value;
43          const nodeLanguageURL = tag.value.language;
44          const nodeLanguage = ctx.languages.get(nodeLanguageURL);
45  
46          languages = languages.push(nodeLanguage);
47  
48          yield freeze({
49            type: OpenNodeTag,
50            value: freeze({
51              ...tag.value,
52              language: unresolveLanguage(ctx, currentLanguage, nodeLanguageURL),
53            }),
54          });
55        } else {
56          yield tag;
57        }
58      } else {
59        yield tag;
60      }
61    }
62  }
63  
64  export const resolveTags = (ctx, tags) => {
65    return new StreamIterable(__resolveTags(ctx, tags));
66  };
67  
68  export const generatePrettyCSTML = (tags, options = {}) => {
69    const { ctx } = options;
70  
71    return agastGeneratePrettyCSTML(ctx ? resolveTags(ctx, tags) : tags, options);
72  };
73  
74  export const printPrettyCSTML = (tags, options = {}) => {
75    return stringFromStream(generatePrettyCSTML(tags, options));
76  };
77  
78  export const generateCSTML = (tags, options = {}) => {
79    const { ctx } = options;
80  
81    return agastGenerateCSTML(ctx ? resolveTags(ctx, tags) : tags, options);
82  };
83  
84  export const printCSTML = (tags, options = {}) => {
85    return stringFromStream(generateCSTML(tags, options));
86  };