/src/Common/URLHelper.js

https://github.com/browserhtml/browserhtml · JavaScript · 144 lines · 49 code · 18 blank · 77 comment · 2 complexity · 42e207759d5b9308c6f9cc0efa0638fa MD5 · raw file

  1. /* @flow */
  2. /* this source code form is subject to the terms of the mozilla public
  3. * license, v. 2.0. if a copy of the mpl was not distributed with this
  4. * file, you can obtain one at http://mozilla.org/mpl/2.0/. */
  5. import {URL, nullURL} from './URL'
  6. import type {URI} from '../Common/Prelude'
  7. export const parse = (input:string):URL => {
  8. try {
  9. return new URL(input)
  10. } catch (_) {
  11. return nullURL
  12. }
  13. }
  14. export const hasScheme =
  15. (input:URI):boolean =>
  16. !!(rscheme.exec(input) || [])[0]
  17. export const getOrigin =
  18. (url:URI):string =>
  19. parse(url).origin
  20. export const getBaseURI =
  21. ():URL =>
  22. new URL('./', window.location.href)
  23. export const getHostname =
  24. (url:URI):string =>
  25. parse(url).hostname
  26. export const getDomainName =
  27. (url:URI):string =>
  28. getHostname(url).replace(/^www\./, '')
  29. export const getProtocol =
  30. (url:URI):string =>
  31. parse(url).protocol
  32. export const getManifestURL =
  33. ():URL =>
  34. new URL('./manifest.webapp', getBaseURI().href)
  35. export const getPathname =
  36. (input:URI):string =>
  37. parse(input).pathname
  38. const isHttpOrHttps = (url) => {
  39. const {protocol} = parse(url)
  40. return (protocol === 'http:' || protocol === 'https:')
  41. }
  42. export const isAboutURL =
  43. (url:URI):boolean =>
  44. parse(url).protocol === 'about:'
  45. export const isPrivileged = (uri:URI):boolean => {
  46. // FIXME: not safe. White list?
  47. return uri.startsWith(new URL('./components/About/', getBaseURI().href).href)
  48. }
  49. const rscheme = /^(?:[a-z\u00a1-\uffff0-9-+]+)(?::|:\/\/)/i
  50. export const isNotURL = (input:string):boolean => {
  51. var str = input.trim()
  52. // for cases, ?abc and 'a? b' which should searching query
  53. const case1Reg = /^(\?)|(\?.+\s)/
  54. // for cases, pure string
  55. const case2Reg = /[\?\.\s:]/
  56. // for cases, data:uri
  57. const case3Reg = /^\w+:\/*$/
  58. if (str === 'localhost') {
  59. return false
  60. }
  61. if (case1Reg.test(str) || !case2Reg.test(str) || case3Reg.test(str)) {
  62. return true
  63. }
  64. if (!hasScheme(input)) {
  65. str = 'http://' + str
  66. }
  67. try {
  68. // Electron does not throw on `new URL('foo bar')`.
  69. return new URL(str).hostname.includes('%20')
  70. } catch (e) {
  71. return true
  72. }
  73. }
  74. const readSearchURL = input =>
  75. `https://duckduckgo.com/html/?q=${encodeURIComponent(input)}`
  76. const capitilize =
  77. text =>
  78. `${text.charAt(0).toUpperCase()}${text.substr(1)}`
  79. const readAboutURL = input =>
  80. input === 'about:blank' ? input
  81. : `${getBaseURI().toString()}components/About/${capitilize(input.replace('about:', ''))}/index.html`
  82. export const read = (input:string):URI =>
  83. isNotURL(input) ? readSearchURL(input)
  84. : !hasScheme(input) ? `http://${input}`
  85. : isAboutURL(input) ? readAboutURL(input)
  86. : input
  87. export const normalize = (uri:URI):URI =>
  88. isAboutURL(uri) ? readAboutURL(uri)
  89. : uri
  90. export const resolve = (from:URI, to:URI):URI =>
  91. new URL(to, from).href
  92. const aboutPattern = /\/About\/([^\/]+)\/index.html$/
  93. const readAboutTerm = input => {
  94. const match = aboutPattern.exec(input)
  95. return match != null ? match[1] : null
  96. }
  97. export const asAboutURI = (uri:URI):?URI => {
  98. const base = getBaseURI()
  99. const {origin, pathname} = new window.URI(uri)
  100. const about = base.origin === origin ? readAboutTerm(pathname) : null
  101. return about != null ? `about:${about}` : null
  102. }
  103. // Prettify a URL for display purposes. Will minimize the amount of URL cruft.
  104. export const prettify = (input:URI):string =>
  105. // Don't mess with non-urls.
  106. (isNotURL(input)
  107. ? input
  108. // Don't mess with `about:`, `data:`, etc.
  109. : !isHttpOrHttps(input)
  110. ? input
  111. // If there's a meaningful pathname, keep it.
  112. : getPathname(input) !== '/'
  113. ? `${getHostname(input)}${getPathname(input)}`
  114. // Otherwise, just show the hostname
  115. : `${getHostname(input)}`
  116. )