@ibgib/helper-gib
Version:
common helper/utils/etc used in ibgib libs. Node v19+ needed for heavily-used isomorphic webcrypto hashing consumed in both node and browsers.
951 lines • 32.8 kB
text/typescript
export type LanguageCode = "en" | "de" | "en-US" | "en-GB" | "en-CA" | "en-IN" | "de-DE";
export declare const LanguageCode: {
en: LanguageCode;
de: LanguageCode;
enUS: LanguageCode;
enGB: LanguageCode;
enCA: LanguageCode;
enIN: LanguageCode;
deDE: LanguageCode;
};
/**
* Interface for each record in the lex data.
*
* When specifying `TProps`, be sure it is a flat key: value object. (I think...) Definitely not a circular reference complex object, so maybe any non-circular POCO will work.
*/
export interface LexDatum<TProps extends PropsData = PropsData> {
/**
* Language of the lexical datum.
*/
language?: LanguageCode;
/**
* Lexical items with the same id are considered alternatives for
* the equivalent message, e.g. "Hello" and "Howdy".
*
* If you have multiple LexDatums with the same id, then this
* can differentiate among them to get the _exact_ record.
*
* Basically this is an optional unique id, but the data overall
* is indexed by a non-unique "id" string. :nose:? maybe...
*/
specifier?: string;
/**
* Lexical items with the same id are considered alternatives for
* the equivalent message, e.g. "Hello" and "Howdy".
*
* If you have multiple LexDatums with the same id, then this
* can define the weighting of chance when selecting one of those
* alternatives.
*
* Must be non-zero. Default weighting is 1.
*
* @see Lex.pickDatum
*/
weighting?: number;
/**
* Keywords relating to the datum. You can specify keywords.
*/
keywords?: string[];
/**
* This is the lines of plain text.
*
* There should be no ssml tags in here.
*/
texts?: string[];
/**
* This is the ssml equivalent to `text`.
*
* Do NOT include any <speak> tags in here.
*/
ssmls?: string[];
/**
* Additional dynamic properties to filter/match against.
*
* Use Case:
*
* Currently, I'm doing x=123 in keywords, and this is meant to
* improve upon that.
*/
props?: TProps;
}
export interface LexGetOptions<TProps extends PropsData = PropsData> {
/**
* Language of datum to get.
*/
language?: LanguageCode;
/**
* Specifier of datum to get.
*/
specifier?: string;
/**
* Keywords of datum to get.
*/
keywords?: string[];
/**
* Determines how the `LexGetOptions.keywords` match with filtering
* data.
* @see {KeywordMode}
*/
keywordMode?: KeywordMode;
/**
* Index (0-based) into text/ssml of LexDatum to get.
* If not provided, will return all lines.
* Basically, use this if you just want a single string from the
* texts/ssmls array but don't want to duplicate that in a separate
* data entry.
*
* @example If you have texts of [ "a", "b", "c" ], but you just
* want the "b" line, you would pass in a lineIndex of 1.
*/
lineIndex?: number;
/**
* If provided, and if there are multiple lines in datum's
* text/ssml, then this determines how they are concatenated.
*
* @see LexLineConcat
*/
lineConcat?: LexLineConcat;
/**
* If lineConcat is "delim", then it will concat using this
* string as a delimiter. I'll have a default in the `get`
* function.
*
* @see Lex.get
*/
lineConcatDelim?: string;
/**
* How to capitalize the lex item text output when concatenating
* multiple lines in texts/ssmls.
*
* NOTE:
* I'm not sure if I should make it capitalize the ssml, but
* my hunch is to NOT do this, since that is supposed to be spoken
* text.
*
* @see LexCapitalize for individual options.
*/
capitalize?: LexCapitalize;
/**
* Template placeholder arguments. Each template in Lex can either
* be a reference to another Lex datum, e.g. $(hi), or it can be
* a template placeholder, e.g. $name, $age, $0, $1, etc. It simply
* has to start with a $ and be followed by one or more word
* characters ([a-zA-Z_0-9]+, i.e. \w+).
*
* So this javascript object is in the format of
* `"placeholder": "replacement"`, e.g.
*
* NOTE: If you want different variable replacements for texts and
* ssmls, then use this config option for the texts and use
* ssmlVars for the ssmls.
*
* @example
* In Lex data:
* "Welcome back, $username!"
* Calling code:
* `lex._('greeting', { vars: { username } })`
* If the text is and this is called
* with , then the output
* would be e.g. "Welcome back, Cotter!"
* (equivalent to `Welcome back, ${username}!`)
*/
vars?: {
[key: string]: string;
};
/**
* Same as vars option, but will only replace template variables
* in the `ssmls`.
*/
ssmlVars?: {
[key: string]: string;
};
/**
* Additional dynamic properties to filter/match against.
*
* Use Case:
*
* Currently, I'm doing x=123 in keywords, and this is meant to
* improve upon that.
*
* ## notes
*
* These property filters require lambda functions, and as such,
* these cannot be used from within template references in
* lex data. see {@link Lex.replaceTemplateRefs}
*/
props?: PropsFilter<TProps>;
/**
* Determines how the props predicate functions.
* @see PropertyPredicateLevel
*/
propsMode?: PropsFilterMode;
/**
* "Catchall" predicate filter that acts on the entire lex datum.
*
* So if you don't have a specific filter option in the params list, use this as
* a backup to just filter against the entire datum in a custom way.
*
* ## driving use case
*
* I want to reverse get where the `LexDatum.texts` property is exactly a
* certain value and get the reverse mapping to the "semantic id". So a user
* says some natural language, and I map that back to the possibility(s) for the
* semantic id of that user word/phrase.
*/
fnDatumPredicate?: LexDatumPredicate<TProps>;
}
/**
* Contains properties per datum that allow for more complex filtering with
* two strategies:
* 1. per property name via a lambda
* 2. per entire props object via a lambda
*
* This is the type in the LexDatum.props property.
*
* NOTE: atow this must be just a flat dictionary, i.e. cannot contain nested
* objects. However, if you want to use FilterPerProps filtering, I believe you
* can just `any` cast this and do your filtering predicate against the entire
* props object as you like.
* */
export type PropsData = {
[propName: string]: any;
};
/** This is the type used in LexGetOptions.prFilter either per property or per the entire prop data object. */
export type PropsFilter<TProps> = FilterPerProp | FilterPerProps<TProps>;
/** Individual property predicate */
export type PropertyPredicate = (propName: string) => boolean;
/** Filter on individual property level. */
export type FilterPerProp = {
[propName: string]: PropertyPredicate;
};
/** Filter at the entire props object level (`LexDatum.props`). */
export type FilterPerProps<TProps> = (props: TProps) => boolean;
export interface LexFindOptions<TProps extends PropsData = PropsData> {
fnDatumPredicate?: LexDatumPredicate<TProps>;
}
export type LexFindResults<TProps extends PropsData = PropsData> = {
[id: string]: LexDatum<TProps>[];
};
/**
* filter against the entier lex datum entry. see the LexGet options.
*/
export type LexDatumPredicate<TProps extends PropsData> = (value: LexDatum<TProps>) => boolean;
/**
* keywords are used to filter lex items. this sets how those keywords are
* interpreted.
*/
export type KeywordMode = "any" | "all" | "none";
/**
* keywords are used to filter lex items. this sets how those keywords are
* interpreted.
*/
export declare const KeywordMode: {
/** Any of the keywords must match to return a lex result. */
any: KeywordMode;
/** All of the keywords must match to return a lex result. */
all: KeywordMode;
/** Only return results that do NOT include any of the keywords. */
none: KeywordMode;
};
export type PropsFilterMode = "prop" | "props";
export declare const PropertyPredicateLevel: {
/**
* Predicate acts upon individual properties.
* So you'll pass an object in with prop key and a predicate(s).
*
* Check out advanced unit tests for more concrete examples.
*
* @example props: { id: x => x === "id2", color: x => x === "orange" }
*/
prop: PropsFilterMode;
/**
* Predicate acts upon the datum's entire props object.
* So you'll pass a single predicate that is the entire props
* object, i.e. datum[props].
*
* Check out advanced unit tests for more concrete examples.
*
* @example { props: (p: PropsData) => { return p && p.id && p.id === "id1"; }, propsMode: "props"
*/
props: PropsFilterMode;
};
/**
* Result object when using `Lex._`
*
* @see Lex
* @see Lex.get
*/
export interface LexResultObj<TProps extends PropsData = PropsData> {
/**
* The text output of the single datum that was picked.
*/
text: string;
/**
* The ssml output of the single datum that was picked.
*/
ssml: string;
/**
* The single raw datum that was picked.
*/
datum: LexDatum<TProps>;
/**
* All of the data that matched the given params (specifier,
* keywords, language, etc.)
*/
rawData: LexDatum<TProps>[];
}
export type LexCapitalize = "upperfirst" | "uppereach" | "lowerfirst" | "lowereach" | "none";
export declare const LexCapitalize: {
/**
* Uppercase the first letter of only the first line in texts/ssmls.
*/
upperfirst: LexCapitalize;
/**
* Uppercase the first letter of each line in texts/ssmls.
*/
uppereach: LexCapitalize;
/**
* Lowercase the first letter of only the first line in texts/ssmls.
*/
lowerfirst: LexCapitalize;
/**
* Lowercase the first letter of each line in texts/ssmls.
*/
lowereach: LexCapitalize;
/**
* Leave the casing as-is for texts/ssmls.
*/
none: LexCapitalize;
};
export type LexLineConcat = "paragraph" | "sentence" | "newline" | "delim";
export declare const LexLineConcat: {
/**
* Each line will be combined into a single string of paragraphs.
* @example
* ["Line 1.", "Line 2."] will become
* if text: "Line 1.\n\nLine 2."
* if ssml: "<p>Line 1.</p><p>Line 2.</p>"
*/
p: LexLineConcat;
paragraph: LexLineConcat;
/**
* Each line will be combined into a single string of sentences.
* @example
* ["Line 1.", "Line 2."] will become
* if text: "Line 1. Line 2."
* if ssml: "<s>Line 1</s><s>Line 2</s>"
*/
s: LexLineConcat;
sentence: LexLineConcat;
/**
* Each line will be combined into a single string with new
* line feeds between each line.
*
* Note: For Ssml, this is the same as "paragraph".
*
* @example
* ["Line 1.", "Line 2."] will become
* if text: "Line 1.\nLine 2."
* if ssml: "<p>Line 1.</p><p>Line 2.</p>"
*/
n: LexLineConcat;
newline: LexLineConcat;
/**
* Each line will be combined into a single string with each
* line delimited by the delimiter specified in the function.
*
* @example
* ["Line 1.", "Line 2."] with delim | will become
* if text: "Line 1.|Line 2."
* if ssml: "Line 1.|Line 2."
*/
delim: LexLineConcat;
};
export type LexData<TProps extends PropsData = PropsData> = {
[key: string]: LexDatum<TProps>[];
};
/**
* These options control mostly the default behavior for filtering lex results
* when consuming via the `Lex._(someIdentifier, opts)` call. When you don't
* specify in the `opts` how to filter, these values will be used.
*
* These options are in the constructor of the {@link Lex} class.
*/
export interface LexCtorOpts {
/**
* This is the language that your data will default to.
*
* This means that entries defined in the Lex data that do not
* have an explicit 'language' set will be interpreted as this
* language.
*
* So basically, if you're an American with American data, leave
* this as en-US. If you're a German speaker writing a skill
* that is primarily targeted at a German-speaking audience,
* then set this to de-DE and you don't need to explicitly
* set each entry to this.
*
* Then, when you go to translate into other languages, you can
* add on the explicit language markers in data. The overall
* mechanism allows you to skip this for the first language
* you write the skill in.
*
* @see requestLanguage
*/
defaultLanguage?: LanguageCode;
/**
* This is the language that is coming in from the request.
*
* @see defaultLanguage
*/
requestLanguage?: LanguageCode;
/**
* Default setting when concatenating lines. This will depend on how most of
* your data is structured. For example, it's designed so that you input
* your data separated by paragraphs, so the concat would be "paragraph".
* But if you already have data with <p> tags in your ssml, then you may
* want to set this to "delim" and do your own interpretation of using the
* multiple strings for the data.
*
* Defaults to delim & "" because most of the time, I find I
* just have a single line and want the single thing returned.
* This helps with templating, chunking, etc.
*/
defaultLineConcat?: LexLineConcat;
/**
* Default delimiter used when using `lineConcatDelim`.
*
* Defaults to delim & "" because most of the time, I find I just have a
* single line and want the single thing returned. This helps with
* templating, chunking, etc.
*/
defaultDelim?: string;
/**
* Default capitalization action when getting texts/ssmls.
*/
defaultCapitalize?: LexCapitalize;
/**
* When using keyword filtering, this is the default mode to be used
* when not explicitly set in the lex consumer.
*/
defaultKeywordMode?: KeywordMode;
/**
* When using props filtering, this is the default mode to be used
* when not explicitly set in the lex consumer.
*/
defaultPropsMode?: PropsFilterMode;
}
/**
* Imports helper that has logging, among other things.
*/
/**
* Lex is a helper for your lexical data, i.e. the things that you get
* Alexa to say. This can be used for i18n, but really it's a broader
* helper to create more dynamic speech/text for Alexa to say and
* present via cards.
*
* I am making this after learning my lessons with creating dynamic,
* alternative-laden text and/or ssml generation for use with both
* Alexa's speech, as well as outputting plain text to
* cards. I'm designing it to be (actually) simple to use, but with
* robustness allowed the more you become comfortable with it.
*
* Simple Usage
*
* To use it, you simply init what you want her to be able to say.
* Then, when you want to create her speech, you call `text` or `ssml`
* and pass in your options, the primary one being the `id`.
*
* For example, you could define the following data:
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ]}
]
}
```
* To access this, you would call `Lex._('hi').text` to simply get the
* plain text entry for "hi".
*
* Alternatives
*
* But there are a LOT of ways to say "hi", and this is the primary
* reason for using Lex: Alternatives. With Lex, multiple items with
* the same id are considered alternatives.
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ] }
]
}
```
* Again, to access this, you would call the same line:
* `Lex._('hi').text
*
* So by using the _same_ calling code, you could get any one of these
* texts as _alternatives_ for the "hi" lex datum. This is a huge
* difference between natural voice interaction and computer UI as we
* have known it up to now.
*
* If you want to get really fancy (looking forward to AI/ML), you can
* weight the various alternatives, for example if you want to only
* say "Howdy" a small percentage of the time. You could define this as follows:
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ], weighting: 0.2 }
]
}
```
* Again, there is _no_ change to the calling code. This really allows
* for a wonderful layer of dynamicism, and is easy to do.
*
* Internationalization (i18n)
*
* You can have your text be localized, but not worry about it to start
* off with. It's _implicit_ i18n. So the above examples are actually
* not really attached to any language, even though I'm writing in
* English (en-US). This is because the i18n aspect relies on both the
* data and the retrieval of the data via the `language` param option.
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ], weighting: 0.2 },
{ texts: [ "Cheers" ], language: "en-GB" },
{ texts: [ "Guten Tag" ], language: "de-DE" }
]
}
```
/**
* Lex is a helper for your lexical data, i.e. the things that you get
* Alexa to say. This can be used for i18n, but really it's a broader
* helper to create more dynamic speech/text for Alexa to say and
* present via cards.
*
* I am making this after learning my lessons with creating dynamic,
* alternative-laden text and/or ssml generation for use with both
* Alexa's speech, as well as outputting plain text to
* cards. I'm designing it to be (actually) simple to use, but with
* robustness allowed the more you become comfortable with it.
*
* Simple Usage
*
* To use it, you simply init what you want her to be able to say.
* Then, when you want to create her speech, you call `text` or `ssml`
* and pass in your options, the primary one being the `id`.
*
* For example, you could define the following data:
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ]}
]
}
```
* To access this, you would call `Lex._('hi').text` to simply get the
* plain text entry for "hi".
*
* Alternatives
*
* But there are a LOT of ways to say "hi", and this is the primary
* reason for using Lex: Alternatives. With Lex, multiple items with
* the same id are considered alternatives.
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ] }
]
}
```
* Again, to access this, you would call the same line:
* `Lex._('hi').text
*
* So by using the _same_ calling code, you could get any one of these
* texts as _alternatives_ for the "hi" lex datum. This is a huge
* difference between natural voice interaction and computer UI as we
* have known it up to now.
*
* If you want to get really fancy (looking forward to AI/ML), you can
* weight the various alternatives, for example if you want to only
* say "Howdy" a small percentage of the time. You could define this as follows:
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ], weighting: 0.2 }
]
}
```
* Again, there is _no_ change to the calling code. This really allows
* for a wonderful layer of dynamicism, and is easy to do.
*
* Internationalization (i18n)
*
* You can have your text be localized, but not worry about it to start
* off with. It's _implicit_ i18n. So the above examples are actually
* not really attached to any language, even though I'm writing in
* English (en-US). This is because the i18n aspect relies on both the
* data and the retrieval of the data via the `language` param option.
*
```
const data: LexData = {
'hi': [
{ texts: [ "Hi" ] },
{ texts: [ "Hello" ] },
{ texts: [ "Howdy" ], weighting: 0.2 },
{ texts: [ "Cheers" ], language: "en-GB" },
{ texts: [ "Guten Tag" ], language: "de-DE" }
]
}
```
*
* You can get at these languages multiple ways:
*
* 1) Choose the language when instantiating Lex.
* `let lex = new Lex(data, "de-DE");`
* Now, when you call `lex._(...)`, you will only return German
* data.
* 2) Override the default language upon calling for data:
* `lex._('hi', { language: "en-US" }).text;`
*/
export declare class Lex<TProps extends PropsData = PropsData> {
protected lc: string;
data: LexData<TProps>;
defaultLanguage: LanguageCode;
defaultLineConcat: LexLineConcat;
/**
* Defaults to delim & "" because most of the time, I find I
* just have a single line and want the single thing returned.
* This helps with templating, chunking, etc.
*
* BREAKING CHANGE: This formerly defaulted to paragraphs, as
* I thought lines would mean paragraphs. No longer the case.
*/
defaultDelim: string;
defaultCapitalize: LexCapitalize;
/**
* This is the language that is coming in from the request.
*
* @see defaultLanguage
*/
requestLanguage: LanguageCode;
defaultKeywordMode: KeywordMode;
defaultPropsMode: PropsFilterMode;
constructor(
/**
* This is the initial lexical data that you want Alexa to be able to
* say. You can always change this dynamically at runtime as well.
*/
data: LexData<TProps>,
/** optional opts */
{
/**
* This is the language that your data will default to.
* If a language isn't specified in `get`, `text`, or `ssml`, then this is used.
*
* This means that entries defined in the Lex data that do not
* have an explicit 'language' set will be interpreted as this
* language.
*
* So basically, if you're an American with American data, leave
* this as en-US. If you're a German speaker writing a skill
* that is primarily targeted at a German-speaking audience,
* then set this to de-DE and you don't need to explicitly
* set each entry to this.
*
* Then, when you go to translate into other languages, you can
* add on the explicit language markers in data. The overall
* mechanism allows you to skip this for the first language
* you write the skill in.
*
* @see requestLanguage
*/
defaultLanguage, requestLanguage,
/**
* Defaults to delim & "" because most of the time, I find I
* just have a single line and want the single thing returned.
* This helps with templating, chunking, etc.
*
* BREAKING CHANGE: This formerly defaulted to paragraphs, as
* I thought lines would mean paragraphs. No longer the case.
*/
defaultLineConcat,
/**
* Defaults to delim & "" because most of the time, I find I
* just have a single line and want the single thing returned.
* This helps with templating, chunking, etc.
*
* BREAKING CHANGE: This formerly defaulted to paragraphs, as
* I thought lines would mean paragraphs. No longer the case.
*/
defaultDelim, defaultCapitalize, defaultKeywordMode, defaultPropsMode, }: LexCtorOpts);
/**
* Gets a string or array of strings of text or ssml.
* Builds the string or obj depending on the passed in options.
*
* NOTE: You'll probably want to actually use the `text` or `ssml`
* functions instead of this one.
*
* @param id Lexical items with the same id are considered alternatives for the equivalent message, e.g. "Hello" and "Howdy".
* @see LexGetOptions
*/
get(id: string, { language, specifier, keywords, keywordMode, lineIndex, lineConcat, lineConcatDelim, capitalize, vars, ssmlVars, props, propsMode, fnDatumPredicate, }?: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* Does a reverse lookup for lex data ids that correspond to the find
* criteria.
*
* @returns array of data ids that have at least one LexDatum entry that matches criteria.
*/
find({ fnDatumPredicate }: LexFindOptions<TProps>): LexFindResults<TProps> | null;
/**
* This is the original single function. it is just for backwards compatibility at this point.
* Probably not needed...
*
* @deprecated
*/
_(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
getVariant(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
variant(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
getTranslation(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
translate(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
getSynonym(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
synonym(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
getI18n(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* just syntactic sugar for {@link Lex.get} .
*/
i18n(id: string, opts: LexGetOptions<TProps>): LexResultObj<TProps> | null;
/**
* Pulls out lines from the datum, based on the what is wanted
* and what exists in the data.
*
* For example, you may be trying to extract text but only ssml
* is defined in the data. So you'll have to strip the ssml and
* return that. Or if you want ssml and only text exists in the
* data, then you'll simply return the texts.
*
* If you only want a single line out of multiple strings in the
* texts/ssmls array, then use lineIndex.
*
* @param param0 info
*/
private extractLines;
/**
* Replaces any embedded template variables, e.g. $name, $0, etc.
* Note the format is "$" proceeded by any word characters
* ([a-zA-Z0-9_]).
*
* This is different than template references.
*
* @see {replaceTemplateRefs}
*/
private replaceTemplateVars;
/**
* Replaces any embedded template references, e.g. $(hi). Note the
* parenthesis around "hi". This means it is a reference to another lex
* datum.
*
* This is different than template variables, e.g. $name, $0, etc.
*
* The template refs can be recursive, i.e. datum A can include a ref to
* datum B which includes a template to datum C. But these cannot be
* self-referencing, i.e. C cannot then include a reference back to A.
*
* Template refs CANNOT work with props for filtering, as these require
* lambda functions.
*
* @see {replaceTemplateVars}
*/
private replaceTemplateRefs;
/**
* Capitalizes the given lines depending on the given
* capitalize options.
*
* @param param0
*/
private capitalizeLines;
/**
* Concatenates lines depending on given params.
*
* @param param0
*/
private concatLines;
/**
* Filters the given lexData per the language, specifier,
* and keywords.
*
* @param param0 Filter params
* @returns filtered datum array
*/
private filterLexData;
/**
* executes the property filter on the given (intermediate) result.
*/
private filterProps;
private filterLanguage;
/**
* Picks a randomesque datum from the given lexData, taking into
* account the weighting of each datum.
*
* @param lexData Filtered lexData from which to choose a random item, per the item's weighting
*
* @see LexDatum.weighting
*/
private pickDatum;
}
/**
* Contains a unit of speech, represented either by text, ssml, or both.
* */
export interface OutputSpeech {
/**
* A string containing the type of output speech to render. Valid types are:
* "PlainText": Indicates that the output speech is defined as plain text.
* "SSML": Indicatesthat the output speech is text marked up with SSML.
*/
type: OutputSpeechType;
/** A string containing the speech to render to the user. Use this when type is "PlainText" */
text?: string;
/** A string containing text marked up with SSML to render to the user. Use this when type is "SSML" */
ssml?: string;
}
/**
* output speech is either text or ssml.
*/
export declare type OutputSpeechType = 'PlainText' | 'SSML';
export declare const OutputSpeechType: {
/**
* Indicates that the output speech is defined as plain text.
*/
PlainText: OutputSpeechType;
/**
* Indicates that the output speech is text marked up with SSML.
*/
SSML: OutputSpeechType;
};
/**
* Builds an OutputSpeech object that contains both text and ssml. The text is
* convenient for showing information on cards, while building the ssml at the
* same time.
*
* The OutputSpeech.type is always ssml.
*/
export declare class SpeechBuilder {
private lc;
/**
* The builder accumulates speech bits and then composes these together when
* outputting.
*/
private _bits;
constructor();
/**
* Static factory function for fluent-style speech building.
*/
static with(): SpeechBuilder;
/**
* Adds a bit of speech corresponding to bare (non-ssml/tagged) text.
*
* @param text text to add to the builder
*/
text(text: string): SpeechBuilder;
/**
* Adds a bit of speech corresponding to existing ssml.
*
* NOTE: This ssml should **NOT** contain a `<speak>` tag, as this
* is not automatically stripped. Also, if you choose
* `newParagraph`, ssml should **NOT** contain any hard-coded <p>
* tags
*
* @param ssml ssml to add to the builder. See NOTE in function description.
* @param newParagraph if true, wraps ssml in <p> tags. See NOTE in function description.
*/
ssml(ssml: string, newParagraph?: boolean): SpeechBuilder;
/**
* Adds a pause (<break> tag) in the speech builder.
* Equivalent to `<break='${seconds}s'/>` ATOW.
*
* @param seconds amount of time to pause.
*/
pause(seconds: number): SpeechBuilder;
/**
* Syntactic sugar for adding text of '\n'
*/
newLine(): SpeechBuilder;
/**
* Syntactic sugar for adding text of '\n\n'
*/
newParagraph(): SpeechBuilder;
/**
* Takes text and/or ssml from existing `OutputSpeech`
* object and adds it to the builder.
*
* For example, say you already have an outputSpeech and you just
* want to add an intro text to it. You would create the builder,
* add the intro text via `text` function and then call this
* function with your existing outputSpeech.
*
* @example `let outputWithIntro = SpeechBuilder.with().text('Some intro text').existing(prevOutputSpeech).outputSpeech();`
* @param outputSpeech existing `OutputSpeech` to weave into the builder.
*/
existing(outputSpeech: OutputSpeech): SpeechBuilder;
/**
* Creates an `OutputSpeech` from the builder's state.
*/
outputSpeech({ outputType, }: {
/**
* Somewhat vestigial, originally for use with Alexa skills (I had
* created ask-gib and this builder before Amazon's sdk was created.)
*/
outputType?: OutputSpeechType;
}): OutputSpeech;
}
export declare type SpeechBitType = "text" | "ssml" | "break" | "phoneme" | "existingOutputSpeech";
export declare const SpeechBitType: {
text: SpeechBitType;
ssml: SpeechBitType;
break: SpeechBitType;
phoneme: SpeechBitType;
existingOutputSpeech: SpeechBitType;
};
/**
* OutputSpeech objects are basically just arrays of these.
*/
export interface SpeechBit {
type: SpeechBitType;
value: string | number | OutputSpeech;
}
//# sourceMappingURL=lex-helper.d.mts.map