@dpgradio/creative 5.0.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 +4 -0
- package/.eslintrc.cjs +12 -0
- package/README.md +232 -0
- package/examples/updateConfigSchema.js +27 -0
- package/examples/useApi.js +16 -0
- package/examples/useConfig.js +13 -0
- package/jest.config.cjs +195 -0
- package/package.json +31 -0
- package/src/__test__/utils/openLink.test.js +44 -0
- package/src/api/api.js +60 -0
- package/src/api/endpoints/Channels.js +7 -0
- package/src/api/endpoints/Config.js +15 -0
- package/src/api/endpoints/Endpoint.js +37 -0
- package/src/api/endpoints/Members.js +7 -0
- package/src/api/request.js +100 -0
- package/src/app/hybrid.js +107 -0
- package/src/config/config.js +60 -0
- package/src/index.js +15 -0
- package/src/privacy/dataLayer.js +73 -0
- package/src/privacy/privacy.js +100 -0
- package/src/share/ImageGeneratorProperties.js +28 -0
- package/src/share/ShareResult.js +33 -0
- package/src/share/Shareable.js +55 -0
- package/src/share.js +5 -0
- package/src/socket/SocketConnection.js +169 -0
- package/src/socket/SocketStation.js +16 -0
- package/src/socket/SocketSubscription.js +47 -0
- package/src/socket/socket.js +36 -0
- package/src/utils/cdnUrl.js +12 -0
- package/src/utils/loadScript.js +28 -0
- package/src/utils/openLink.js +14 -0
- package/src/utils/tap.js +10 -0
- package/styles/colors/joe.css +19 -0
- package/styles/colors/qmusic.css +17 -0
- package/styles/fonts/joe.css +34 -0
- package/styles/fonts/qmusic.css +48 -0
- package/styles/fonts/willy.css +2 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import SockJS from 'sockjs-client/dist/sockjs'
|
|
2
|
+
|
|
3
|
+
export default class SocketConnection {
|
|
4
|
+
constructor(host, options) {
|
|
5
|
+
this.host = host
|
|
6
|
+
this.options = options
|
|
7
|
+
|
|
8
|
+
this.lastId = 0
|
|
9
|
+
this.subscriptions = {}
|
|
10
|
+
this.authData = []
|
|
11
|
+
this.messages = []
|
|
12
|
+
this.lastAttempt = 1
|
|
13
|
+
this.reconnecting = false
|
|
14
|
+
|
|
15
|
+
this.connect()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
connect() {
|
|
19
|
+
this.socket = new SockJS(this.host)
|
|
20
|
+
|
|
21
|
+
this.socket.onopen = () => {
|
|
22
|
+
this.log('Connected')
|
|
23
|
+
|
|
24
|
+
// Reset lastAttempt counter
|
|
25
|
+
this.lastAttempt = 1
|
|
26
|
+
|
|
27
|
+
if (this.reconnecting) {
|
|
28
|
+
this._reauthenticate()
|
|
29
|
+
this._resubscribeSubscriptions()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.reconnecting = false
|
|
33
|
+
this.flushMessages()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.socket.onmessage = (event) => {
|
|
37
|
+
this.log('>>>', event.data)
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const message = JSON.parse(event.data)
|
|
41
|
+
this.processMessage(message)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
this.log('Failed to parse server response', event.data)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.socket.onclose = (event) => {
|
|
49
|
+
this.log(`Disconnected ${event.code}`, event)
|
|
50
|
+
|
|
51
|
+
// This is a technical issue, try again
|
|
52
|
+
if ([1000, 1001, 1002, 1003, 1004, 1005, 1006, 2000].includes(event.code)) {
|
|
53
|
+
this.reconnecting = true
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
this.connect()
|
|
56
|
+
}, this.lastAttempt * 1000)
|
|
57
|
+
|
|
58
|
+
this.lastAttempt *= 2
|
|
59
|
+
if (this.lastAttempt > this.options.maxRetryTimeout) {
|
|
60
|
+
this.lastAttempt = this.options.maxRetryTimeout
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
processMessage(message) {
|
|
67
|
+
if (message.action !== 'data') {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
const payload = JSON.parse(message.data)
|
|
71
|
+
|
|
72
|
+
// Contribute internal ID
|
|
73
|
+
payload._push_id = message.key || null
|
|
74
|
+
|
|
75
|
+
for (const n of message.ids) {
|
|
76
|
+
try {
|
|
77
|
+
const callback = this.subscriptions[n]?.callback
|
|
78
|
+
|
|
79
|
+
callback(payload.data, payload)
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.log(error)
|
|
82
|
+
|
|
83
|
+
if (!this.options.catchErrors) {
|
|
84
|
+
throw error
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
flushMessages() {
|
|
91
|
+
if (this.isConnected()) {
|
|
92
|
+
for (const msg of this.messages) {
|
|
93
|
+
this.send(...msg)
|
|
94
|
+
}
|
|
95
|
+
this.messages = []
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
isConnected() {
|
|
100
|
+
return this.socket.readyState === 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
send(...args) {
|
|
104
|
+
if (this.isConnected()) {
|
|
105
|
+
this.log('<<<', ...args)
|
|
106
|
+
this.socket.send(args)
|
|
107
|
+
} else {
|
|
108
|
+
this.messages.push(args)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
log(...args) {
|
|
113
|
+
if (this.options.debug) {
|
|
114
|
+
console?.log(...args)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_registerSubscription(subscription) {
|
|
119
|
+
const subscriptionId = this.lastId++
|
|
120
|
+
|
|
121
|
+
this.subscriptions[subscriptionId] = subscription
|
|
122
|
+
|
|
123
|
+
this._sendSubscription(subscription, subscriptionId)
|
|
124
|
+
|
|
125
|
+
return subscriptionId
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_registerAuthentication(authentication) {
|
|
129
|
+
this.authData.push(authentication)
|
|
130
|
+
|
|
131
|
+
this._sendAuthentication(authentication)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_unregister(id) {
|
|
135
|
+
delete this.subscriptions[id]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_sendSubscription(subscription, id) {
|
|
139
|
+
const msg = {
|
|
140
|
+
action: 'join',
|
|
141
|
+
id,
|
|
142
|
+
sub: subscription.sub,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (subscription.backlog) {
|
|
146
|
+
msg.backlog = subscription.backlog
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.send(JSON.stringify(msg))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
_sendAuthentication(params) {
|
|
153
|
+
const msg = { action: 'authenticate', ...params }
|
|
154
|
+
|
|
155
|
+
this.send(JSON.stringify(msg))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
_resubscribeSubscriptions() {
|
|
159
|
+
for (const [id, subscription] of Object.entries(this.subscriptions)) {
|
|
160
|
+
this._sendSubscription({ sub: subscription.sub }, id)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
_reauthenticate() {
|
|
165
|
+
for (const auth of this.authData) {
|
|
166
|
+
this._sendAuthentication(auth)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import SocketSubscription from './SocketSubscription'
|
|
2
|
+
|
|
3
|
+
export default class SocketStation {
|
|
4
|
+
constructor(connection, station) {
|
|
5
|
+
this.connection = connection
|
|
6
|
+
this.station = station
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
subscribe(entity) {
|
|
10
|
+
return new SocketSubscription(this.connection, this.station, entity)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
authenticate(method, authParams) {
|
|
14
|
+
this.connection._registerAuthentication({ station: this.station, method, ...authParams })
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export default class SocketSubscription {
|
|
2
|
+
constructor(connection, station, entity) {
|
|
3
|
+
this.connection = connection
|
|
4
|
+
this.station = station
|
|
5
|
+
this.entity = entity
|
|
6
|
+
|
|
7
|
+
this.callbacks = {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
subscribe(entity) {
|
|
11
|
+
this.connection.subscribe(entity)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
listen(callback, options = {}) {
|
|
15
|
+
this.on(null, callback, options)
|
|
16
|
+
|
|
17
|
+
return this
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
on(action, callback, options = {}) {
|
|
21
|
+
const id = this.connection._registerSubscription({
|
|
22
|
+
sub: {
|
|
23
|
+
station: this.station,
|
|
24
|
+
entity: this.entity,
|
|
25
|
+
action,
|
|
26
|
+
scope: options.scope,
|
|
27
|
+
},
|
|
28
|
+
callback,
|
|
29
|
+
backlog: options.backlog,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
this.callbacks[action] = id
|
|
33
|
+
|
|
34
|
+
return this
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
off(action) {
|
|
38
|
+
const id = this.callbacks[action]
|
|
39
|
+
this.connection._unregister(id)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
unsubscribe() {
|
|
43
|
+
for (const id of Object.values(this.callbacks)) {
|
|
44
|
+
this.connection._unregister(id)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import SocketConnection from './SocketConnection'
|
|
2
|
+
import SocketStation from './SocketStation'
|
|
3
|
+
|
|
4
|
+
// This is a JS rewrite of [https://github.com/medialaan/radio-sockets-server/blob/master/dist/q.coffee] with some minor additional functionality.
|
|
5
|
+
class Socket {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.connections = {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
connect(station, host = 'https://socket.qmusic.be/api', options = {}) {
|
|
11
|
+
const connectionOptions = {
|
|
12
|
+
debug: false,
|
|
13
|
+
catchErrors: false,
|
|
14
|
+
maxRetryTimeout: 10,
|
|
15
|
+
...options,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!this.connections[host]) {
|
|
19
|
+
this.connections[host] = new SocketConnection(host, connectionOptions)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return new SocketStation(this.connections[host], station)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Shortcut for subscribing to an entity action.
|
|
27
|
+
*
|
|
28
|
+
* Instead of `socket.connect('station').subscribe('entity').on('action', () => { ... })`
|
|
29
|
+
* you can use `socket.join({ station: 'station', entity: 'entity', action: 'action' }, () => { ... })`.
|
|
30
|
+
*/
|
|
31
|
+
join({ station, entity, action, options = {} }, callback) {
|
|
32
|
+
return this.connect(station).subscribe(entity).on(action, callback, options)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default new Socket()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const baseUrl = 'https://cdn-radio.dpgmedia.net'
|
|
2
|
+
|
|
3
|
+
export const cdnImageUrl = (endpoint, size = 'w480') => {
|
|
4
|
+
if (!endpoint) {
|
|
5
|
+
return null
|
|
6
|
+
}
|
|
7
|
+
return `${baseUrl}/site/${size}/${endpoint}`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const cdnUrl = (endpoint) => {
|
|
11
|
+
return `${baseUrl}/${endpoint}`
|
|
12
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// From: https://github.com/medialaan/radio-radioplayer-frontend/blob/develop/src/general/utils/loadScript.js
|
|
2
|
+
// TODO: Refactor
|
|
3
|
+
|
|
4
|
+
export default function loadScript(url, { timeout = undefined } = {}) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
let script = document.createElement('script')
|
|
7
|
+
const firstScript = document.getElementsByTagName('script')[0]
|
|
8
|
+
script.async = true
|
|
9
|
+
script.defer = true
|
|
10
|
+
|
|
11
|
+
const loadScriptTimeout = timeout ? setTimeout(() => reject(`Loading script [${url}] blocked.`), timeout) : null
|
|
12
|
+
|
|
13
|
+
const readyHandler = (_, isAbort) => {
|
|
14
|
+
if (isAbort) {
|
|
15
|
+
reject()
|
|
16
|
+
} else {
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
clearTimeout(loadScriptTimeout)
|
|
19
|
+
resolve()
|
|
20
|
+
}, 0)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
script.onload = script.onreadystatechange = readyHandler
|
|
25
|
+
script.src = url
|
|
26
|
+
firstScript.parentNode.insertBefore(script, firstScript)
|
|
27
|
+
})
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import hybrid from '../app/hybrid'
|
|
2
|
+
|
|
3
|
+
export default function openLink(url) {
|
|
4
|
+
const chromeAgent = navigator.userAgent.indexOf('Chrome') > -1
|
|
5
|
+
const safariAgent = chromeAgent ? false : navigator.userAgent.indexOf('Safari') > -1
|
|
6
|
+
|
|
7
|
+
if (hybrid.isNativeApp()) {
|
|
8
|
+
hybrid.call('navigateTo', { url, inApp: false })
|
|
9
|
+
} else if (!safariAgent) {
|
|
10
|
+
window.open(url)
|
|
11
|
+
} else {
|
|
12
|
+
window.location = url
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/utils/tap.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--joe-lime: 206 220 0;
|
|
3
|
+
|
|
4
|
+
--joe-purple: 150 4 99;
|
|
5
|
+
--joe-purple-dark: 92 29 84;
|
|
6
|
+
--joe-purple-light: 220 50 130;
|
|
7
|
+
|
|
8
|
+
--joe-green: 3 112 108;
|
|
9
|
+
--joe-green-dark: 9 76 89;
|
|
10
|
+
--joe-green-light: 20 160 140;
|
|
11
|
+
|
|
12
|
+
--joe-red: 186 22 52;
|
|
13
|
+
--joe-red-dark: 154 23 54;
|
|
14
|
+
--joe-red-light: 240 40 70;
|
|
15
|
+
|
|
16
|
+
--joe-blue: 7 77 163;
|
|
17
|
+
--joe-blue-dark: 44 45 119;
|
|
18
|
+
--joe-blue-light: 0 130 220;
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--q-red: 237 54 36;
|
|
3
|
+
--q-grey: 61 61 61;
|
|
4
|
+
--q-teal: 0 191 179;
|
|
5
|
+
--q-yellow: 249 212 35;
|
|
6
|
+
--q-purple: 210 110 230;
|
|
7
|
+
--q-green: 151 215 0;
|
|
8
|
+
--q-blue: 2 134 255;
|
|
9
|
+
|
|
10
|
+
--q-red-dark: 205 34 17;
|
|
11
|
+
--q-blue-dark: 9 0 134;
|
|
12
|
+
|
|
13
|
+
--q-blue-light: 91 194 231;
|
|
14
|
+
--q-teal-light: 184 229 209;
|
|
15
|
+
--q-grey-light: 249 249 250;
|
|
16
|
+
--q-purple-light: 244 224 249;
|
|
17
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: geomanist;
|
|
3
|
+
src: url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-light-webfont.eot), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-light-webfont.woff), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-light-webfont.woff2);
|
|
4
|
+
font-weight: 200;
|
|
5
|
+
font-style: normal
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@font-face {
|
|
9
|
+
font-family: geomanist;
|
|
10
|
+
src: url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-book-webfont.eot), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-book-webfont.woff), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-book-webfont.woff2);
|
|
11
|
+
font-weight: 300;
|
|
12
|
+
font-style: normal
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@font-face {
|
|
16
|
+
font-family: geomanist;
|
|
17
|
+
src: url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-regular-webfont.eot), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-regular-webfont.woff), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-regular-webfont.woff2);
|
|
18
|
+
font-weight: 400;
|
|
19
|
+
font-style: normal
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@font-face {
|
|
23
|
+
font-family: geomanist;
|
|
24
|
+
src: url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-medium-webfont.eot), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-medium-webfont.woff), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-medium-webfont.woff2);
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
font-style: normal
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@font-face {
|
|
30
|
+
font-family: geomanist;
|
|
31
|
+
src: url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-bold-webfont.eot), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-bold-webfont.woff), url(https://static1.qmusic.medialaancdn.be/store/static/fonts/geomanist-bold-webfont.woff2);
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
font-style: normal
|
|
34
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: Cervo;
|
|
3
|
+
src: url(https://fonts.qmusic.be/cervo-light-webfont.ttf), url(https://fonts.qmusic.be/cervo-light-webfont.eot), url(https://fonts.qmusic.be/cervo-light-webfont.woff), url(https://fonts.qmusic.be/cervo-light-webfont.woff2), url(https://fonts.qmusic.be/cervo-light-webfont.svg);
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
font-style: normal
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@font-face {
|
|
9
|
+
font-family: Cervo;
|
|
10
|
+
src: url(https://fonts.qmusic.be/cervo-medium-webfont.ttf), url(https://fonts.qmusic.be/cervo-medium-webfont.eot), url(https://fonts.qmusic.be/cervo-medium-webfont.woff), url(https://fonts.qmusic.be/cervo-medium-webfont.woff2), url(https://fonts.qmusic.be/cervo-medium-webfont.svg);
|
|
11
|
+
font-weight: 600;
|
|
12
|
+
font-style: normal
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@font-face {
|
|
16
|
+
font-family: Qarla;
|
|
17
|
+
src: url(https://fonts.qmusic.be/qarla-bold-webfont.ttf), url(https://fonts.qmusic.be/qarla-bold-webfont.eot), url(https://fonts.qmusic.be/qarla-bold-webfont.woff), url(https://fonts.qmusic.be/qarla-bold-webfont.woff2), url(https://fonts.qmusic.be/qarla-bold-webfont.svg);
|
|
18
|
+
font-weight: 700;
|
|
19
|
+
font-style: normal
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@font-face {
|
|
23
|
+
font-family: Qarla;
|
|
24
|
+
src: url(https://fonts.qmusic.be/qarla-bolditalic-webfont.ttf), url(https://fonts.qmusic.be/qarla-bolditalic-webfont.eot), url(https://fonts.qmusic.be/qarla-bolditalic-webfont.woff), url(https://fonts.qmusic.be/qarla-bolditalic-webfont.woff2), url(https://fonts.qmusic.be/qarla-bolditalic-webfont.svg);
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
font-style: italic
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@font-face {
|
|
30
|
+
font-family: Qarla;
|
|
31
|
+
src: url(https://fonts.qmusic.be/qarla-italic-webfont.ttf), url(https://fonts.qmusic.be/qarla-italic-webfont.eot), url(https://fonts.qmusic.be/qarla-italic-webfont.woff), url(https://fonts.qmusic.be/qarla-italic-webfont.woff2), url(https://fonts.qmusic.be/qarla-italic-webfont.svg);
|
|
32
|
+
font-weight: 400;
|
|
33
|
+
font-style: italic
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@font-face {
|
|
37
|
+
font-family: Qarla;
|
|
38
|
+
src: url(https://fonts.qmusic.be/qarla-regular-webfont.ttf), url(https://fonts.qmusic.be/qarla-regular-webfont.eot), url(https://fonts.qmusic.be/qarla-regular-webfont.woff), url(https://fonts.qmusic.be/qarla-regular-webfont.woff2), url(https://fonts.qmusic.be/qarla-regular-webfont.svg);
|
|
39
|
+
font-weight: 400;
|
|
40
|
+
font-style: normal
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@font-face {
|
|
44
|
+
font-family: QMarkMyWords;
|
|
45
|
+
src: url(https://fonts.qmusic.be/qmarkmywords-webfont.ttf), url(https://fonts.qmusic.be/qmarkmywords-webfont.eot), url(https://fonts.qmusic.be/qmarkmywords-webfont.woff), url(https://fonts.qmusic.be/qmarkmywords-webfont.woff2), url(https://fonts.qmusic.be/qmarkmywords-webfont.svg);
|
|
46
|
+
font-weight: 400;
|
|
47
|
+
font-style: normal
|
|
48
|
+
}
|