{"version":3,"sources":["About.js","sofa.svg","Intro.js","AboutMe.js","Friends.js","Images.js","Raw.js","trustroots-tree.svg","Profile.js","App.js","index.js","utils.js","components.js"],"names":["FaqHeading","children","id","className","href","onClick","scrollToElementById","title","About","isDragActive","input","role","Intro","src","sofa","alt","event","stopPropagation","ProfileContent","profile","interests","about_me","dangerouslySetInnerHTML","__html","marked","map","interest","name","media","teach","amazing_thing","surf_reason","offer_hosts","AboutMe","user","text","document","querySelector","textContent","console","log","CopyToClipboard","format","TrustrootsSearch","search","label","target","rel","FriendList","list","listHasNames","some","displayName","username","classnames","Friends","friends","names","friendIds","friend","parseInt","replace","has","get","unknownFriends","filter","knownFriends","length","Images","images","blobUrl","download","Raw","json","data","Messages","lazy","References","Profile","fileDate","user_data","references","messages","routes","route","count","written_references","received_references","formatDate","first_name","last_name","occupation","window","sessionStorage","clear","error","Sentry","exact","path","fallback","userId","TrustrootsTree","async","extractZip","file","zip","jszip","loadAsync","files","relativePath","zipEntry","dir","split","pop","jsonString","JSON","parse","getJsonFromZip","imageProcessor","includes","blob","URL","webkitURL","createObjectURL","Promise","all","getImagesFromZip","getNamesFromJson","Map","collectName","visit","person","surfer","host","display_name","set","couch_visits","host_couch_visits","forEach","surfer_couch_visits","setCacheValue","key","value","setItem","scrollTop","body","documentElement","App","isStorageAvailable","testStorage","cachedFileDate","cachedNames","cachedProfile","cachedProfileImages","getItem","loadFromCache","setProfile","useState","profileImages","setProfileImages","setNames","setFileDate","isProcessing","setIsProcessing","useEffect","stringify","onDrop","useCallback","acceptedFiles","alert","type","lastModifiedDate","toString","jsonProfile","resolve","reject","fr","FileReader","onload","result","readAsText","readBlobFile","getRootProps","getInputProps","useDropzone","dsn","couchspinner_settings","sentry","ReactDOM","render","StrictMode","getElementById","date","dateString","formattedDate","Date","toLocaleDateString","undefined","year","month","day","preventDefault","hash","el","history","pushState","scrollIntoView","behavior","storage","x","removeItem","e","DOMException","code","Section","Heading","Content","props","Loading","CsProfileLink","CsProfileName","append","Tabs","activeClassName","to","Button"],"mappings":"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","file":"static/js/main.07b6b0c6.chunk.js","sourcesContent":["import React from 'react';\n\nimport { scrollToElementById } from './utils';\nimport './About.css';\n\nfunction FaqHeading({ children, id }) {\n return (\n

\n \n #\n \n {children}\n

\n );\n}\n\nfunction About({ isDragActive, input }) {\n return (\n
\n

About

\n\n
\n \n How can I export my CouchSurfing profile?{' '}\n \n

\n If you can still access your profile,{' '}\n \n follow these instructions to download your data\n \n .\n

\n

\n If you cannot access your profile, you can ask for a copy of your data\n and to delete your account by contacting Couchsurfing Support at{' '}\n support@couchsurfing.com{' '}\n or through{' '}\n privacy@couchsurfing.com\n .\n

\n\n \n Why CouchSpinner exists?\n \n

\n CouchSurfing locked out a significant portion of their community by{' '}\n \n turning into a paid site overnight\n {' '}\n on May 14, 2020.\n

\n

\n You can recover your data from CouchSurfing, but what can you do with\n it then?\n

\n

\n With CouchSpinner, you can preview your profile, references, and\n messages again!\n

\n\n Who made this?\n

\n Folks behind{' '}\n \n Trustroots.org\n \n , a free and community-run hospitality exchange site you can use\n instead of CouchSurfing.\n

\n

\n We built the functionality anyway for Trustroots and wanted to give it\n away for everyone.\n

\n

\n We'd love it if you would also join Trustroots, of course!{' '}\n \n 🙂\n \n

\n\n \n Do you store my CouchSurfing profile?{' '}\n \n

\n Nope. Your profile is never uploaded to us — we never see it.\n Everything happens in your browser only. This is completely secure.\n

\n\n It didn't work!\n

\n Oh no!{' '}\n Please get in touch{' '}\n with Mikael to see if we can help.\n

\n\n \n What are other alternatives to CouchSurfing?\n \n

\n You could check{' '}\n \n Trustroots\n \n , BeWelcome,{' '}\n Warmshowers, and{' '}\n Hackercouch.\n

\n\n \n I see only some names, but not everyone?\n \n

\n Most of the Couchsurfing export doesn't contain names of other\n profiles, only user IDs. There are a few names available from \"couch\n requests\", which then we can show elsewhere too.\n

\n\n \n Not all my data is here!\n \n

\n Could be! Please check the \"raw\" tab of your profile to see what the\n file actually contains and what we are showing.\n

\n

\n The preview doesn't show everything, but also the file from\n CouchSurfing could be only partial. They've elaborated that{' '}\n \n some of the very old data might've been lost\n \n . You should reach out to CouchSurfing for any specifics, though.\n

\n\n Is this open-source?\n

\n Yep! Feel free\n to help out.\n

\n\n \n Can I download images and profiles of my friends?\n \n

\n Yes! See the{' '}\n \n scripts\n {' '}\n that you can use directly from your computer to download your\n Couchsurfing friend's profiles and images. You also need some\n technical know-how. 😉\n

\n
\n
\n );\n}\n\nexport default About;\n","export default __webpack_public_path__ + \"static/media/sofa.c73c213a.svg\";","import React from 'react';\n\nimport './Intro.scss';\nimport { scrollToElementById } from './utils';\nimport sofa from './sofa.svg';\n\nfunction Intro() {\n return (\n
\n

CouchSpinner

\n

\n Preview Couchsurfing profile export files.{' '}\n \n Read more…\n \n

\n {/* https://www.flaticon.com/free-icon/sofa_2965901?term=sofa&page=1&position=39 */}\n \"logo\"\n \n

\n \n How do I get CouchSurfing profile export file?\n \n
\n
\n event.stopPropagation()}\n href=\"https://www.trustroots.org/?ref=couchspinner&ref-location=intro\"\n >\n By Trustroots.org\n \n

\n
\n );\n}\n\nexport default Intro;\n","import CopyToClipboard from 'copy-to-clipboard';\nimport { marked } from 'marked';\nimport React from 'react';\n// import ReactDOMServer from 'react-dom/server';\n\nimport { Section, Heading, Content, Button } from './components';\nimport './AboutMe.scss';\n\nfunction ProfileContent({ profile, interests }) {\n if (!profile) {\n return

Your profile looks empty!

;\n }\n\n return (\n <>\n {profile?.about_me && (\n \n )}\n {profile?.about_me && (\n \n )}\n {profile?.interests && (\n <>\n

\n More about my interests\n

\n \n {interests?.interests && (\n
    \n {interests.interests.map(interest => (\n
  • {interest.name}
  • \n ))}\n
\n )}\n \n )}\n {profile?.media && (\n <>\n

\n My Favorite Music, Movies & Books\n

\n \n \n )}\n {profile?.teach && (\n <>\n

\n Teach, Learn, Share\n

\n \n \n )}\n {profile?.amazing_thing && (\n <>\n

\n One Amazing Thing I've Done\n

\n \n \n )}\n {profile?.surf_reason && (\n <>\n

\n Why I'm on Couchsurfing\n

\n \n \n )}\n {profile?.offer_hosts && (\n <>\n

\n What I Can Share With Hosts\n

\n \n \n )}\n \n );\n}\n\nfunction AboutMe({ user, interests }) {\n const copy = () => {\n /*\n // Generate static HTML from React component\n const profileElement = ProfileContent({profile: user?.profile, interests});\n const html = ReactDOMServer.renderToString(profileElement);\n\n // Strip out HTML for copying\n // @TODO: this losts newlines :-( https://stackoverflow.com/a/50230647\n // @TODO: can we preserve some HTML and copy-paste that to Trustroots?\n const div = document.createElement('div');\n div.innerHTML = html;\n const text = div.textContent || div.innerText || '';\n */\n\n const text = document.querySelector('.Section-content').textContent;\n console.log('text:', text);\n CopyToClipboard(text, {\n format: 'text/plain',\n });\n };\n\n return (\n
\n \n About me\n \n \n \n \n \n
\n );\n}\n\nexport default AboutMe;\n","import React from 'react';\nimport classnames from 'classnames';\n\nimport { Section, Heading, Content, CsProfileLink } from './components';\nimport './Friends.scss';\n\nfunction TrustrootsSearch({ search, label }) {\n return (\n search && (\n \n {label}\n \n )\n );\n}\n\nfunction FriendList({ className, list }) {\n // Does at least one friend on the list have name or username?\n const listHasNames = list.some(\n ({ displayName, username }) => displayName || username,\n );\n\n return (\n
    \n {listHasNames && (\n
  • \n We had their names from couch requests:\n \n Search them on Trustroots:\n \n
  • \n )}\n {list.map(({ id, displayName, username }) => {\n return (\n
  • \n \n \n {displayName || username || `Member ${id}`}\n {username && ` (${username})`}\n \n \n {(displayName || username) && (\n \n \n Search on Trustroots{' '}\n \n {displayName && (\n \n )}\n {displayName && username && ' or '}\n {username && (\n \n )}\n \n )}\n
  • \n );\n })}\n
\n );\n}\n\nfunction Friends({ friends, names }) {\n const friendIds = friends.map(friend => {\n const id = parseInt(\n friend.profile.replace('https://www.couchsurfing.com/users/', ''),\n 10,\n );\n const { displayName, username } = names.has(id) ? names.get(id) : {};\n return {\n displayName,\n id,\n username,\n };\n });\n\n const unknownFriends = friendIds.filter(({ displayName }) => !displayName);\n const knownFriends = friendIds.filter(({ displayName }) => displayName);\n\n return (\n
\n Friends\n \n {!friendIds.length === 0 &&

No friends. :-(

}\n {knownFriends.length > 0 && (\n <>\n

Known friends

\n \n \n )}\n {unknownFriends.length > 0 && (\n <>\n

Unknown friends

\n

\n Your export file does not have names for these members.\n
\n \n Some of their profiles might be public so you could try see whom\n they are.\n \n

\n \n \n )}\n
\n
\n );\n}\n\nexport default Friends;\n","import React from 'react';\n\nimport { Content, Section, Heading } from './components';\nimport './Images.css';\n\nfunction Images({ images }) {\n return (\n
\n Images\n \n {images.length ? (\n images.map(({ id, blobUrl }) => (\n

\n \n \"\"\n \n

\n ))\n ) : (\n

You had no images… :-(

\n )}\n
\n
\n );\n}\n\nexport default Images;\n","import React from 'react';\nimport JsonTree from 'react-json-tree';\n\nimport { Section, Heading } from './components';\n\nfunction Raw({ json }) {\n return (\n
\n Raw profile export\n \n
\n );\n}\n\nexport default Raw;\n","export default __webpack_public_path__ + \"static/media/trustroots-tree.b1f8bf95.svg\";","import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';\nimport * as Sentry from '@sentry/browser';\nimport React, { Suspense, lazy } from 'react';\n\nimport './Profile.scss';\nimport { formatDate } from './utils';\nimport { Section, CsProfileLink, Tabs, Loading, Button } from './components';\nimport AboutMe from './AboutMe';\nimport Friends from './Friends';\nimport Images from './Images';\nimport Raw from './Raw';\nimport TrustrootsTree from './trustroots-tree.svg';\n\n// Slow rendering elements\nconst Messages = lazy(() => import('./Messages'));\nconst References = lazy(() => import('./References'));\n\nfunction Profile({ fileDate, images, names, profile }) {\n const { user_data: user, interests, references, friends, messages } = profile;\n\n const referencesCount =\n (references?.written_references?.length ?? 0) +\n (references?.received_references?.length ?? 0);\n const friendsCount = friends?.friends?.length ?? 0;\n const messagesCount = messages?.messages?.length ?? 0;\n const imagesCount = images?.length ?? 0;\n const routes = [\n { route: '/', label: 'About me' },\n { route: '/references', label: 'References', count: referencesCount },\n { route: '/friends', label: 'Friends', count: friendsCount },\n { route: '/messages', label: 'Messages', count: messagesCount },\n { route: '/images', label: 'Images', count: imagesCount },\n { route: '/raw', label: 'Raw' },\n ];\n\n const clearSessionStorage = () => {\n try {\n window.sessionStorage.clear();\n } catch (error) {\n Sentry.captureException(error);\n console.error(error);\n }\n };\n\n return (\n \n
\n
\n
\n \n \n Your Couchsurfing.com profile\n \n {fileDate && ` as of ${formatDate(fileDate)}`}\n \n

\n {user?.profile?.first_name && `${user.profile.first_name} `}\n {user?.profile?.last_name && `${user.profile.last_name} `}\n {user?.username && `(${user.username})`}\n

\n {user?.profile?.occupation &&

{user.profile.occupation}

}\n
\n
\n \n Clear out the profile\n \n \n Sign up Trustroots.org\n \n
\n
\n\n
\n \n
\n\n \n \n \n \n \n References}>\n \n \n \n \n \n \n \n Messages}>\n \n \n \n \n \n \n \n \n \n \n\n
\n \n \"Trustroots\"\n
\n Join Trustroots.org\n
\n Travellers hospitality community.\n \n
\n
\n
\n );\n}\n\nexport default Profile;\n","import { useDropzone } from 'react-dropzone';\nimport * as Sentry from '@sentry/browser';\nimport classnames from 'classnames';\nimport jszip from 'jszip';\nimport React, { useCallback, useState, useEffect } from 'react';\n\nimport './App.scss';\nimport About from './About';\nimport Intro from './Intro';\nimport Profile from './Profile';\nimport { testStorage } from './utils';\nimport { STORAGE_PREFIX } from './constants';\n// import example from './example-profile.json';\nconst EXAMPLE_PROFILE = '';\n\nasync function getJsonFromZip(zip) {\n const files = zip.filter((relativePath, zipEntry) => {\n return !zipEntry.dir && zipEntry.name.split('.').pop() === 'json';\n });\n\n if (!files.length) {\n return false;\n }\n\n const jsonString = await zip.file(files[0].name).async('string');\n\n try {\n const json = JSON.parse(jsonString);\n return json;\n } catch (error) {\n Sentry.captureException(error);\n return false;\n }\n}\n\nasync function getImagesFromZip(zip) {\n const files = zip.filter((relativePath, zipEntry) => {\n return (\n !zipEntry.dir &&\n ['jpg', 'gif', 'png'].includes(zipEntry.name.split('.').pop())\n );\n });\n\n const imageProcessor = files.map(async file => {\n const blob = await zip.file(file.name).async('blob');\n const urlCreator = window.URL || window.webkitURL;\n const blobUrl = urlCreator.createObjectURL(blob);\n\n return {\n blobUrl,\n id: file.name,\n };\n });\n\n const images = await Promise.all(imageProcessor);\n\n return images;\n}\n\nasync function extractZip(file) {\n const zip = await jszip.loadAsync(file);\n const json = await getJsonFromZip(zip);\n const images = await getImagesFromZip(zip);\n\n return {\n images,\n json,\n };\n}\n\nfunction getNamesFromJson(json) {\n const names = new Map();\n\n const collectName = visit => {\n const person = visit?.surfer || visit?.host || {};\n const username = person?.username;\n const id = person?.profile?.id;\n const displayName = person?.profile?.display_name;\n names.set(id, { displayName, username });\n };\n\n if (json?.couch_visits?.host_couch_visits) {\n json.couch_visits.host_couch_visits.forEach(collectName);\n }\n\n if (json?.couch_visits?.surfer_couch_visits) {\n json.couch_visits.surfer_couch_visits.forEach(collectName);\n }\n\n return names;\n}\n\nfunction setCacheValue(key, value) {\n try {\n window.sessionStorage.setItem(`${STORAGE_PREFIX}_${key}`, value);\n } catch (error) {\n Sentry.captureException(error);\n console.error(`Saving ${key} in cache failed:`, error);\n }\n}\n\n/**\n * Read file from Blob or File entry\n * @param {[File|Blob]}\n * @return {[String]} Text contents of the File\n */\nfunction readBlobFile(file) {\n // Browser supports Blob.text(), all good!\n // https://developer.mozilla.org/en-US/docs/Web/API/Blob/text\n if (typeof file.text === 'function') {\n return file.text();\n }\n\n // Namely Safari needs this\n // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsText\n // https://stackoverflow.com/a/46568146\n return new Promise((resolve, reject) => {\n var fr = new FileReader();\n fr.onload = () => {\n resolve(fr.result);\n };\n fr.readAsText(file);\n });\n}\n\n/**\n * Load previously cached items\n * @return {[Object]}\n */\nfunction loadFromCache() {\n let cachedFileDate;\n let cachedNames;\n let cachedProfile;\n let cachedProfileImages;\n try {\n cachedFileDate = window.sessionStorage.getItem(\n `${STORAGE_PREFIX}_file_date`,\n );\n cachedProfile = JSON.parse(\n window.sessionStorage.getItem(`${STORAGE_PREFIX}_profile`),\n );\n cachedProfileImages = JSON.parse(\n window.sessionStorage.getItem(`${STORAGE_PREFIX}_profile_images`),\n );\n\n if (cachedProfile) {\n cachedNames = getNamesFromJson(cachedProfile);\n }\n } catch (error) {\n Sentry.captureException(error);\n console.error(error);\n }\n\n return {\n cachedFileDate,\n cachedNames,\n cachedProfile,\n cachedProfileImages,\n };\n}\n\nfunction scrollTop() {\n document.body.scrollTop = 0; // For Safari\n document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera\n}\n\nfunction App() {\n const isStorageAvailable = testStorage('sessionStorage');\n\n const { cachedFileDate, cachedNames, cachedProfile, cachedProfileImages } =\n isStorageAvailable ? loadFromCache() : {};\n\n const [profile, setProfile] = useState(cachedProfile || EXAMPLE_PROFILE);\n const [profileImages, setProfileImages] = useState(cachedProfileImages || []);\n const [names, setNames] = useState(cachedNames || new Map());\n const [fileDate, setFileDate] = useState(cachedFileDate || '');\n const [isProcessing, setIsProcessing] = useState(false);\n\n // Store for the browser session — gets cleared out when closing tab but not on page refresh\n useEffect(() => {\n if (isStorageAvailable) {\n setCacheValue('file_date', fileDate);\n setCacheValue('profile_images', JSON.stringify(profileImages));\n setCacheValue('profile', JSON.stringify(profile));\n }\n }, [isStorageAvailable, profile, profileImages, fileDate]);\n\n // On uploading file(s)\n const onDrop = useCallback(async acceptedFiles => {\n setIsProcessing(true);\n\n if (!acceptedFiles || acceptedFiles.length === 0) {\n setIsProcessing(false);\n return alert('No files? 😥');\n }\n\n if (acceptedFiles.length !== 1) {\n setIsProcessing(false);\n return alert('Just one file please.');\n }\n\n const file = acceptedFiles[0];\n\n if (!['application/zip', 'application/json'].includes(file.type)) {\n setIsProcessing(false);\n return alert(\n 'Please drop either the zip file or json file.\\n\\nE.g. \"couchsurfing-export-123456-202005200751.zip\", or \"123456-202005200751.json\"',\n );\n }\n\n if (file.lastModifiedDate) {\n setFileDate(file.lastModifiedDate.toString());\n }\n\n if (file.type === 'application/zip') {\n const { json, images } = await extractZip(file);\n if (!json) {\n setIsProcessing(false);\n return alert(\n 'Please drop a zip file which contains the profile json file.\\n\\nE.g. \"couchsurfing-export-123456-202005200751.zip\", or \"123456-202005200751.json\"',\n );\n }\n\n const names = getNamesFromJson(json);\n setProfile(json);\n setNames(names);\n setProfileImages(images);\n scrollTop();\n } else if (file.type === 'application/json') {\n const jsonProfile = await readBlobFile(file);\n\n try {\n const json = JSON.parse(jsonProfile);\n const names = getNamesFromJson(json);\n setProfile(json);\n setNames(names);\n scrollTop();\n } catch (error) {\n Sentry.captureException(error);\n console.error(error);\n alert(\n 'File is little too funky for us to understand… 😥\\n\\nMake sure you uploaded correct export file (it should be .json or .zip file).\\n\\nIf problem persists, feel free to get in touch with Mikael (https://mikaelkorpela.fi/#contact).',\n );\n }\n }\n\n setIsProcessing(false);\n }, []);\n\n const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });\n\n return (\n
\n {profile ? (\n \n ) : (\n <>\n \n \n \n
\n \n \n )}\n \n );\n}\n\nexport default App;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport * as Sentry from '@sentry/browser';\n\nimport './index.scss';\nimport App from './App';\n// import * as serviceWorker from './serviceWorker';\n\n// JavaScript error logging\nSentry.init({\n dsn: window.couchspinner_settings?.sentry || '',\n});\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root'),\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\n//serviceWorker.unregister();\n","/**\n * Give out pretty date\n *\n * @param {String|Date object} date Date as a string or Date object\n * @return {String}\n */\nexport function formatDate(date) {\n if (!date) {\n return date;\n }\n\n let dateString;\n\n // Dates on CS exports are in format \"2007-01-11 22:29:44 UTC\"\n if (typeof date !== 'object') {\n dateString = date.replace(' UTC', '');\n }\n\n const formattedDate = new Date(dateString).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n return formattedDate && formattedDate !== 'Invalid Date'\n ? formattedDate\n : date;\n}\n\nexport const scrollToElementById = event => {\n event.stopPropagation();\n event.preventDefault();\n const hash = event?.target?.hash;\n if (hash) {\n const el = document.getElementById(hash.replace('#', ''));\n if (el) {\n window.history.pushState({}, '', hash);\n el.scrollIntoView({\n behavior: 'smooth',\n });\n }\n }\n};\n\n/**\n * Test if browser supports sessionStorage or localStorage\n *\n * From https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\n *\n * @param {[String]} type Either `sessionStorage` or `localStorage`\n * @return {[Boolean]}\n */\nexport function testStorage(type) {\n var storage;\n try {\n storage = window[type];\n var x = '__storage_test__';\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return (\n e instanceof DOMException &&\n // everything except Firefox\n (e.code === 22 ||\n // Firefox\n e.code === 1014 ||\n // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' ||\n // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&\n // acknowledge QuotaExceededError only if there's something already stored\n storage &&\n storage.length !== 0\n );\n }\n}\n","import React from 'react';\nimport { NavLink } from 'react-router-dom';\n\nimport './components.scss';\n\nexport function Section({ children }) {\n return
{children}
;\n}\n\nexport function Heading({ children }) {\n return
{children}
;\n}\n\nexport function Content(props) {\n return (\n
\n {props.children}\n
\n );\n}\n\nexport function Loading({ children }) {\n return (\n
\n {children || }\n \n \n
\n \n
\n \n
\n
\n );\n}\n\nexport function CsProfileLink(props) {\n const label = props.children || 'Member';\n return !!props.id ? (\n \n {props.id === props.userId ? 'You' : label}\n \n ) : (\n {label}\n );\n}\n\nexport function CsProfileName(props) {\n const { id, names, alt, append } = props;\n const displayName = names ? names.get(id)?.displayName : false;\n\n return (\n <>\n \n {displayName || alt}\n \n {displayName && append}\n \n );\n}\n\nexport function Tabs({ routes }) {\n return (\n
    \n {routes.map(({ route, label, count }) => (\n
  • \n \n {label}\n {!!count && {count}}\n \n
  • \n ))}\n
\n );\n}\n\nexport function Button(props) {\n return props.href ? (\n \n {props.children}\n \n ) : (\n \n );\n}\n"],"sourceRoot":""}