feat: add parser and links postproccessing

This commit is contained in:
Aidar Shaikhutdin @makeweb.space 2023-05-22 08:14:40 +06:00
parent cda646259f
commit 1b3d55843c
11 changed files with 310 additions and 55 deletions

256
package-lock.json generated
View File

@ -9,7 +9,9 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^1.9.5", "@reduxjs/toolkit": "^1.9.5",
"html-react-parser": "^3.0.16",
"i18next": "^22.5.0", "i18next": "^22.5.0",
"i18next-react-postprocessor": "^3.1.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -1531,12 +1533,74 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.376", "version": "1.4.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz",
"integrity": "sha512-TFeOKd98TpJzRHkr4Aorn16QkMnuCQuGAE6IZ0wYF+qkbSfMPqjplvRppR02tMUpVxZz8nyBNvVm9lIZsqrbPQ==", "integrity": "sha512-TFeOKd98TpJzRHkr4Aorn16QkMnuCQuGAE6IZ0wYF+qkbSfMPqjplvRppR02tMUpVxZz8nyBNvVm9lIZsqrbPQ==",
"dev": true "dev": true
}, },
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.17.18", "version": "0.17.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz",
@ -2131,6 +2195,15 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"node_modules/html-dom-parser": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-3.1.7.tgz",
"integrity": "sha512-cDgNF4YgF6J3H+d9mcldGL19p0GzVdS3iGuDNzYWQpU47q3+IRM85X3Xo07E+nntF4ek4s78A9V24EwxlPTjig==",
"dependencies": {
"domhandler": "5.0.3",
"htmlparser2": "8.0.2"
}
},
"node_modules/html-parse-stringify": { "node_modules/html-parse-stringify": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
@ -2139,6 +2212,38 @@
"void-elements": "3.1.0" "void-elements": "3.1.0"
} }
}, },
"node_modules/html-react-parser": {
"version": "3.0.16",
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-3.0.16.tgz",
"integrity": "sha512-ysQZtRFPcg+McVb4B05oNWSnqM14zagpvTgGcI5e1/BvCl38YwzWzKibrbBmXeemg70olN1bAoeixo7o06G5Eg==",
"dependencies": {
"domhandler": "5.0.3",
"html-dom-parser": "3.1.7",
"react-property": "2.0.0",
"style-to-js": "1.1.3"
},
"peerDependencies": {
"react": "0.14 || 15 || 16 || 17 || 18"
}
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/i18next": { "node_modules/i18next": {
"version": "22.5.0", "version": "22.5.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz",
@ -2161,6 +2266,18 @@
"@babel/runtime": "^7.20.6" "@babel/runtime": "^7.20.6"
} }
}, },
"node_modules/i18next-react-postprocessor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/i18next-react-postprocessor/-/i18next-react-postprocessor-3.1.0.tgz",
"integrity": "sha512-VG1k4KSEwuYQlGRtksPfcp6PXjOUCD5jRtrAW+nfAzds8ksKzTvScHt9ue7G8RPuqKS1Ctx3je1hDDd83usWVw==",
"dependencies": {
"md5-es": "^1.8.2"
},
"peerDependencies": {
"i18next": ">=8.4.3",
"react": ">=15.6.1"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.4", "version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@ -2220,6 +2337,11 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true "dev": true
}, },
"node_modules/inline-style-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -2372,6 +2494,11 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/md5-es": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/md5-es/-/md5-es-1.8.2.tgz",
"integrity": "sha512-LKq5jmKMhJYhsBFUh2w+J3C4bMiC5uQie/UYJ429UATmMnFr6iANO2uQq5HXAZSIupGp0WO2mH3sNfxR4XO40Q=="
},
"node_modules/merge2": { "node_modules/merge2": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -2693,6 +2820,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}, },
"node_modules/react-property": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
},
"node_modules/react-redux": { "node_modules/react-redux": {
"version": "8.0.5", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
@ -2973,6 +3105,22 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/style-to-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.3.tgz",
"integrity": "sha512-zKI5gN/zb7LS/Vm0eUwjmjrXWw8IMtyA8aPBJZdYiQTXj4+wQ3IucOLIOnF7zCHxvW8UhIGh/uZh/t9zEHXNTQ==",
"dependencies": {
"style-to-object": "0.4.1"
}
},
"node_modules/style-to-object": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz",
"integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==",
"dependencies": {
"inline-style-parser": "0.1.1"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -4194,12 +4342,50 @@
"esutils": "^2.0.2" "esutils": "^2.0.2"
} }
}, },
"dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"requires": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
}
},
"domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
},
"domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"requires": {
"domelementtype": "^2.3.0"
}
},
"domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"requires": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
}
},
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.376", "version": "1.4.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz",
"integrity": "sha512-TFeOKd98TpJzRHkr4Aorn16QkMnuCQuGAE6IZ0wYF+qkbSfMPqjplvRppR02tMUpVxZz8nyBNvVm9lIZsqrbPQ==", "integrity": "sha512-TFeOKd98TpJzRHkr4Aorn16QkMnuCQuGAE6IZ0wYF+qkbSfMPqjplvRppR02tMUpVxZz8nyBNvVm9lIZsqrbPQ==",
"dev": true "dev": true
}, },
"entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
"esbuild": { "esbuild": {
"version": "0.17.18", "version": "0.17.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz",
@ -4648,6 +4834,15 @@
} }
} }
}, },
"html-dom-parser": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-3.1.7.tgz",
"integrity": "sha512-cDgNF4YgF6J3H+d9mcldGL19p0GzVdS3iGuDNzYWQpU47q3+IRM85X3Xo07E+nntF4ek4s78A9V24EwxlPTjig==",
"requires": {
"domhandler": "5.0.3",
"htmlparser2": "8.0.2"
}
},
"html-parse-stringify": { "html-parse-stringify": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
@ -4656,6 +4851,28 @@
"void-elements": "3.1.0" "void-elements": "3.1.0"
} }
}, },
"html-react-parser": {
"version": "3.0.16",
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-3.0.16.tgz",
"integrity": "sha512-ysQZtRFPcg+McVb4B05oNWSnqM14zagpvTgGcI5e1/BvCl38YwzWzKibrbBmXeemg70olN1bAoeixo7o06G5Eg==",
"requires": {
"domhandler": "5.0.3",
"html-dom-parser": "3.1.7",
"react-property": "2.0.0",
"style-to-js": "1.1.3"
}
},
"htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"requires": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"i18next": { "i18next": {
"version": "22.5.0", "version": "22.5.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz",
@ -4664,6 +4881,14 @@
"@babel/runtime": "^7.20.6" "@babel/runtime": "^7.20.6"
} }
}, },
"i18next-react-postprocessor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/i18next-react-postprocessor/-/i18next-react-postprocessor-3.1.0.tgz",
"integrity": "sha512-VG1k4KSEwuYQlGRtksPfcp6PXjOUCD5jRtrAW+nfAzds8ksKzTvScHt9ue7G8RPuqKS1Ctx3je1hDDd83usWVw==",
"requires": {
"md5-es": "^1.8.2"
}
},
"ignore": { "ignore": {
"version": "5.2.4", "version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@ -4707,6 +4932,11 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true "dev": true
}, },
"inline-style-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
"is-extglob": { "is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -4820,6 +5050,11 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"md5-es": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/md5-es/-/md5-es-1.8.2.tgz",
"integrity": "sha512-LKq5jmKMhJYhsBFUh2w+J3C4bMiC5uQie/UYJ429UATmMnFr6iANO2uQq5HXAZSIupGp0WO2mH3sNfxR4XO40Q=="
},
"merge2": { "merge2": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -5027,6 +5262,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}, },
"react-property": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
},
"react-redux": { "react-redux": {
"version": "8.0.5", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
@ -5202,6 +5442,22 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true "dev": true
}, },
"style-to-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.3.tgz",
"integrity": "sha512-zKI5gN/zb7LS/Vm0eUwjmjrXWw8IMtyA8aPBJZdYiQTXj4+wQ3IucOLIOnF7zCHxvW8UhIGh/uZh/t9zEHXNTQ==",
"requires": {
"style-to-object": "0.4.1"
}
},
"style-to-object": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz",
"integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==",
"requires": {
"inline-style-parser": "0.1.1"
}
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

View File

@ -11,7 +11,9 @@
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^1.9.5", "@reduxjs/toolkit": "^1.9.5",
"html-react-parser": "^3.0.16",
"i18next": "^22.5.0", "i18next": "^22.5.0",
"i18next-react-postprocessor": "^3.1.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View File

@ -17,11 +17,6 @@ function BirthdayPage(): JSX.Element {
const navigate = useNavigate() const navigate = useNavigate()
const birthdate = useSelector(selectors.selectBirthdate) const birthdate = useSelector(selectors.selectBirthdate)
const [isDisabled, setIsDisabled] = useState(true) const [isDisabled, setIsDisabled] = useState(true)
const links = [
{ text: 'EULA', href: 'https://aura.wit.life/terms' },
{ text: 'Privacy Notice', href: 'https://aura.wit.life/privacy' },
{ text: 'here', href: 'https://aura.wit.life/' },
]
const handleNext = () => navigate(routes.client.birthtime()) const handleNext = () => navigate(routes.client.birthtime())
const handleValid = (birthdate: string) => { const handleValid = (birthdate: string) => {
dispatch(actions.form.addDate(birthdate)) dispatch(actions.form.addDate(birthdate))
@ -42,7 +37,13 @@ function BirthdayPage(): JSX.Element {
{t('next')} {t('next')}
</MainButton> </MainButton>
<footer className='footer'> <footer className='footer'>
<Policy links={links}>{t('privacy_text')}</Policy> <Policy>
{t('privacy_text', {
eulaLink: <a href='https://aura.wit.life/terms' target='_blank' rel='noopener noreferrer'>{t('eula')}</a>,
privacyLink: <a href='https://aura.wit.life/privacy' target='_blank' rel='noopener noreferrer'>{t('privacy_notice')}</a>,
clickHere: <a href='https://aura.wit.life/' target='_blank' rel='noopener noreferrer'>{t('here')}</a>,
})}
</Policy>
<Purposes /> <Purposes />
</footer> </footer>
</section> </section>

View File

@ -27,10 +27,6 @@ function EmailEnterPage(): JSX.Element {
const [error, setError] = useState<Error | null>(null) const [error, setError] = useState<Error | null>(null)
const timezone = getClientTimezone() const timezone = getClientTimezone()
const locale = i18n.language const locale = i18n.language
const links = [
{ text: 'EULA', href: 'https://aura.wit.life/terms' },
{ text: 'Privacy Policy', href: 'https://aura.wit.life/privacy' },
]
const handleValidEmail = (email: string) => { const handleValidEmail = (email: string) => {
dispatch(actions.form.addEmail(email)) dispatch(actions.form.addEmail(email))
setIsDisabled(false) setIsDisabled(false)
@ -66,7 +62,12 @@ function EmailEnterPage(): JSX.Element {
onInvalid={() => setIsDisabled(true)} onInvalid={() => setIsDisabled(true)}
/> />
<p>{t('we_dont_share')}</p> <p>{t('we_dont_share')}</p>
<Policy links={links} sizing='medium'>{t('continue_agree')}</Policy> <Policy sizing='medium'>
{t('continue_agree', {
eulaLink: <a href='https://aura.wit.life/terms' target='_blank' rel='noopener noreferrer'>{t('eula')}</a>,
privacyLink: <a href='https://aura.wit.life/privacy' target='_blank' rel='noopener noreferrer'>{t('privacy_policy')}</a>,
})}
</Policy>
<MainButton onClick={handleClick} disabled={isDisabled}> <MainButton onClick={handleClick} disabled={isDisabled}>
{isLoading ? <Loader color={LoaderColor.White} /> : t('continue')} {isLoading ? <Loader color={LoaderColor.White} /> : t('continue')}
</MainButton> </MainButton>

View File

@ -1,3 +1,4 @@
import { useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { useAuth } from '../../auth' import { useAuth } from '../../auth'
import { useLegal } from '../../legal' import { useLegal } from '../../legal'
@ -13,6 +14,7 @@ const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1)
function Navbar({ isOpen, closeMenu }: NavbarProps): JSX.Element { function Navbar({ isOpen, closeMenu }: NavbarProps): JSX.Element {
const { logout } = useAuth() const { logout } = useAuth()
const { t } = useTranslation()
const legal = useLegal() const legal = useLegal()
const combinedClassNames = ['navbar', isOpen && 'navbar--open'].filter(Boolean).join(' ') const combinedClassNames = ['navbar', isOpen && 'navbar--open'].filter(Boolean).join(' ')
return ( return (
@ -31,7 +33,10 @@ function Navbar({ isOpen, closeMenu }: NavbarProps): JSX.Element {
{capitalize(item.title)} {capitalize(item.title)}
</Link> </Link>
))} ))}
<a href='#' onClick={closeMenu}>Contact us</a> <a href='https://aura.wit.life/' onClick={closeMenu} target='_blank' rel='noopener noreferrer'>
{t('contact_us')}
</a>
<hr />
<a href='#' onClick={logout}>Log Out</a> <a href='#' onClick={logout}>Log Out</a>
</nav> </nav>
</div> </div>

View File

@ -57,7 +57,9 @@ function PaymentPage(): JSX.Element {
<img className='payment-card' src={card} alt='Credit / Debit Card' /> <img className='payment-card' src={card} alt='Credit / Debit Card' />
{t('card')} {t('card')}
</MainButton> </MainButton>
<p className='payment-warining'>You will be charged only <strong>$1 for your 7-day trial</strong>. We'll email your a reminder before your trial period ends.</p> <p className='payment-warining'>
{t('will_be_charged', { strongText: <strong>{t('trial_price')}</strong> })}
</p>
</> </>
)} )}
</section> </section>

View File

@ -1,13 +1,6 @@
import { ReactNode } from 'react'
import './styles.css' import './styles.css'
type Link = {
text: string
href: string
}
interface PolicyProps { interface PolicyProps {
links: Link[]
children: string children: string
sizing?: 'small' | 'medium' | 'large' sizing?: 'small' | 'medium' | 'large'
} }
@ -18,26 +11,10 @@ const sizes = {
large: 'policy--large', large: 'policy--large',
} }
function Policy({ links, children, sizing = 'small' }: PolicyProps): JSX.Element { function Policy({ children, sizing = 'small' }: PolicyProps): JSX.Element {
const createLinkedContent = (sentence: string): ReactNode[] => {
const pattern = links.map(link => `(${link.text})`).join('|');
const regex = new RegExp(pattern, 'g');
return sentence.split(regex).map((part, idx) => {
const link = links.find(({ text }) => text === part);
if (!link) return part
return (
<a key={`${link.text}-${idx}`} href={link.href} target="_blank" rel="noreferrer nofollow">
{link.text}
</a>
);
});
}
return ( return (
<div className={`policy ${sizes[sizing]}`}> <div className={`policy ${sizes[sizing]}`}>
<p>{createLinkedContent(children)}</p> <p>{children}</p>
</div> </div>
) )
} }

View File

@ -2,6 +2,7 @@ import { useParams } from 'react-router'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useApi, useApiCall, Element } from '../../api' import { useApi, useApiCall, Element } from '../../api'
import { useCallback } from 'react' import { useCallback } from 'react'
import parse from 'html-react-parser'
import Loader from '../Loader' import Loader from '../Loader'
import NotFoundPage from '../NotFoundPage' import NotFoundPage from '../NotFoundPage'
import './styles.css' import './styles.css'
@ -20,7 +21,7 @@ function StaticPage(): JSX.Element {
return ( return (
<section className='page page-static'> <section className='page page-static'>
{isPending ? <Loader /> : <div className='page-static__content' dangerouslySetInnerHTML={{ __html: data?.body }} />} {isPending ? <Loader /> : <div className='page-static__content'>{parse(data?.body)}</div>}
{error && <NotFoundPage />} {error && <NotFoundPage />}
</section> </section>
) )

View File

@ -14,9 +14,6 @@ function SubscriptionPage(): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
const navigate = useNavigate() const navigate = useNavigate()
const email = useSelector(selectors.selectEmail) const email = useSelector(selectors.selectEmail)
const links = [
{ text: 'Subscription policy', href: 'https://aura.wit.life/' },
]
const currency = Currency.USD const currency = Currency.USD
const locale = Locale.EN const locale = Locale.EN
const paymentItems = [ const paymentItems = [
@ -35,7 +32,11 @@ function SubscriptionPage(): JSX.Element {
<Countdown start={10}/> <Countdown start={10}/>
<Payment items={paymentItems} currency={currency} locale={locale}/> <Payment items={paymentItems} currency={currency} locale={locale}/>
<MainButton onClick={handleClick}>{t('get_access')}</MainButton> <MainButton onClick={handleClick}>{t('get_access')}</MainButton>
<Policy links={links}>{t('subscription_policy')}</Policy> <Policy>
{t('subscription_text', {
policyLink: <a href='https://aura.wit.life/' target='_blank' rel='noopener noreferrer'>{t('subscription_policy')}</a>,
})}
</Policy>
</section> </section>
</> </>
) )

View File

@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import i18next from 'i18next' import i18next from 'i18next'
import ReactPostprocessor from 'i18next-react-postprocessor'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import { I18nextProvider, initReactI18next } from 'react-i18next' import { I18nextProvider, initReactI18next } from 'react-i18next'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
@ -17,8 +18,8 @@ const init = async () => {
const resources = buildResources(response) const resources = buildResources(response)
const legal = buildLegal(response) const legal = buildLegal(response)
const i18nextInstance = i18next.createInstance() const i18nextInstance = i18next.createInstance()
const options = { lng, resources, fallbackLng } const options = { lng, resources, fallbackLng, postProcess: [ `reactPostprocessor` ] }
await i18nextInstance.use(initReactI18next).init(options) await i18nextInstance.use(initReactI18next).use(new ReactPostprocessor()).init(options)
return ( return (
<React.StrictMode> <React.StrictMode>
<I18nextProvider i18n={i18nextInstance}> <I18nextProvider i18n={i18nextInstance}>

View File

@ -3,7 +3,10 @@ export default {
lets_start: "Let's start!", lets_start: "Let's start!",
next: "Next", next: "Next",
date_of_birth: "What's your date of birth?", date_of_birth: "What's your date of birth?",
privacy_text: "By continuing, you agree to our EULA and Privacy Notice. Have a question? Reach our support team here", privacy_text: "By continuing, you agree to our <eulaLink> and <privacyLink>. Have a question? Reach our support team <clickHere>",
eula: 'EULA',
here: 'here',
privacy_notice: 'Privacy Notice',
born_time_question: "What time were you born?", born_time_question: "What time were you born?",
nasa_data_using: "We use NASA data to determine the exact position of the planets in the sky at the time of your birth to create wallpapers that are just right for you.", nasa_data_using: "We use NASA data to determine the exact position of the planets in the sky at the time of your birth to create wallpapers that are just right for you.",
cta_title: "Start your 7-day trial", cta_title: "Start your 7-day trial",
@ -20,19 +23,24 @@ export default {
we_will_email_you: "We will email you a copy of your wallpaper for easy access.", we_will_email_you: "We will email you a copy of your wallpaper for easy access.",
your_email: "Your email", your_email: "Your email",
we_dont_share: "We don't share any personal information.", we_dont_share: "We don't share any personal information.",
continue_agree: 'By clicking "Continue" below, you agree to our EULA and Privacy Policy.', continue_agree: 'By clicking "Continue" below, you agree to our <eulaLink> and <privacyLink>.',
privacy_policy: "Privacy Policy",
continue: 'Continue', continue: 'Continue',
app_name: "Aura", app_name: "Aura",
unexpected_error: 'Sorry, an unexpected error has occurred.', unexpected_error: 'Sorry, an unexpected error has occurred.',
oops: "Oops!", oops: "Oops!",
total_today: 'Total today', total_today: "Total today",
charged_only: "You will be charged only $1 for your 7-day trial. We'll email you a reminder before your trial period ends. Cancel anytime.", charged_only: "You will be charged only $1 for your 7-day trial. We'll email you a reminder before your trial period ends. Cancel anytime.",
purposes: 'For entertaiment purposes only.', purposes: "For entertaiment purposes only.",
get_access: 'Get access', get_access: "Get access",
subscription_policy: 'By proceeding, you agree that if you do not cancel your subscription before the end of the 7-day trial period, you will be automatically charged nineteen US dollars zero cents every 2 weeks until you cancel the subscription in the settings. Learn more about cancellation and refund policy in Subscription policy', subscription_text: "By proceeding, you agree that if you do not cancel your subscription before the end of the 7-day trial period, you will be automatically charged nineteen US dollars zero cents every 2 weeks until you cancel the subscription in the settings. Learn more about cancellation and refund policy in <policyLink>",
company_name: 'Wit LLC, California, US', subscription_policy: "Subscription policy",
choose_payment: 'Choose Payment Method', company_name: "Wit LLC, California, US",
or: 'OR', choose_payment: "Choose Payment Method",
card: 'Credit / Debit Card', or: "OR",
card: "Credit / Debit Card",
contact_us: "Contact us",
will_be_charged: "You will be charged only <strongText>. We'll email your a reminder before your trial period ends.",
trial_price: "$1 for your 7-day trial",
}, },
} }