@hellotext/hellotext 1.4.0 → 1.5.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.
- package/.babelrc +6 -3
- package/.github/workflows/ci.yml +1 -1
- package/.prettierignore +2 -0
- package/README.md +30 -170
- package/__tests__/api/sessions_test.js +12 -0
- package/__tests__/builders/input_builder_test.js +117 -0
- package/__tests__/{event_emitter_test.js → core/event_test.js} +26 -6
- package/__tests__/hellotext_test.js +12 -0
- package/__tests__/models/business_test.js +26 -0
- package/__tests__/models/cookies_test.js +25 -0
- package/__tests__/models/form_collection_test.js +100 -0
- package/__tests__/models/form_test.js +29 -0
- package/__tests__/models/query_test.js +97 -0
- package/dist/hellotext.js +1 -1
- package/docs/forms.md +127 -0
- package/docs/tracking.md +155 -0
- package/lib/api/businesses.js +45 -0
- package/lib/api/events.js +54 -0
- package/lib/api/forms.js +65 -0
- package/lib/api/index.js +51 -0
- package/lib/api/response.js +57 -0
- package/lib/api/sessions.js +46 -0
- package/lib/api/submissions.js +61 -0
- package/lib/api.js +73 -0
- package/lib/builders/inputBuilder.js +97 -0
- package/lib/builders/input_builder.js +61 -0
- package/lib/builders/logo_builder.js +38 -0
- package/lib/builders/otp_builder.js +39 -0
- package/lib/controllers/form_controller.js +139 -0
- package/lib/controllers/otp_controller.js +114 -0
- package/lib/core/configuration.js +37 -0
- package/lib/core/event.js +73 -0
- package/lib/core/index.js +20 -0
- package/lib/errors/index.js +19 -0
- package/lib/errors/invalid_event.js +34 -0
- package/lib/errors/not_initialized_error.js +34 -0
- package/lib/event.js +159 -32
- package/lib/eventEmitter.js +139 -46
- package/lib/forms.js +133 -0
- package/lib/hellotext.js +64 -102
- package/lib/index.js +7 -0
- package/lib/locales/en.js +20 -0
- package/lib/locales/es.js +20 -0
- package/lib/locales/index.js +14 -0
- package/lib/models/business.js +57 -0
- package/lib/models/configuration.js +66 -0
- package/lib/models/cookies.js +34 -0
- package/lib/models/form.js +148 -0
- package/lib/models/form_collection.js +96 -0
- package/lib/models/index.js +40 -0
- package/lib/models/query.js +51 -0
- package/lib/models/step.js +45 -0
- package/lib/query.js +65 -32
- package/lib/response.js +82 -42
- package/package.json +7 -3
- package/src/api/businesses.js +18 -0
- package/src/api/events.js +24 -0
- package/src/api/forms.js +30 -0
- package/src/api/index.js +24 -0
- package/src/{response.js → api/response.js} +9 -4
- package/src/api/sessions.js +23 -0
- package/src/api/submissions.js +30 -0
- package/src/builders/input_builder.js +55 -0
- package/src/builders/logo_builder.js +25 -0
- package/src/builders/otp_builder.js +42 -0
- package/src/controllers/form_controller.js +105 -0
- package/src/controllers/otp_controller.js +77 -0
- package/src/core/configuration.js +16 -0
- package/src/core/event.js +54 -0
- package/src/core/index.js +2 -0
- package/src/errors/index.js +2 -0
- package/src/hellotext.js +50 -72
- package/src/index.js +10 -0
- package/src/locales/en.js +13 -0
- package/src/locales/es.js +13 -0
- package/src/locales/index.js +7 -0
- package/src/models/business.js +41 -0
- package/src/models/cookies.js +16 -0
- package/src/models/form.js +133 -0
- package/src/models/form_collection.js +81 -0
- package/src/models/index.js +5 -0
- package/src/models/query.js +33 -0
- package/styles/index.css +32 -0
- package/webpack.config.js +15 -9
- package/__tests__/event_test.js +0 -21
- package/__tests__/query_test.js +0 -13
- package/src/event.js +0 -15
- package/src/eventEmitter.js +0 -28
- package/src/query.js +0 -21
- /package/src/errors/{invalidEvent.js → invalid_event.js} +0 -0
- /package/src/errors/{notInitializedError.js → not_initialized_error.js} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import API from '../api/businesses'
|
|
2
|
+
|
|
3
|
+
import locales from '../locales'
|
|
4
|
+
|
|
5
|
+
class Business {
|
|
6
|
+
constructor(id) {
|
|
7
|
+
this.id = id
|
|
8
|
+
this.data = {}
|
|
9
|
+
this.fetchPublicData()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get subscription() {
|
|
13
|
+
return this.data.subscription
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get country() {
|
|
17
|
+
return this.data.country
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get enabledWhitelist() {
|
|
21
|
+
return this.data.whitelist !== 'disabled'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get locale() {
|
|
25
|
+
return locales[this.data.locale]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get features() {
|
|
29
|
+
return this.data.features
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// private
|
|
33
|
+
|
|
34
|
+
fetchPublicData() {
|
|
35
|
+
API.get(this.id)
|
|
36
|
+
.then(response => response.json())
|
|
37
|
+
.then(data => (this.data = data))
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { Business }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Hellotext from '../hellotext'
|
|
2
|
+
|
|
3
|
+
class Cookies {
|
|
4
|
+
static set(name, value) {
|
|
5
|
+
document.cookie = `${name}=${value}`
|
|
6
|
+
Hellotext.eventEmitter.dispatch('session-set', value)
|
|
7
|
+
|
|
8
|
+
return value
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static get(name) {
|
|
12
|
+
return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop()
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { Cookies }
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import Hellotext from '../hellotext'
|
|
2
|
+
|
|
3
|
+
import { InputBuilder } from '../builders/input_builder'
|
|
4
|
+
import { LogoBuilder } from '../builders/logo_builder'
|
|
5
|
+
|
|
6
|
+
class Form {
|
|
7
|
+
constructor(data, element = null) {
|
|
8
|
+
this.data = data
|
|
9
|
+
this.element =
|
|
10
|
+
element ||
|
|
11
|
+
document.querySelector(`[data-hello-form="${this.id}"]`) ||
|
|
12
|
+
document.createElement('form')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async mount() {
|
|
16
|
+
const firstStep = this.data.steps[0]
|
|
17
|
+
|
|
18
|
+
this.buildHeader(firstStep.header)
|
|
19
|
+
this.buildInputs(firstStep.inputs)
|
|
20
|
+
this.buildButton(firstStep.button)
|
|
21
|
+
this.buildFooter(firstStep.footer)
|
|
22
|
+
|
|
23
|
+
this.elementAttributes.forEach(attribute => {
|
|
24
|
+
this.element.setAttribute(attribute.name, attribute.value)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
if (!document.contains(this.element)) {
|
|
28
|
+
document.body.appendChild(this.element)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if(!Hellotext.business.features.white_label) {
|
|
32
|
+
this.element.prepend(LogoBuilder.build())
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
buildHeader(header) {
|
|
37
|
+
const headerElement = this.#findOrCreateComponent('[data-form-header]', 'header')
|
|
38
|
+
headerElement.innerHTML = header.content
|
|
39
|
+
|
|
40
|
+
if (this.element.querySelector('[data-form-header]')) {
|
|
41
|
+
this.element.querySelector('[data-form-header]').replaceWith(headerElement)
|
|
42
|
+
} else {
|
|
43
|
+
this.element.prepend(headerElement)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
buildInputs(inputs) {
|
|
48
|
+
const inputsContainerElement = this.#findOrCreateComponent('[data-form-inputs]', 'main')
|
|
49
|
+
const inputElements = inputs.map(input => InputBuilder.build(input))
|
|
50
|
+
|
|
51
|
+
inputElements.forEach(inputElement => inputsContainerElement.appendChild(inputElement))
|
|
52
|
+
|
|
53
|
+
if (this.element.querySelector('[data-form-inputs]')) {
|
|
54
|
+
this.element.querySelector('[data-form-inputs]').replaceWith(inputsContainerElement)
|
|
55
|
+
} else {
|
|
56
|
+
this.element
|
|
57
|
+
.querySelector('[data-form-header]')
|
|
58
|
+
.insertAdjacentHTML('afterend', inputsContainerElement.outerHTML)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
buildButton(button) {
|
|
63
|
+
const buttonElement = this.#findOrCreateComponent('[data-form-button]', 'button')
|
|
64
|
+
buttonElement.innerText = button.text
|
|
65
|
+
|
|
66
|
+
buttonElement.setAttribute('data-action', 'click->hellotext--form#submit')
|
|
67
|
+
buttonElement.setAttribute('data-hellotext--form-target', 'button')
|
|
68
|
+
|
|
69
|
+
if (this.element.querySelector('[data-form-button]')) {
|
|
70
|
+
this.element.querySelector('[data-form-button]').replaceWith(buttonElement)
|
|
71
|
+
} else {
|
|
72
|
+
this.element
|
|
73
|
+
.querySelector('[data-form-inputs]')
|
|
74
|
+
.insertAdjacentHTML('afterend', buttonElement.outerHTML)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
buildFooter(footer) {
|
|
79
|
+
const element = this.#findOrCreateComponent('[data-form-footer]', 'footer')
|
|
80
|
+
element.innerHTML = footer.content
|
|
81
|
+
|
|
82
|
+
if (this.element.querySelector('[data-form-footer]')) {
|
|
83
|
+
this.element.querySelector('[data-form-footer]').replaceWith(element)
|
|
84
|
+
} else {
|
|
85
|
+
this.element.appendChild(element)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
markAsCompleted(data) {
|
|
90
|
+
localStorage.setItem(`hello-form-${this.id}`, 'completed')
|
|
91
|
+
Hellotext.eventEmitter.dispatch('form:completed', { id: this.id, ...data })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get id() {
|
|
95
|
+
return this.data.id
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get elementAttributes() {
|
|
99
|
+
return [
|
|
100
|
+
{
|
|
101
|
+
name: 'data-controller',
|
|
102
|
+
value: 'hellotext--form',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'data-hello-form',
|
|
106
|
+
value: this.id,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'data-hellotext--form-data-value',
|
|
110
|
+
value: JSON.stringify(this.data),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'data-action',
|
|
114
|
+
value: 'hellotext--otp:verified->hellotext--form#completed',
|
|
115
|
+
},
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#findOrCreateComponent(selector, tag) {
|
|
120
|
+
const existingElement = this.element.querySelector(selector)
|
|
121
|
+
|
|
122
|
+
if (existingElement) {
|
|
123
|
+
return existingElement.cloneNode(true)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const createdElement = document.createElement(tag)
|
|
127
|
+
createdElement.setAttribute(selector.replace('[', '').replace(']', ''), '')
|
|
128
|
+
|
|
129
|
+
return createdElement
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { Form }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Hellotext from '../hellotext.js'
|
|
2
|
+
import API from '../api'
|
|
3
|
+
|
|
4
|
+
import { Form } from './form'
|
|
5
|
+
|
|
6
|
+
import { NotInitializedError } from '../errors'
|
|
7
|
+
|
|
8
|
+
class FormCollection {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.forms = []
|
|
11
|
+
|
|
12
|
+
this.includes = this.includes.bind(this)
|
|
13
|
+
this.excludes = this.excludes.bind(this)
|
|
14
|
+
|
|
15
|
+
this.add = this.add.bind(this)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
collect() {
|
|
19
|
+
if(Hellotext.notInitialized) {
|
|
20
|
+
throw new NotInitializedError()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const formsIdsToFetch = this.#formIdsToFetch
|
|
24
|
+
if (formsIdsToFetch.length === 0) return
|
|
25
|
+
|
|
26
|
+
const promises = formsIdsToFetch.map(id => {
|
|
27
|
+
return API.forms.get(id).then(response => response.json())
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
if (!Hellotext.business.enabledWhitelist) {
|
|
31
|
+
console.warn(
|
|
32
|
+
'No whitelist has been configured. It is advised to whitelist the domain to avoid bots from submitting forms.',
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Promise.all(promises)
|
|
37
|
+
.then(forms => forms.forEach(this.add))
|
|
38
|
+
.then(() => Hellotext.eventEmitter.dispatch('forms:collected', this))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
forEach(callback) {
|
|
42
|
+
this.forms.forEach(callback)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
map(callback) {
|
|
46
|
+
return this.forms.map(callback)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
add(data) {
|
|
50
|
+
if (this.includes(data.id)) return
|
|
51
|
+
this.forms.push(new Form(data))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getById(id) {
|
|
55
|
+
return this.forms.find(form => form.id === id)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getByIndex(index) {
|
|
59
|
+
return this.forms[index]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
includes(formId) {
|
|
63
|
+
return this.forms.some(form => form.id === formId)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
excludes(id) {
|
|
67
|
+
return !this.includes(id)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get length() {
|
|
71
|
+
return this.forms.length
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get #formIdsToFetch() {
|
|
75
|
+
return Array.from(document.querySelectorAll('[data-hello-form]'))
|
|
76
|
+
.map(form => form.dataset.helloForm)
|
|
77
|
+
.filter(this.excludes)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { FormCollection }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Cookies } from './cookies'
|
|
2
|
+
|
|
3
|
+
class Query {
|
|
4
|
+
static get inPreviewMode() {
|
|
5
|
+
return new this().inPreviewMode
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this.urlSearchParams = new URLSearchParams(window.location.search)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get(param) {
|
|
13
|
+
return this.urlSearchParams.get(this.toHellotextParam(param))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
has(param) {
|
|
17
|
+
return this.urlSearchParams.has(this.toHellotextParam(param))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get inPreviewMode() {
|
|
21
|
+
return this.has('preview')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get session() {
|
|
25
|
+
return this.get('session') || Cookies.get('hello_session')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toHellotextParam(param) {
|
|
29
|
+
return `hello_${param}`
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { Query }
|
package/styles/index.css
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
form[data-hello-form] {
|
|
2
|
+
position: relative;
|
|
3
|
+
|
|
4
|
+
article {
|
|
5
|
+
[data-error-container] {
|
|
6
|
+
display: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
&:has(input:invalid) {
|
|
10
|
+
[data-error-container] {
|
|
11
|
+
display: block;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
[data-logo-container] {
|
|
17
|
+
display: flex;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: flex-end;
|
|
20
|
+
position: absolute;
|
|
21
|
+
right: 1rem;
|
|
22
|
+
bottom: 1rem;
|
|
23
|
+
|
|
24
|
+
small {
|
|
25
|
+
margin: 0 .3rem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-hello-brand] {
|
|
29
|
+
width: 4rem;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/webpack.config.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
mode: 'production',
|
|
3
|
-
entry: ['whatwg-fetch', './lib/
|
|
3
|
+
entry: ['whatwg-fetch', '@hotwired/stimulus', './lib/index.js'],
|
|
4
4
|
output: {
|
|
5
|
-
filename: 'hellotext.js'
|
|
5
|
+
filename: 'hellotext.js',
|
|
6
6
|
},
|
|
7
7
|
module: {
|
|
8
8
|
rules: [
|
|
9
9
|
{
|
|
10
10
|
test: /\.m?js$/,
|
|
11
11
|
exclude: [/node_modules/],
|
|
12
|
-
use: [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
use: [
|
|
13
|
+
{
|
|
14
|
+
loader: 'babel-loader',
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
test: /\.css$/i,
|
|
20
|
+
use: ['style-loader', 'css-loader'],
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
}
|
package/__tests__/event_test.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import Event from "../src/event"
|
|
2
|
-
|
|
3
|
-
describe(".valid", function () {
|
|
4
|
-
it("is true when event name is a valid defined name", () => {
|
|
5
|
-
expect(Event.valid("session-set")).toEqual(true)
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it("is false when event name is not defined", () => {
|
|
9
|
-
expect(Event.valid("undefined-event")).toEqual(false)
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe(".invalid", () => {
|
|
14
|
-
it("is true when event name is not defined", () => {
|
|
15
|
-
expect(Event.invalid("undefined-event")).toEqual(true)
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("is false when event name is a valid defined name", () => {
|
|
19
|
-
expect(Event.invalid("session-set")).toEqual(false)
|
|
20
|
-
});
|
|
21
|
-
});
|
package/__tests__/query_test.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import Query from "../src/query";
|
|
6
|
-
|
|
7
|
-
describe("#toHellotextParameter", () => {
|
|
8
|
-
it("prefixes the argument with hello_", () => {
|
|
9
|
-
const query = new Query()
|
|
10
|
-
|
|
11
|
-
expect(query.toHellotextParam("preview")).toEqual("hello_preview")
|
|
12
|
-
});
|
|
13
|
-
})
|
package/src/event.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export default class Event {
|
|
2
|
-
static events = ["session-set"]
|
|
3
|
-
|
|
4
|
-
static valid(name) {
|
|
5
|
-
return Event.exists(name)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
static invalid(name) {
|
|
9
|
-
return !this.valid(name)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static exists(name) {
|
|
13
|
-
return this.events.find((eventName) => eventName === name) !== undefined
|
|
14
|
-
}
|
|
15
|
-
}
|
package/src/eventEmitter.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export default class EventEmitter {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.subscribers = {}
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
addSubscriber(eventName, callback) {
|
|
7
|
-
this.subscribers = {
|
|
8
|
-
...this.subscribers,
|
|
9
|
-
[eventName]: this.subscribers[eventName] ? [...this.subscribers[eventName], callback] : [callback]
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
removeSubscriber(eventName, callback) {
|
|
14
|
-
if(this.subscribers[eventName]) {
|
|
15
|
-
this.subscribers[eventName] = this.subscribers[eventName].filter((cb) => cb !== callback)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
emit(eventName, data) {
|
|
20
|
-
this.subscribers[eventName].forEach((subscriber) => {
|
|
21
|
-
subscriber(data)
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get listeners() {
|
|
26
|
-
return Object.keys(this.subscribers).length !== 0
|
|
27
|
-
}
|
|
28
|
-
}
|
package/src/query.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export default class Query {
|
|
2
|
-
constructor(urlQueries) {
|
|
3
|
-
this.urlSearchParams = new URLSearchParams(urlQueries)
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
get(param) {
|
|
7
|
-
return this.urlSearchParams.get(
|
|
8
|
-
this.toHellotextParam(param)
|
|
9
|
-
)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
has(param) {
|
|
13
|
-
return this.urlSearchParams.has(
|
|
14
|
-
this.toHellotextParam(param)
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
toHellotextParam(param) {
|
|
19
|
-
return `hello_${param}`
|
|
20
|
-
}
|
|
21
|
-
}
|
|
File without changes
|
|
File without changes
|