<commit_before>import {
  Location,
  createBrowserHistory,
  LocationDescriptorObject
} from 'history'
import path from 'path'
import pathToRegexp from 'path-to-regexp'
import { createStoreContext } from '../utils/context'
import React, { useState, useEffect, useCallback, FC } from 'react'

export const history = createBrowserHistory()

export const storageRegexp = pathToRegexp(
  '/storages/:storageName/:rest*',
  undefined,
  {
    sensitive: true
  }
)

export const folderRegexp = pathToRegexp(
  '/storages/:storageName/notes/:rest*',
  undefined,
  {
    sensitive: true
  }
)

export const tagRegexp = pathToRegexp(
  '/storages/:storageName/tags/:tag',
  undefined,
  {
    sensitive: true
  }
)

function normalizePathname(pathname: string): string {
  const normalizedPathname = path.normalize(pathname)
  const normalizedLength = normalizedPathname.length
  if (normalizedPathname[normalizedLength - 1] === '/') {
    return normalizedPathname.slice(0, normalizedLength - 1)
  }
  return normalizedPathname
}

function normalizeLocation({ pathname, key, ...otherProps }: Location) {
  return {
    pathname: normalizePathname(pathname),
    ...otherProps
  }
}

export interface RouterStore {
  pathname: string
  search: string
  hash: string
  push: (path: string | LocationDescriptorObject<any>) => void
  replace: (path: string | LocationDescriptorObject<any>) => void
  go: (count: number) => void
  goBack: () => void
  goForward: () => void
}

const initialLocation = normalizeLocation(history.location)

function createRouteStore(): RouterStore {
  const [location, setLocation] = useState(initialLocation)

  useEffect(() => {
    const unlisten = history.listen(location => {
      setLocation(normalizeLocation(location))
    })
    return unlisten
  }, [])

  const push = useCallback(history.push, [])
  const replace = useCallback(
    (path: string | LocationDescriptorObject<any>) => {
      history.replace(path as string)
    },
    []
  )
  const go = useCallback((count: number) => {
    history.go(count)
  }, [])
  const goBack = useCallback(() => go(-1), [])
  const goForward = useCallback(() => go(1), [])

  return {
    pathname: location.pathname,
    search: location.search,
    hash: location.hash,
    push,
    replace,
    go,
    goBack,
    goForward
  }
}

export const {
  StoreProvider: RouterProvider,
  useStore: useRouter
} = createStoreContext(createRouteStore)

export interface LinkProps {
  href: string
  children: React.ReactChildren
}

export const Link: FC<LinkProps> = ({ children, href }) => {
  const router = useRouter()

  const push = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault()
      router.push(href)
    },
    [href, router]
  )

  return (
    <a onClick={push} href={href}>
      {children}
    </a>
  )
}<commit_msg>Fix Link children prop type<commit_after>import {
  Location,
  createBrowserHistory,
  LocationDescriptorObject
} from 'history'
import path from 'path'
import pathToRegexp from 'path-to-regexp'
import { createStoreContext } from '../utils/context'
import React, { useState, useEffect, useCallback, FC } from 'react'

export const history = createBrowserHistory()

export const storageRegexp = pathToRegexp(
  '/storages/:storageName/:rest*',
  undefined,
  {
    sensitive: true
  }
)

export const folderRegexp = pathToRegexp(
  '/storages/:storageName/notes/:rest*',
  undefined,
  {
    sensitive: true
  }
)

export const tagRegexp = pathToRegexp(
  '/storages/:storageName/tags/:tag',
  undefined,
  {
    sensitive: true
  }
)

function normalizePathname(pathname: string): string {
  const normalizedPathname = path.normalize(pathname)
  const normalizedLength = normalizedPathname.length
  if (normalizedPathname[normalizedLength - 1] === '/') {
    return normalizedPathname.slice(0, normalizedLength - 1)
  }
  return normalizedPathname
}

function normalizeLocation({ pathname, key, ...otherProps }: Location) {
  return {
    pathname: normalizePathname(pathname),
    ...otherProps
  }
}

export interface RouterStore {
  pathname: string
  search: string
  hash: string
  push: (path: string | LocationDescriptorObject<any>) => void
  replace: (path: string | LocationDescriptorObject<any>) => void
  go: (count: number) => void
  goBack: () => void
  goForward: () => void
}

const initialLocation = normalizeLocation(history.location)

function createRouteStore(): RouterStore {
  const [location, setLocation] = useState(initialLocation)

  useEffect(() => {
    const unlisten = history.listen(location => {
      setLocation(normalizeLocation(location))
    })
    return unlisten
  }, [])

  const push = useCallback(history.push, [])
  const replace = useCallback(
    (path: string | LocationDescriptorObject<any>) => {
      history.replace(path as string)
    },
    []
  )
  const go = useCallback((count: number) => {
    history.go(count)
  }, [])
  const goBack = useCallback(() => go(-1), [])
  const goForward = useCallback(() => go(1), [])

  return {
    pathname: location.pathname,
    search: location.search,
    hash: location.hash,
    push,
    replace,
    go,
    goBack,
    goForward
  }
}

export const {
  StoreProvider: RouterProvider,
  useStore: useRouter
} = createStoreContext(createRouteStore)

export interface LinkProps {
  href: string
  children: React.ReactNode
}

export const Link: FC<LinkProps> = ({ children, href }) => {
  const router = useRouter()

  const push = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault()
      router.push(href)
    },
    [href, router]
  )

  return (
    <a onClick={push} href={href}>
      {children}
    </a>
  )
}
{'fraction_non_alphanumeric': 0.12672566371681415, 'fraction_numerical': 0.0017699115044247787, 'mean_word_length': 3.7288702928870294, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4790163', 'n_tokens_mistral': 1743, 'n_tokens_neox': 1739, 'n_words': 408}