├── .dockerignore ├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── automerge.yml │ ├── build-container.yml │ ├── codeql-analysis.yml │ ├── test.yml │ └── update-snapshot.yml ├── .gitignore ├── .mailmap ├── .perlcriticrc ├── .perltidyrc ├── .prettierrc.yml ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── app.psgi ├── bin ├── install-playwright └── install-precious ├── build-assets.mjs ├── codecov.yml ├── cpanfile ├── cpanfile.forced ├── cpanfile.snapshot ├── docker-compose.yml ├── e2e └── home.spec.ts ├── eslint.config.mjs ├── git ├── hooks │ └── pre-commit └── setup.sh ├── lib └── MetaCPAN │ ├── Middleware │ ├── OldUrls.pm │ ├── Session │ │ └── Cookie.pm │ └── Static.pm │ ├── Web.pm │ └── Web │ ├── API │ └── ReleaseInfo │ │ └── Orchestrator.pm │ ├── ActionRole │ └── Sortable.pm │ ├── Authentication │ ├── Realm.pm │ ├── Store.pm │ └── User.pm │ ├── Controller.pm │ ├── Controller │ ├── About.pm │ ├── Account.pm │ ├── Account │ │ └── Favorite.pm │ ├── Activity.pm │ ├── Author.pm │ ├── Changes.pm │ ├── ContributingDoc.pm │ ├── Diff.pm │ ├── Dist.pm │ ├── Favorite.pm │ ├── Feed.pm │ ├── Lab.pm │ ├── Login.pm │ ├── Module.pm │ ├── Permission.pm │ ├── Pod.pm │ ├── Pod2HTML.pm │ ├── Raw.pm │ ├── Recent.pm │ ├── Recent │ │ └── TopUploaders.pm │ ├── Release.pm │ ├── Requires.pm │ ├── River.pm │ ├── Root.pm │ ├── Search.pm │ ├── Search │ │ └── AutoComplete.pm │ ├── Source.pm │ ├── Tools.pm │ └── View.pm │ ├── Model │ ├── API.pm │ ├── API │ │ ├── Author.pm │ │ ├── Changes.pm │ │ ├── Changes │ │ │ └── Parser.pm │ │ ├── Contributors.pm │ │ ├── Diff.pm │ │ ├── Distribution.pm │ │ ├── Favorite.pm │ │ ├── File.pm │ │ ├── Lab.pm │ │ ├── Module.pm │ │ ├── Permission.pm │ │ ├── Pod.pm │ │ ├── Release.pm │ │ └── User.pm │ ├── GitHub.pm │ └── ReleaseInfo.pm │ ├── RenderUtil.pm │ ├── Role │ ├── Date.pm │ ├── FileData.pm │ ├── Request.pm │ ├── Response.pm │ └── RiverData.pm │ ├── Types.pm │ └── View │ ├── JSON.pm │ ├── Xslate.pm │ └── Xslate │ └── Bridge.pm ├── local └── .gitignore ├── log4perl.conf ├── log4perl_prod.conf ├── metacpan_web.yaml ├── package-lock.json ├── package.json ├── perlimports.toml ├── playwright.config.ts ├── precious.toml ├── root ├── about │ ├── about.tx │ ├── contact.tx │ ├── contributors.tx │ ├── development.tx │ ├── faq.tx │ ├── meta_hack.tx │ ├── metadata.tx │ ├── missing_modules.tx │ └── sponsors.tx ├── account │ ├── favorite │ │ └── list.tx │ ├── identities.tx │ ├── login.tx │ └── profile.tx ├── activity.svg.tx ├── assets │ └── .gitignore ├── author.tx ├── author │ └── releases.tx ├── base.tx ├── base │ ├── about.tx │ ├── about │ │ └── markdown.tx │ ├── account.tx │ ├── error.tx │ ├── recent.tx │ ├── release.tx │ ├── search.tx │ └── tools.tx ├── browse.tx ├── contributing_not_found.tx ├── diff.tx ├── favorite │ ├── leaderboard.tx │ └── recent.tx ├── forbidden.tx ├── healthcheck.tx ├── home.tx ├── inc │ ├── activity.tx │ ├── author_pic.tx │ ├── contributors.tx │ ├── dependencies.tx │ ├── favorite.tx │ ├── favorite_table.tx │ ├── keyboard_shortcuts.tx │ ├── link_to_file.tx │ ├── link_to_source.tx │ ├── module_install.tx │ ├── no_sidebar.tx │ ├── notification.tx │ ├── notification │ │ ├── adoptme.tx │ │ ├── base.tx │ │ ├── deprecated.tx │ │ ├── handoff.tx │ │ ├── module_deprecated.tx │ │ └── needhelp.tx │ ├── opengraph.tx │ ├── opengraph │ │ ├── author.tx │ │ ├── module.tx │ │ └── release.tx │ ├── pager.tx │ ├── permission.tx │ ├── plussers.tx │ ├── release_status.tx │ ├── release_table.tx │ ├── river_gauge.tx │ ├── version_select.tx │ └── version_select │ │ └── diff.tx ├── internal_error.tx ├── lab │ ├── dashboard.tx │ └── dependencies.tx ├── login │ └── pause.tx ├── mobile │ └── toolbar_search_form.tx ├── no_result.tx ├── not_found.tx ├── permission │ ├── author.tx │ ├── distribution.tx │ └── module.tx ├── plussers.tx ├── pod.tx ├── pod2html │ └── pod2html.tx ├── raw.tx ├── recent.tx ├── recent │ └── topuploaders.tx ├── release.tx ├── requires.tx ├── river │ └── gauge.svg.tx ├── robots.txt ├── search.tx ├── source.tx ├── static │ ├── css │ │ └── user.css │ ├── fastly_do_not_delete.gif │ ├── icons │ │ ├── apple-touch-icon.png │ │ ├── favicon-16.ico │ │ ├── favicon.ico │ │ ├── folder.png │ │ ├── grid.svg │ │ ├── page_white.png │ │ ├── page_white_c.png │ │ └── page_white_code.png │ ├── images │ │ ├── dots.png │ │ ├── dots.svg │ │ ├── flag │ │ │ ├── ad.png │ │ │ ├── ae.png │ │ │ ├── af.png │ │ │ ├── ag.png │ │ │ ├── ai.png │ │ │ ├── al.png │ │ │ ├── am.png │ │ │ ├── an.png │ │ │ ├── ao.png │ │ │ ├── ar.png │ │ │ ├── as.png │ │ │ ├── at.png │ │ │ ├── au.png │ │ │ ├── aw.png │ │ │ ├── ax.png │ │ │ ├── az.png │ │ │ ├── ba.png │ │ │ ├── bb.png │ │ │ ├── bd.png │ │ │ ├── be.png │ │ │ ├── bf.png │ │ │ ├── bg.png │ │ │ ├── bh.png │ │ │ ├── bi.png │ │ │ ├── bj.png │ │ │ ├── bm.png │ │ │ ├── bn.png │ │ │ ├── bo.png │ │ │ ├── br.png │ │ │ ├── bs.png │ │ │ ├── bt.png │ │ │ ├── bv.png │ │ │ ├── bw.png │ │ │ ├── by.png │ │ │ ├── bz.png │ │ │ ├── ca.png │ │ │ ├── catalonia.png │ │ │ ├── cc.png │ │ │ ├── cd.png │ │ │ ├── cf.png │ │ │ ├── cg.png │ │ │ ├── ch.png │ │ │ ├── ci.png │ │ │ ├── ck.png │ │ │ ├── cl.png │ │ │ ├── cm.png │ │ │ ├── cn.png │ │ │ ├── co.png │ │ │ ├── cr.png │ │ │ ├── cs.png │ │ │ ├── ct.png │ │ │ ├── cu.png │ │ │ ├── cv.png │ │ │ ├── cx.png │ │ │ ├── cy.png │ │ │ ├── cz.png │ │ │ ├── de.png │ │ │ ├── dj.png │ │ │ ├── dk.png │ │ │ ├── dm.png │ │ │ ├── do.png │ │ │ ├── dz.png │ │ │ ├── ec.png │ │ │ ├── ee.png │ │ │ ├── eg.png │ │ │ ├── eh.png │ │ │ ├── england.png │ │ │ ├── er.png │ │ │ ├── es.png │ │ │ ├── et.png │ │ │ ├── europeanunion.png │ │ │ ├── fam.png │ │ │ ├── fi.png │ │ │ ├── fj.png │ │ │ ├── fk.png │ │ │ ├── fm.png │ │ │ ├── fo.png │ │ │ ├── fr.png │ │ │ ├── ga.png │ │ │ ├── gb.png │ │ │ ├── gd.png │ │ │ ├── ge.png │ │ │ ├── gf.png │ │ │ ├── gh.png │ │ │ ├── gi.png │ │ │ ├── gl.png │ │ │ ├── gm.png │ │ │ ├── gn.png │ │ │ ├── gp.png │ │ │ ├── gq.png │ │ │ ├── gr.png │ │ │ ├── gs.png │ │ │ ├── gt.png │ │ │ ├── gu.png │ │ │ ├── gw.png │ │ │ ├── gy.png │ │ │ ├── hk.png │ │ │ ├── hm.png │ │ │ ├── hn.png │ │ │ ├── hr.png │ │ │ ├── ht.png │ │ │ ├── hu.png │ │ │ ├── id.png │ │ │ ├── ie.png │ │ │ ├── il.png │ │ │ ├── in.png │ │ │ ├── io.png │ │ │ ├── iq.png │ │ │ ├── ir.png │ │ │ ├── is.png │ │ │ ├── it.png │ │ │ ├── jm.png │ │ │ ├── jo.png │ │ │ ├── jp.png │ │ │ ├── ke.png │ │ │ ├── kg.png │ │ │ ├── kh.png │ │ │ ├── ki.png │ │ │ ├── km.png │ │ │ ├── kn.png │ │ │ ├── kp.png │ │ │ ├── kr.png │ │ │ ├── kw.png │ │ │ ├── ky.png │ │ │ ├── kz.png │ │ │ ├── la.png │ │ │ ├── lb.png │ │ │ ├── lc.png │ │ │ ├── li.png │ │ │ ├── lk.png │ │ │ ├── lr.png │ │ │ ├── ls.png │ │ │ ├── lt.png │ │ │ ├── lu.png │ │ │ ├── lv.png │ │ │ ├── ly.png │ │ │ ├── ma.png │ │ │ ├── mc.png │ │ │ ├── md.png │ │ │ ├── me.png │ │ │ ├── mg.png │ │ │ ├── mh.png │ │ │ ├── mk.png │ │ │ ├── ml.png │ │ │ ├── mm.png │ │ │ ├── mn.png │ │ │ ├── mo.png │ │ │ ├── mp.png │ │ │ ├── mq.png │ │ │ ├── mr.png │ │ │ ├── ms.png │ │ │ ├── mt.png │ │ │ ├── mu.png │ │ │ ├── mv.png │ │ │ ├── mw.png │ │ │ ├── mx.png │ │ │ ├── my.png │ │ │ ├── mz.png │ │ │ ├── na.png │ │ │ ├── nc.png │ │ │ ├── ne.png │ │ │ ├── nf.png │ │ │ ├── ng.png │ │ │ ├── ni.png │ │ │ ├── nl.png │ │ │ ├── no.png │ │ │ ├── np.png │ │ │ ├── nr.png │ │ │ ├── nu.png │ │ │ ├── nz.png │ │ │ ├── om.png │ │ │ ├── pa.png │ │ │ ├── pe.png │ │ │ ├── pf.png │ │ │ ├── pg.png │ │ │ ├── ph.png │ │ │ ├── pk.png │ │ │ ├── pl.png │ │ │ ├── pm.png │ │ │ ├── pn.png │ │ │ ├── pr.png │ │ │ ├── ps.png │ │ │ ├── pt.png │ │ │ ├── pw.png │ │ │ ├── py.png │ │ │ ├── qa.png │ │ │ ├── re.png │ │ │ ├── ro.png │ │ │ ├── rs.png │ │ │ ├── ru.png │ │ │ ├── rw.png │ │ │ ├── sa.png │ │ │ ├── sb.png │ │ │ ├── sc.png │ │ │ ├── scotland.png │ │ │ ├── sd.png │ │ │ ├── se.png │ │ │ ├── sg.png │ │ │ ├── sh.png │ │ │ ├── si.png │ │ │ ├── sj.png │ │ │ ├── sk.png │ │ │ ├── sl.png │ │ │ ├── sm.png │ │ │ ├── sn.png │ │ │ ├── so.png │ │ │ ├── sr.png │ │ │ ├── st.png │ │ │ ├── sv.png │ │ │ ├── sy.png │ │ │ ├── sz.png │ │ │ ├── tc.png │ │ │ ├── td.png │ │ │ ├── tf.png │ │ │ ├── tg.png │ │ │ ├── th.png │ │ │ ├── tj.png │ │ │ ├── tk.png │ │ │ ├── tl.png │ │ │ ├── tm.png │ │ │ ├── tn.png │ │ │ ├── to.png │ │ │ ├── tr.png │ │ │ ├── tt.png │ │ │ ├── tv.png │ │ │ ├── tw.png │ │ │ ├── tz.png │ │ │ ├── ua.png │ │ │ ├── ug.png │ │ │ ├── uk.png │ │ │ ├── um.png │ │ │ ├── us.png │ │ │ ├── uy.png │ │ │ ├── uz.png │ │ │ ├── va.png │ │ │ ├── vc.png │ │ │ ├── ve.png │ │ │ ├── vg.png │ │ │ ├── vi.png │ │ │ ├── vn.png │ │ │ ├── vu.png │ │ │ ├── wales.png │ │ │ ├── wf.png │ │ │ ├── ws.png │ │ │ ├── ye.png │ │ │ ├── yt.png │ │ │ ├── za.png │ │ │ ├── zm.png │ │ │ └── zw.png │ │ ├── gray.png │ │ ├── metacpan-logo.svg │ │ ├── profile │ │ │ ├── bitbucket.png │ │ │ ├── blinklist.png │ │ │ ├── brightkite.png │ │ │ ├── coderwall.png │ │ │ ├── couchsurfing.png │ │ │ ├── design_float.png │ │ │ ├── dopplr.png │ │ │ ├── dotshare.png │ │ │ ├── email.png │ │ │ ├── facebook.png │ │ │ ├── feed.png │ │ │ ├── flickr.png │ │ │ ├── friendfeed.png │ │ │ ├── furl.png │ │ │ ├── gamespot.png │ │ │ ├── geeklist.png │ │ │ ├── github.png │ │ │ ├── gitlab.png │ │ │ ├── gitorious.png │ │ │ ├── gittip.png │ │ │ ├── hackernews.png │ │ │ ├── hackerrank.png │ │ │ ├── hackthissite.png │ │ │ ├── identica.png │ │ │ ├── instagram.png │ │ │ ├── lastfm.png │ │ │ ├── linkedin.png │ │ │ ├── magnolia.png │ │ │ ├── meetup.png │ │ │ ├── metacpan.png │ │ │ ├── mixx.png │ │ │ ├── myspace.png │ │ │ ├── nerdability.png │ │ │ ├── newsblur.png │ │ │ ├── newsvine.png │ │ │ ├── ohloh.png │ │ │ ├── orcid.png │ │ │ ├── perlmonks.png │ │ │ ├── pinboard.png │ │ │ ├── playperl.png │ │ │ ├── posterous.png │ │ │ ├── reddit.png │ │ │ ├── slideshare.png │ │ │ ├── sourceforge.png │ │ │ ├── speakerdeck.png │ │ │ ├── sphere.png │ │ │ ├── sphinn.png │ │ │ ├── stackexchange.png │ │ │ ├── stackoverflow.png │ │ │ ├── stackoverflowcareers.png │ │ │ ├── steam.png │ │ │ ├── stumbleupon.png │ │ │ ├── substack.png │ │ │ ├── technorati.png │ │ │ ├── tripadvisor.png │ │ │ ├── tumblr.png │ │ │ ├── twitter.png │ │ │ ├── vimeo.png │ │ │ └── youtube.png │ │ └── sponsors │ │ │ ├── activestate.png │ │ │ ├── advance-systems.jpg │ │ │ ├── booking.png │ │ │ ├── bytemark_logo.svg │ │ │ ├── control-my-id.png │ │ │ ├── cpanel.png │ │ │ ├── datadog.png │ │ │ ├── dealspotr.png │ │ │ ├── deriv.svg │ │ │ ├── dyn.png │ │ │ ├── easyname.png │ │ │ ├── elastic.svg │ │ │ ├── epo.png │ │ │ ├── fastly_logo.svg │ │ │ ├── fastmail.svg │ │ │ ├── geocodelogo.svg │ │ │ ├── github_logo.png │ │ │ ├── idonethis.png │ │ │ ├── kritika.svg │ │ │ ├── liquidweb_logo.png │ │ │ ├── open-cage.svg │ │ │ ├── panopta.png │ │ │ ├── perl-careers.png │ │ │ ├── perl-services.svg │ │ │ ├── perl_logo.png │ │ │ ├── qah-2014.png │ │ │ ├── route4me.png │ │ │ ├── servercentral.png │ │ │ ├── sonic.png │ │ │ ├── speedchilli.png │ │ │ ├── travis-ci.png │ │ │ ├── vienna.pm.jpeg │ │ │ ├── yellowbot-small.png │ │ │ ├── yellowbot.png │ │ │ └── yellowbot_2.png │ ├── js │ │ ├── autocomplete.mjs │ │ ├── bootstrap-slidepanel.js │ │ ├── brush-cpan-changes.js │ │ ├── brush-perl.js │ │ ├── cpan.js │ │ ├── document-ui.mjs │ │ ├── dropdown.js │ │ ├── github.js │ │ ├── google-analytics.mjs │ │ ├── inject.mjs │ │ ├── main.mjs │ │ ├── pod2html.mjs │ │ ├── profile.js │ │ ├── relatize_date.js │ │ ├── search.js │ │ ├── storage.js │ │ ├── syntaxhighlighter.mjs │ │ └── tablesorter.mjs │ ├── less │ │ ├── about.less │ │ ├── account.less │ │ ├── anchors.less │ │ ├── author.less │ │ ├── autocomplete.less │ │ ├── breadcrumbs.less │ │ ├── diff.less │ │ ├── dropdown.less │ │ ├── footer.less │ │ ├── global.less │ │ ├── home.less │ │ ├── lab.less │ │ ├── nav-list.less │ │ ├── nav.less │ │ ├── notification.less │ │ ├── plusser.less │ │ ├── pod.less │ │ ├── pod2html.less │ │ ├── print.less │ │ ├── release.less │ │ ├── responsive.less │ │ ├── search.less │ │ ├── silk.less │ │ ├── style.less │ │ ├── syntaxhighlighter-theme.less │ │ ├── syntaxhighlighter.less │ │ ├── table.less │ │ ├── tablesorter.less │ │ └── toplists.less │ └── opensearch.xml └── tools.tx ├── run-dev ├── static-app.psgi └── t ├── assets.t ├── controller ├── about.t ├── account.t ├── activity.t ├── author.t ├── changes.t ├── contributing-to.t ├── diff.t ├── favorite │ └── leaderboard.t ├── feed.t ├── healthcheck.t ├── home.t ├── lab │ └── dashboard.t ├── permission.t ├── pod.t ├── raw.t ├── recent.t ├── release.t ├── robots.t ├── search.t ├── search │ ├── autocomplete.t │ ├── precision.t │ └── suggestion.t ├── shared │ └── release-info.t └── source.t ├── encoding.t ├── fastly_headers.t ├── html.t ├── lib └── MetaCPAN │ └── Web │ ├── Controller │ └── Test.pm │ ├── Test.pm │ └── Test │ └── HTML5 │ ├── Element │ └── SVG.pm │ └── TreeBuilder.pm ├── markdown.t ├── model ├── api │ └── lab.t ├── changes-tests │ ├── dbix-class.changes │ ├── moose.changes │ ├── read_dbix-class.t │ └── read_moose.t ├── changes.t ├── permission.t ├── release-info.t └── release.t ├── moose.t ├── session.t ├── static-files.t ├── static-mounts.t ├── testrules.yml └── view └── json.t /.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 4 10 | 11 | end_of_line = lf 12 | charset = utf-8 13 | 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | 17 | [*.html] 18 | indent_size = 2 19 | [*.tx] 20 | indent_size = 2 21 | [*.md] 22 | indent_size = 2 23 | max_line_length = 80 24 | [*.{yml,yaml}] 25 | indent_size = 2 26 | quote_type = single 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: ["type:Bug"] 6 | assignees: "" 7 | --- 8 | 9 | **PLEASE NOTE** 10 | 11 | This issue tracker is for bugs in the https://metacpan.org web site. If you are 12 | are reporting a bug about anything else, this is most likely not the correct 13 | venue. Please use the left side menu for the module you are interested in and 14 | click the `Issues` link in order to find the bug tracker for your module. 15 | 16 | **Describe the bug** A clear and concise description of what the bug is. 17 | 18 | **To Reproduce** Steps to reproduce the behavior: 19 | 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | **Expected behavior** A clear and concise description of what you expected to 26 | happen. 27 | 28 | **Screenshots** If applicable, add screenshots to help explain your problem. 29 | 30 | **Desktop (please complete the following information):** 31 | 32 | - OS: [e.g. iOS] 33 | - Browser [e.g. chrome, safari] 34 | - Version [e.g. 22] 35 | 36 | **Smartphone (please complete the following information):** 37 | 38 | - Device: [e.g. iPhone6] 39 | - OS: [e.g. iOS8.1] 40 | - Browser [e.g. stock browser, safari] 41 | - Version [e.g. 22] 42 | 43 | **Additional context** Add any other context about the problem here. 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | blank_issues_enabled: false 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Request a feature to be added 4 | title: "" 5 | labels: ["type:Feature"] 6 | assignees: "" 7 | --- 8 | 9 | **Describe the feature** A clear and concise description of what the feature is. 10 | 11 | **Which problem does it solve?** 12 | 13 | **Expected behavior** A clear and concise description of what you expect to see. 14 | 15 | **Volunteering** Are you willing to implement (or help to implement) this 16 | feature? 17 | 18 | **Additional context** Add any other context about the request here. 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | - package-ecosystem: npm 8 | directory: / 9 | schedule: 10 | interval: weekly 11 | - package-ecosystem: docker 12 | directory: / 13 | schedule: 14 | interval: daily 15 | -------------------------------------------------------------------------------- /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | name: Enable Auto-Merge For bots 2 | on: 3 | pull_request_target: 4 | types: [opened] 5 | 6 | jobs: 7 | enable-auto-merge: 8 | runs-on: ubuntu-latest 9 | if: > 10 | github.event.pull_request.user.login == 'metacpan-automation[bot]' 11 | || github.event.pull_request.user.login == 'dependabot[bot]' 12 | steps: 13 | - name: Generate Auth Token 14 | uses: actions/create-github-app-token@v2 15 | id: app-token 16 | with: 17 | app-id: ${{ secrets.APP_ID }} 18 | private-key: ${{ secrets.APP_PRIVATE_KEY }} 19 | - uses: peter-evans/enable-pull-request-automerge@v3 20 | with: 21 | token: ${{ steps.app-token.outputs.token }} 22 | pull-request-number: ${{ github.event.pull_request.number }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.carton 2 | /.includepath 3 | /.project 4 | /.tidyall.d/ 5 | /MYMETA.* 6 | /Makefile 7 | /Makefile.old 8 | /blib 9 | /carton.lock 10 | /cover_db/ 11 | /log4perl_local.conf 12 | /metacpan_web_local.* 13 | /node_modules/ 14 | /perltidy.LOG 15 | /playwright 16 | /pm_to_blib 17 | /tidyall.ERR 18 | /var 19 | /bin/precious 20 | /bin/ubi 21 | /root/assets 22 | /root/static/sitemaps 23 | *.bak 24 | *.sw* 25 | .DS_Store 26 | -------------------------------------------------------------------------------- /.perltidyrc: -------------------------------------------------------------------------------- 1 | --maximum-line-length=78 2 | --indent-columns=4 3 | --continuation-indentation=4 4 | --standard-error-output 5 | --vertical-tightness=2 6 | --closing-token-indentation=0 7 | --paren-tightness=1 8 | --brace-tightness=1 9 | --square-bracket-tightness=1 10 | --block-brace-tightness=1 11 | --nospace-for-semicolon 12 | --nooutdent-long-quotes 13 | --want-break-before="% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=" 14 | # Break a line after opening/before closing token. 15 | --vertical-tightness=0 16 | --vertical-tightness-closing=0 17 | --weld-nested-containers 18 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | overrides: 2 | - files: '*.md' 3 | options: 4 | proseWrap: always 5 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | --------------- | ------------------ | 7 | | `master` branch | :white_check_mark: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Please report all vulnerabilities by sending an email to noc@metacpan.org 12 | -------------------------------------------------------------------------------- /bin/install-playwright: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu -o pipefail 4 | npm i 5 | npx playwright install chromium --with-deps 6 | -------------------------------------------------------------------------------- /bin/install-precious: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This is for installing precious and other 3rd party libs needed for linting 4 | # in CI 5 | 6 | set -euo pipefail 7 | 8 | if [ -z "${1:-}" ]; then 9 | echo "usage: ./bin/install-precious /path/to/bin/dir" 10 | exit 1 11 | fi 12 | 13 | TARGET=$1 14 | export TARGET 15 | 16 | TARGET=$1 17 | export TARGET 18 | 19 | curl --silent --location \ 20 | https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh | 21 | sh 22 | 23 | ubi --project houseabsolute/omegasort --in "$TARGET" 24 | ubi --project houseabsolute/precious --in "$TARGET" 25 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | --- 2 | comment: 3 | layout: 'diff, files' 4 | behavior: default 5 | require_changes: true # if true: only post the comment if coverage changes 6 | require_base: false # [true :: must have a base report to post] 7 | require_head: true # [true :: must have a head report to post] 8 | hide_project_coverage: false # [true :: only show coverage on the git diff] 9 | coverage: 10 | status: 11 | patch: 12 | default: 13 | threshold: 1% 14 | project: 15 | default: 16 | threshold: 1% 17 | -------------------------------------------------------------------------------- /cpanfile.forced: -------------------------------------------------------------------------------- 1 | # transitive deps 2 | # Not used directly, but they need to be explicitly listed to ensure they are 3 | # in our cpanfile.snapshot at appropriate versions. Either for older perl 4 | # versions, or unpredictable dynamic deps. These will be installed using a 5 | # different process to ensure they are present in the snapshot, even if they 6 | # would be satisfied by core. 7 | requires 'CPAN::Meta', '2.141520'; 8 | requires 'Devel::PPPort', '3.62'; # for older perls 9 | requires 'HTTP::Lite', '2.44'; # Unpredictably depended on by XML::TreePP, which is a dep of XML::FeedPP 10 | requires 'HTTP::Tiny', '0.076'; # for older perls 11 | requires 'Pod::Parser', '1.63'; # for newer perls 12 | requires 'version', '0.9929'; # for older perls 13 | requires 'YAML', '1.15'; 14 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web-asset-build: 3 | build: 4 | context: . 5 | target: build-assets 6 | volumes: 7 | - './root/static/:/build/root/static/' 8 | - 'web-assets:/build/root/assets/' 9 | command: ['./build-assets.mjs', '--watch'] 10 | develop: 11 | watch: 12 | - path: ./build-assets.mjs 13 | action: rebuild 14 | - path: ./package.json 15 | action: rebuild 16 | web-server: 17 | build: 18 | context: . 19 | target: develop 20 | volumes: 21 | - './:/app/' 22 | - 'web-assets:/app/root/assets/' 23 | - '/app/local' 24 | ports: 25 | - '5001:8000' 26 | environment: 27 | # default is 120, shorten to work with compose label 28 | COLUMNS: 96 29 | depends_on: 30 | - web-asset-build 31 | develop: 32 | watch: 33 | - path: ./cpanfile 34 | action: rebuild 35 | volumes: 36 | web-assets: 37 | -------------------------------------------------------------------------------- /e2e/home.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('home page', async ({ page }) => { 4 | await page.goto('/'); 5 | await expect(page).toHaveTitle(/Search the CPAN - metacpan.org/, { timeout: 10 }); 6 | }); 7 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import globals from "globals"; 2 | import pluginJs from "@eslint/js"; 3 | 4 | export default [{ 5 | ignores: ["root/assets/"], 6 | }, 7 | { 8 | languageOptions: { 9 | globals: globals.browser, 10 | } 11 | }, 12 | { 13 | files: ['build-assets.mjs'], 14 | languageOptions: { 15 | globals: globals.nodeBuiltin, 16 | }, 17 | }, 18 | { 19 | files: ['**/*.js'], 20 | languageOptions: { 21 | sourceType: 'commonjs', 22 | } 23 | }, 24 | { 25 | files: ['**/*.mjs'], 26 | languageOptions: { 27 | sourceType: 'module', 28 | } 29 | }, 30 | pluginJs.configs.recommended, 31 | ]; 32 | -------------------------------------------------------------------------------- /git/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | precious lint -s 4 | -------------------------------------------------------------------------------- /git/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .git/hooks 4 | ln -s ../../git/hooks/pre-commit 5 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/ActionRole/Sortable.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::ActionRole::Sortable; 2 | 3 | use Moose::Role; 4 | 5 | # Config necessary! See example in Controller::Requires 6 | 7 | around execute => sub { 8 | my $orig = shift; 9 | my $self = shift; 10 | my ( $controller, $c ) = @_; 11 | 12 | my $order = [qw(asc desc)]; 13 | my $action = $c->action; 14 | my $config = $controller->config->{sort}{ $c->action->name }; 15 | my $columns = $config->{columns} or die 'Config required!'; 16 | my $sort = { column => $columns->[0], order => $order->[0] }; 17 | 18 | if ( $config->{default} ) { 19 | $sort = { 20 | column => $config->{default}[0], 21 | order => $config->{default}[1], 22 | }; 23 | } 24 | 25 | if ( my $param = $c->req->param('sort') ) { 26 | my ( $p_column, $p_order ) = $param =~ /(\d+),(\d+)/; 27 | 28 | $sort->{column} = $config->{columns}[$p_column] 29 | if defined $p_column && defined $config->{columns}[$p_column]; 30 | 31 | $sort->{order} = $order->[$p_order] 32 | if defined $p_order && defined $order->[$p_order]; 33 | } 34 | 35 | # convert sort to the non-structure form (so we can pass it in URL) 36 | # API can handle it. 37 | my $sort_param = sprintf '%s:%s', $sort->{column}, $sort->{order}; 38 | return $self->$orig( @_, $sort_param ); 39 | }; 40 | 41 | 1; 42 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Authentication/Store.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Authentication::Store; 2 | use MetaCPAN::Web::Types qw( LoadableClass ); 3 | use Moo; 4 | 5 | has user_class => ( 6 | is => 'ro', 7 | isa => LoadableClass, 8 | default => 'MetaCPAN::Web::Authentication::User', 9 | handles => [ qw( 10 | from_session 11 | find_user 12 | ) ], 13 | ); 14 | has realm => ( is => 'ro' ); 15 | 16 | sub BUILDARGS { 17 | my ( $class, $config, $c, $realm ) = @_; 18 | return { %$config, realm => $realm, }; 19 | } 20 | 21 | sub for_session { 22 | my ( $self, $c, $user ) = @_; 23 | $user->for_session; 24 | } 25 | 26 | sub user_supports { } 27 | 28 | 1; 29 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller; 2 | use Moose; 3 | use namespace::autoclean; 4 | 5 | BEGIN { extends 'Catalyst::Controller'; } 6 | 7 | __PACKAGE__->meta->make_immutable; 8 | 9 | 1; 10 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Dist.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Dist; 2 | 3 | use Moose; 4 | use namespace::autoclean; 5 | 6 | BEGIN { extends 'MetaCPAN::Web::Controller' } 7 | 8 | sub root : Chained('/') PathPart('dist') CaptureArgs(1) { 9 | my ( $self, $c, $dist ) = @_; 10 | if ( $dist =~ /[^A-Za-z0-9_\-\.\@\+]/ ) { 11 | $c->detach('/not_found'); 12 | } 13 | $c->stash( { distribution_name => $dist } ); 14 | } 15 | 16 | sub dist_view : Chained('root') PathPart('') Args(0) { 17 | my ( $self, $c ) = @_; 18 | my $dist = $c->stash->{distribution_name}; 19 | 20 | $c->stash( release_info => 21 | $c->model( 'ReleaseInfo', full_details => 1 )->find($dist) ); 22 | $c->forward('/release/view'); 23 | } 24 | 25 | sub plussers : Chained('root') PathPart('plussers') Args(0) { 26 | my ( $self, $c ) = @_; 27 | my $dist = $c->stash->{distribution_name}; 28 | $c->stash( $c->model('API::Favorite')->find_plussers($dist)->get ); 29 | $c->stash( { template => 'plussers.tx' } ); 30 | } 31 | 32 | __PACKAGE__->meta->make_immutable; 33 | 34 | 1; 35 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Module.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Module; 2 | 3 | use Moose; 4 | use namespace::autoclean; 5 | 6 | BEGIN { extends 'MetaCPAN::Web::Controller' } 7 | 8 | sub root : Chained('/') PathPart('module') CaptureArgs(1) { 9 | my ( $self, $c, $module ) = @_; 10 | $c->stash( { module_name => $module } ); 11 | } 12 | 13 | sub pod : Chained('root') PathPart('') Args(0) { 14 | my ( $self, $c ) = @_; 15 | my $module = $c->stash->{module_name}; 16 | $c->cdn_max_age('1y'); 17 | $c->res->redirect( $c->uri_for( '/pod', $module ), 301 ); 18 | $c->detach; 19 | } 20 | 21 | __PACKAGE__->meta->make_immutable; 22 | 23 | 1; 24 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Recent.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Recent; 2 | use Moose; 3 | 4 | BEGIN { extends 'MetaCPAN::Web::Controller' } 5 | 6 | sub index : Path : Args(0) { 7 | my ( $self, $c ) = @_; 8 | my $req = $c->req; 9 | 10 | my $page = $req->page; 11 | my $page_size = $req->get_page_size(100); 12 | 13 | my $filter = $req->params->{f} || 'l'; 14 | my ($data) 15 | = $c->model('API::Release') 16 | ->recent( $page, $page_size, $filter ) 17 | ->get; 18 | 19 | $c->add_surrogate_key( 'RECENT', 'DIST_UPDATES' ); 20 | $c->browser_max_age('1m'); 21 | $c->cdn_max_age('1y'); # DIST_UPDATES will purge it 22 | 23 | my $pageset = Data::Pageset->new( { 24 | current_page => $page, 25 | entries_per_page => $page_size, 26 | mode => 'slide', 27 | pages_per_set => 10, 28 | total_entries => $data->{total}, 29 | } ); 30 | 31 | $c->stash( { 32 | recent => $data->{releases}, 33 | took => $data->{took}, 34 | page => $page, 35 | page_size => $page_size, 36 | pageset => $pageset, 37 | filter => $filter, 38 | template => 'recent.tx', 39 | } ); 40 | } 41 | 42 | sub favorites : Local : Args(0) { 43 | my ( $self, $c ) = @_; 44 | $c->res->redirect( '/favorite/recent', 301 ); 45 | $c->detach; 46 | } 47 | 48 | __PACKAGE__->meta->make_immutable; 49 | 50 | 1; 51 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Recent/TopUploaders.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Recent::TopUploaders; 2 | use Moose; 3 | BEGIN { extends 'MetaCPAN::Web::Controller' } 4 | 5 | sub weekly : Local : Args(0) { 6 | my ( $self, $c ) = @_; 7 | $c->forward( 'topuploaders', ['weekly'] ); 8 | } 9 | 10 | sub monthly : Local : Args(0) { 11 | my ( $self, $c ) = @_; 12 | $c->forward( 'topuploaders', ['monthly'] ); 13 | } 14 | 15 | sub yearly : Local : Args(0) { 16 | my ( $self, $c ) = @_; 17 | $c->forward( 'topuploaders', ['yearly'] ); 18 | } 19 | 20 | sub all : Local : Args(0) { 21 | my ( $self, $c ) = @_; 22 | $c->forward( 'topuploaders', ['all'] ); 23 | } 24 | 25 | sub topuploaders : Private { 26 | my ( $self, $c, $range ) = @_; 27 | 28 | my $data = $c->model('API::Release')->topuploaders($range)->get; 29 | 30 | my $authors 31 | = $c->model('API::Author') 32 | ->get_multiple( keys %{ $data->{counts} } ) 33 | ->get; 34 | 35 | $c->stash( { 36 | authors => [ 37 | sort { $b->{releases} <=> $a->{releases} } 38 | map +{ %{$_}, releases => $data->{counts}{ $_->{pauseid} } }, 39 | @{ $authors->{authors} } 40 | ], 41 | took => $data->{took}, 42 | total => $data->{total}, 43 | range => $range, 44 | template => 'recent/topuploaders.tx', 45 | } ); 46 | } 47 | 48 | __PACKAGE__->meta->make_immutable; 49 | 50 | 1; 51 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/River.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::River; 2 | use Moose; 3 | 4 | BEGIN { extends 'MetaCPAN::Web::Controller' } 5 | 6 | sub gauge : Chained('/dist/root') PathPart('river.svg') Args(0) { 7 | my ( $self, $c ) = @_; 8 | my $dist = $c->stash->{distribution_name}; 9 | 10 | my $dist_info 11 | = $c->model('API::Distribution')->get($dist)->get->{distribution}; 12 | 13 | # Lack of river data for a dist is handled differently in the template. 14 | $c->detach('/not_found') 15 | unless $dist_info->{name}; 16 | 17 | $c->res->content_type('image/svg+xml'); 18 | $c->stash( { 19 | river => $dist_info->{river}, 20 | distribution => $dist_info->{name}, 21 | template => 'river/gauge.svg.tx', 22 | } ); 23 | 24 | $c->cdn_max_age('1y'); 25 | $c->browser_max_age('7d'); 26 | $c->add_dist_key( $dist_info->{name} ); 27 | } 28 | 29 | __PACKAGE__->meta->make_immutable; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Search/AutoComplete.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Search::AutoComplete; 2 | 3 | use Moose; 4 | use List::Util qw( uniq ); 5 | 6 | use namespace::autoclean; 7 | 8 | BEGIN { extends 'MetaCPAN::Web::Controller' } 9 | 10 | sub index : Path : Args(0) { 11 | my ( $self, $c ) = @_; 12 | $c->stash( { current_view => 'JSON' } ); 13 | my $query = join( q{ }, $c->req->param('q') ); 14 | my $module_data = $c->model('API::Module')->autocomplete($query); 15 | my $author_data = $c->model('API::Author')->search($query); 16 | my @results = ( 17 | ( 18 | map +{ 19 | value => join( ' - ', 20 | $_->{pauseid}, $_->{name} || $_->{asciiname} || () ), 21 | data => { id => $_->{pauseid}, type => 'author' } 22 | }, 23 | @{ $author_data->get->{authors} } 24 | ), 25 | ( 26 | map +{ value => $_, data => { module => $_, type => 'module' } }, 27 | uniq map { $_->{name} } @{ $module_data->get->{results} } 28 | ), 29 | ); 30 | 31 | $c->stash( { 32 | json => { suggestions => \@results }, 33 | } ); 34 | } 35 | 36 | __PACKAGE__->meta->make_immutable; 37 | 38 | 1; 39 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Controller/Tools.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Tools; 2 | 3 | use Moose; 4 | use namespace::autoclean; 5 | 6 | BEGIN { extends 'MetaCPAN::Web::Controller' } 7 | 8 | sub tools : Path : Args(0) { 9 | my ( $self, $c ) = @_; 10 | $c->stash( { 11 | template => 'tools.tx', 12 | } ); 13 | } 14 | 15 | __PACKAGE__->meta->make_immutable; 16 | 1; 17 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Model/API/Contributors.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Model::API::Contributors; 2 | use Moose; 3 | use namespace::autoclean; 4 | 5 | extends 'MetaCPAN::Web::Model::API'; 6 | 7 | =head1 NAME 8 | 9 | MetaCPAN::Web::Model::Contributors - Catalyst Model 10 | 11 | =head1 DESCRIPTION 12 | 13 | Catalyst Model. 14 | 15 | =head1 AUTHOR 16 | 17 | Graham Knop 18 | 19 | =head1 LICENSE 20 | 21 | This library is free software. You can redistribute it and/or modify 22 | it under the same terms as Perl itself. 23 | 24 | =cut 25 | 26 | sub get { 27 | my ( $self, $author, $release ) = @_; 28 | 29 | $self->request( '/release/contributors/' . $author . '/' . $release ); 30 | } 31 | 32 | __PACKAGE__->meta->make_immutable; 33 | 34 | 1; 35 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Model/API/Distribution.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Model::API::Distribution; 2 | use Moose; 3 | extends 'MetaCPAN::Web::Model::API'; 4 | 5 | sub get { 6 | my ( $self, $dist ) = @_; 7 | $self->request("/distribution/$dist")->then( sub { 8 | my $data = shift; 9 | Future->done( { 10 | distribution => $data, 11 | } ); 12 | } ); 13 | } 14 | 15 | __PACKAGE__->meta->make_immutable; 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Model/API/File.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Model::API::File; 2 | use Moose; 3 | extends 'MetaCPAN::Web::Model::API'; 4 | with 'MetaCPAN::Web::Role::FileData'; 5 | 6 | sub get { 7 | my ( $self, @path ) = @_; 8 | $self->request( '/file/' . join( '/', @path ) ) 9 | ->then( $self->_groom_fileinfo( [], \@path ) ); 10 | } 11 | 12 | sub source { 13 | my ( $self, @path ) = @_; 14 | $self->request( '/source/' . join( '/', @path ), undef, { raw => 1 } ); 15 | } 16 | 17 | sub dir { 18 | my ( $self, @path ) = @_; 19 | my $path = join '/', @path; 20 | my $data = $self->request("/file/dir/$path")->transform( 21 | done => sub { 22 | my $dir = $_[0]->{dir}; 23 | for my $entry (@$dir) { 24 | my $stat = $entry->{stat} ||= {}; 25 | for my $stat_entry ( map /^stat\.(.*)/ ? $1 : (), 26 | keys %$entry ) 27 | { 28 | $stat->{$stat_entry} 29 | = delete $entry->{"stat.$stat_entry"}; 30 | } 31 | } 32 | return $dir; 33 | } 34 | )->then( $self->_groom_fileinfo( ['dir'] ) ); 35 | } 36 | 37 | __PACKAGE__->meta->make_immutable; 38 | 39 | 1; 40 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Role/Date.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Role::Date; 2 | use strict; 3 | use warnings; 4 | use Role::Tiny qw( requires ); 5 | 6 | requires 'strftime'; 7 | 8 | sub to_http { 9 | $_[0]->strftime('%d %b %Y %T %Z'); 10 | } 11 | 12 | sub to_ymd { 13 | $_[0]->strftime('%F'); 14 | } 15 | 16 | 1; 17 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Role/Request.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Role::Request; 2 | 3 | use Moose::Role; 4 | use Cpanel::JSON::XS (); 5 | use MetaCPAN::Web::Types qw( is_PositiveInt ); 6 | use Plack::Session (); 7 | use Try::Tiny qw( catch try ); 8 | 9 | use namespace::autoclean; 10 | 11 | has final_args => ( is => 'rw' ); 12 | 13 | sub page { 14 | my $self = shift; 15 | my $page = $self->param('p'); 16 | return is_PositiveInt($page) ? $page : 1; 17 | } 18 | 19 | sub session { 20 | my $self = shift; 21 | return Plack::Session->new( $self->env ); 22 | } 23 | 24 | sub get_page_size { 25 | my $req = shift; 26 | my $default_page_size = shift; 27 | 28 | my $page_size = $req->param('size'); 29 | unless ( is_PositiveInt($page_size) && $page_size <= 500 ) { 30 | $page_size = $default_page_size; 31 | } 32 | return $page_size; 33 | } 34 | 35 | sub json_param { 36 | my ( $self, $name ) = @_; 37 | return try { 38 | Cpanel::JSON::XS->new->relaxed->utf8( 39 | $self->params_are_decoded ? 0 : 1 ) 40 | ->decode( $self->params->{$name} ); 41 | } 42 | catch { 43 | warn "Failed to decode JSON: $_[0]"; 44 | undef; 45 | }; 46 | } 47 | 48 | sub params_are_decoded { 49 | my ($self) = @_; 50 | return $self->params->{utf8} eq "\x{1f42a}"; 51 | } 52 | 53 | 1; 54 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Role/Response.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Role::Response; 2 | 3 | use Moose::Role; 4 | use DateTime::Format::HTTP (); 5 | use DateTime::Format::ISO8601 (); 6 | 7 | =head2 last_modified 8 | 9 | Set the C header to the value passed as first parameter. 10 | The parameter can either be a L object, epoch seconds or 11 | an ISO8601 formatted date string. 12 | 13 | =cut 14 | 15 | sub last_modified { 16 | my ( $self, $date ) = @_; 17 | if ( ref $date ) { 18 | 19 | # assume it's a DateTime 20 | } 21 | elsif ( $date =~ /^\d+$/ ) { 22 | $date = DateTime->from_epoch( epoch => $date ); 23 | } 24 | else { 25 | $date = DateTime::Format::ISO8601->parse_datetime($date); 26 | } 27 | return unless ( eval { $date->isa('DateTime') } ); 28 | $self->header( 29 | 'Last-Modified' => DateTime::Format::HTTP->format_datetime($date) ); 30 | } 31 | 32 | 1; 33 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Role/RiverData.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Role::RiverData; 2 | use Moose::Role; 3 | use Future (); 4 | use List::Util qw( uniq ); 5 | use namespace::autoclean; 6 | 7 | sub add_river { 8 | my ( $self, $map ) = @_; 9 | sub { 10 | my ($data) = @_; 11 | my @items = $map ? $map->($data) : @{ $data->{releases} || [] } 12 | or return Future->done($data); 13 | my @dists = uniq map $_->{distribution}, @items; 14 | $self->request( 15 | '/distribution/river', 16 | { 17 | distribution => \@dists, 18 | } 19 | )->then( sub { 20 | my ($river) = @_; 21 | for my $item (@items) { 22 | $item->{river} 23 | = $river->{river}{ $item->{distribution} } || {}; 24 | } 25 | Future->done($data); 26 | } ); 27 | }; 28 | } 29 | 30 | 1; 31 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/Types.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Types; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Type::Library -base; 7 | use Type::Utils qw( extends ); 8 | 9 | BEGIN { 10 | extends qw( 11 | Types::Standard 12 | Types::Common::Numeric 13 | Types::Common::String 14 | Types::DateTime 15 | Types::LoadableClass 16 | Types::Path::Tiny 17 | Types::URI 18 | ); 19 | } 20 | 21 | __PACKAGE__->meta->add_coercion( 22 | name => 'ArrayToHash', 23 | type_constraint => Types::Standard::HashRef, 24 | coercion_generator => sub { 25 | my ( $coerce, $target, $key ) = @_; 26 | ArrayRef, => sprintf( q[+{ map { $_->{'%s'} => $_ } @$_ }], $key ),; 27 | }, 28 | ); 29 | 30 | 1; 31 | -------------------------------------------------------------------------------- /lib/MetaCPAN/Web/View/JSON.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::View::JSON; 2 | 3 | use Moose; 4 | 5 | # Catalyst::View::JSON uses JSON::MaybeXS 6 | use Cpanel::JSON::XS (); ## no perlimports 7 | 8 | extends 'Catalyst::View::JSON'; 9 | 10 | __PACKAGE__->config( { 11 | expose_stash => 'json', 12 | json_encoder_args => { 13 | canonical => 1, 14 | }, 15 | } ); 16 | 17 | # Catalyst::View::JSON is not a Moose. 18 | __PACKAGE__->meta->make_immutable( inline_constructor => 0 ); 19 | 20 | 1; 21 | -------------------------------------------------------------------------------- /local/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !/.gitignore 3 | -------------------------------------------------------------------------------- /log4perl.conf: -------------------------------------------------------------------------------- 1 | log4perl.rootLogger=DEBUG, OUTPUT 2 | 3 | log4perl.appender.OUTPUT=Log::Log4perl::Appender::Screen 4 | log4perl.appender.OUTPUT.stderr=1 5 | 6 | log4perl.appender.OUTPUT.layout=PatternLayout 7 | log4perl.appender.OUTPUT.layout.ConversionPattern=[%d] [%p] [%X{url}] %m%n 8 | -------------------------------------------------------------------------------- /log4perl_prod.conf: -------------------------------------------------------------------------------- 1 | log4perl.rootLogger=WARN, OUTPUT, SYSLOG 2 | 3 | log4perl.filter.WarningsFilter = Log::Log4perl::Filter::StringMatch 4 | log4perl.filter.WarningsFilter.StringToMatch = failed to writev: -1 errno:32|Timed out at|does not map to Unicode 5 | log4perl.filter.WarningsFilter.AcceptOnMatch = false 6 | 7 | log4perl.appender.OUTPUT = Log::Log4perl::Appender::Screen 8 | log4perl.appender.OUTPUT.stderr = 1 9 | log4perl.appender.OUTPUT.Filter = WarningsFilter 10 | log4perl.appender.OUTPUT.layout = PatternLayout 11 | log4perl.appender.OUTPUT.layout.ConversionPattern = [%d] [%p] [%X{url}] %m%n 12 | 13 | log4perl.appender.SYSLOG = Log::Dispatch::Syslog 14 | log4perl.appender.SYSLOG.Filter = WarningsFilter 15 | log4perl.appender.SYSLOG.ident = metacpan_web 16 | log4perl.appender.SYSLOG.facility = local0 17 | log4perl.appender.SYSLOG.layout = Log::Log4perl::Layout::JSON 18 | log4perl.appender.SYSLOG.layout.field.message = %m{chomp} 19 | log4perl.appender.SYSLOG.layout.field.category = %c 20 | log4perl.appender.SYSLOG.layout.field.class = %C 21 | log4perl.appender.SYSLOG.layout.field.file = %F{1} 22 | log4perl.appender.SYSLOG.layout.field.sub = %M{1} 23 | log4perl.appender.SYSLOG.layout.include_mdc = 1 24 | -------------------------------------------------------------------------------- /metacpan_web.yaml: -------------------------------------------------------------------------------- 1 | api: https://api.metacpan.org/v1 2 | source_host: https://st.aticpan.org 3 | web_host: https://metacpan.org 4 | consumer_key: metacpan.dev 5 | cookie_secret: seekrit 6 | consumer_secret: ClearAirTurbulence 7 | log4perl_file: log4perl.conf 8 | 9 | mark_unauthorized_releases: 0 10 | 11 | View::Xslate: 12 | cache: 1 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacpan-web", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "./build-assets.mjs", 6 | "build:min": "./build-assets.mjs --minify", 7 | "build:watch": "./build-assets.mjs --watch", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/metacpan/metacpan-web.git" 13 | }, 14 | "author": "", 15 | "bugs": { 16 | "url": "https://github.com/metacpan/metacpan-web/issues" 17 | }, 18 | "homepage": "https://github.com/metacpan/metacpanweb#readme", 19 | "devDependencies": { 20 | "@eslint/js": "^9.5.0", 21 | "@playwright/test": "^1.52.0", 22 | "eslint": "^9.28.0", 23 | "globals": "^16.2.0", 24 | "js-beautify": "^1.15.4", 25 | "prettier": "3.5.3" 26 | }, 27 | "dependencies": { 28 | "@fortawesome/fontawesome-free": "^6.7.2", 29 | "bootstrap": "^3.4.1", 30 | "brush-cpp": "^4.0.1", 31 | "brush-diff": "^4.0.0", 32 | "brush-javascript": "^4.0.0", 33 | "brush-plain": "^4.0.1", 34 | "brush-yaml": "^4.0.0", 35 | "devbridge-autocomplete": "^1.4.11", 36 | "esbuild": "^0.25.5", 37 | "esbuild-plugin-less": "^1.3.23", 38 | "jquery": "^3.7.1", 39 | "less": "^4.3.0", 40 | "minimist": "^1.2.8", 41 | "mousetrap": "^1.6.5", 42 | "qtip2": "^3.0.3", 43 | "syntaxhighlighter": "^4.0.1", 44 | "tablesorter": "^2.32.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /perlimports.toml: -------------------------------------------------------------------------------- 1 | # Valid log levels are: 2 | # debug, info, notice, warning, error, critical, alert, emergency 3 | # critical, alert and emergency are not currently used. 4 | # 5 | # Please use boolean values in this config file. Negated options (--no-*) are 6 | # not permitted here. Explicitly set options to true or false. 7 | # 8 | # Some of these values deviate from the regular perlimports defaults. In 9 | # particular, you're encouraged to leave preserve_duplicates and 10 | # preserve_unused disabled. 11 | 12 | cache = false # setting this to true is currently discouraged 13 | ignore_modules = ["Catalyst::Runtime","namespace::clean", "Test::More", "Type::Library", "With::Roles"] 14 | ignore_modules_filename = "" 15 | ignore_modules_pattern = "" # regex like "^(Foo|Foo::Bar)" 16 | ignore_modules_pattern_filename = "" 17 | libs = ["lib", "t/lib"] 18 | log_filename = "" 19 | log_level = "warn" 20 | never_export_modules = [] 21 | never_export_modules_filename = "" 22 | padding = true 23 | preserve_duplicates = false 24 | preserve_unused = false 25 | tidy_whitespace = true 26 | -------------------------------------------------------------------------------- /root/about/contributors.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::about { 2 | %% title => $title || 'MetaCPAN Contributors ordered by commits', 3 | %% } 4 | %% override content -> { 5 |
6 | Number of contributors: [% $contributors.size() %] 7 |
8 |
9 | 20 |
21 | %% } 22 | -------------------------------------------------------------------------------- /root/about/missing_modules.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::about::markdown 2 | %% override about -> { 3 | # Missing module ? - why can I not find a specific module? 4 | 5 | ## Is it in the index? 6 | 7 | MetaCPAN uses the [PAUSE](https://pause.perl.org/)-generated 8 | [02packages.details.txt](https://cpan.metacpan.org/modules/02packages.details.txt) 9 | file. If it's not in there, then the module author will need to fix this. 10 | (Authors are usually emailed about this when they upload a distribution). 11 | 12 | ## Is the distribution POD only with no package? 13 | 14 | A distribution must contain a package, even if it is 100% POD. A good example 15 | of this done correctly is [Catalyst::Manual](/pod/Catalyst::Manual). Check 16 | the package declaration in the source of this file. That's the key to getting 17 | your pure POD distribution indexed by PAUSE. 18 | 19 | ## I still think this is a bug 20 | 21 | We do have bugs, so this is possible, please help by... 22 | 23 | * Please check existing [issues](https://github.com/metacpan/metacpan-web/issues/) 24 | * Create an [issue](https://github.com/metacpan/metacpan-web/issues/new) 25 | * Become a [developer](/about/development) 26 | 27 | %% } 28 | -------------------------------------------------------------------------------- /root/account/favorite/list.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::account 2 | %% override content -> { 3 | %% include inc::favorite_table { 4 | %% favorites => $faves, 5 | %% author => 1, 6 | %% tablesorter => 1, 7 | %% } 8 | %% } 9 | -------------------------------------------------------------------------------- /root/account/identities.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::account 2 | %% override content -> { 3 | 32 | %% } 33 | -------------------------------------------------------------------------------- /root/account/login.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::account 2 | %% override content -> { 3 | %% if $success == "mail_sent" { 4 |

An email has been sent to the email address associated with the PAUSE account. Please check your inbox and verify your account by visiting the link in the mail.

5 |

If you do not receive the email, please ensure that you have properly set up email forwarding for your PAUSE account.

6 | %% } 7 | %% else if $error { 8 |

There has been an error with your request: [% $error %]

9 | %% } 10 | %% } 11 | -------------------------------------------------------------------------------- /root/activity.svg.tx: -------------------------------------------------------------------------------- 1 | 3 | %% my $max = $activity.max() || 1; 4 | %% my $width = (170 / $activity.size()).int(); 5 | %% for $activity -> $week { 6 | %% my $height = $week / $max * 20; 7 | 12 | 17 | %% } 18 | 19 | -------------------------------------------------------------------------------- /root/assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !/.gitignore 3 | -------------------------------------------------------------------------------- /root/author/releases.tx: -------------------------------------------------------------------------------- 1 | %% cascade base with inc::no_sidebar { 2 | %% title => $title || "All releases by " ~ $author.pauseid, 3 | %% } 4 | %% override content -> { 5 | %% include inc::release_table { header => 1, tablesorter => 0 } 6 | %% } 7 | %% override pagination -> { 8 | %% include inc::pager 9 | %% } 10 | -------------------------------------------------------------------------------- /root/base/about.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || 'MetaCPAN About' 3 | %% } 4 | %% override left_nav_classes -> { 'nav nav-pills nav-stacked' } 5 | %% override left_nav_content -> { 6 | [%- 7 | for [ 8 | [ 'About MetaCPAN', '/about' ], 9 | [ 'Sponsor[s|ing]', '/about/sponsors' ], 10 | [ 'Contact', '/about/contact' ], 11 | [ 'Development', '/about/development' ], 12 | [ 'FAQ', '/about/faq' ], 13 | [ 'Contributors', '/about/contributors' ], 14 | [ 'meta::hack', '/about/meta_hack' ], 15 | [ 'Missing Modules', '/about/missing_modules' ], 16 | [ 'Distribution Metadata', '/about/metadata' ], 17 | ] -> $l { 18 | %] 19 |
  • 20 | [% $l.0 %] 21 |
  • 22 | %% } 23 | %% } 24 | %% after content_classes -> { ' about' } 25 | -------------------------------------------------------------------------------- /root/base/about/markdown.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::about 2 | %% after content_classes -> { ' anchors' } 3 | %% override content -> { 4 | %% block about | markdown -> { } 5 | %% } 6 | -------------------------------------------------------------------------------- /root/base/account.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || 'MetaCPAN Account', 3 | %% } 4 | %% override left_nav_classes -> { 'nav nav-pills nav-stacked' } 5 | %% override left_nav_content -> { 6 |
  • 7 | Identities 8 |
  • 9 |
  • 10 | Profile 11 |
  • 12 |
  • 13 | Favorites 14 |
  • 15 |
  • 16 | Logout 17 |
  • 18 | %% } 19 | -------------------------------------------------------------------------------- /root/base/error.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::search with inc::no_sidebar { 2 | %% title => $title || 'Error ' ~ $status_code ~ ' - ' ~ $status_message, 3 | %% } 4 | %% after content_classes -> { ' error-page' } 5 | %% override content -> { 6 |

    [% $status_message %]

    7 | 8 | %% if $message { 9 |

    [% $message %]

    10 | %% } 11 | 12 | %% if $suggest { 13 |

    14 | [% $suggest.description %]: 15 | [% $suggest.link_text %] 16 |

    17 | %% } 18 | 19 | %% if $search_terms && $search_terms.size() { 20 | %% my $q = $search_terms.join(" "); 21 |

    22 | Search the CPAN for [% $q %] 23 |

    24 | %% } 25 | %% } 26 | -------------------------------------------------------------------------------- /root/base/search.tx: -------------------------------------------------------------------------------- 1 | %% cascade base 2 | -------------------------------------------------------------------------------- /root/base/tools.tx: -------------------------------------------------------------------------------- 1 | %% cascade base 2 | %% override left_nav_classes -> { 'nav nav-pills nav-stacked' } 3 | %% override left_nav_content -> { 4 | [%- 5 | for [ 6 | [ 'Tools', '/tools' ], 7 | [ 'Pod Renderer', '/pod2html' ], 8 | [ 'Lab: Dashboard', '/lab/dashboard' ], 9 | [ 'Lab: Dependencies', '/lab/dependencies' ], 10 | ] -> $l { 11 | %] 12 |
  • 13 | [% $l.0 %] 14 |
  • 15 | %% } 16 | %% } 17 | -------------------------------------------------------------------------------- /root/favorite/leaderboard.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::recent { 2 | %% title => $title || 'Popular Distributions', 3 | %% } 4 | %% override content -> { 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | %% for $leaders -> $leader { 15 | 16 | 17 | 18 | 19 | 20 | %% } 21 | 22 |
    Distribution
    [% $~leader.index + 1 %][% $leader.key %][% $leader.doc_count %] ++
    23 | %% } 24 | -------------------------------------------------------------------------------- /root/favorite/recent.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::recent { 2 | %% title => $title || "Recent Favorites", 3 | %% } 4 | %% override content -> { 5 | %% include inc::favorite_table { favorites => $recent, per_day => 1 } 6 | %% } 7 | %% override pagination -> { 8 | %% include inc::pager 9 | %% } 10 | -------------------------------------------------------------------------------- /root/forbidden.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::error { 2 | %% message => $message || "You don't have permission to access this resource.", 3 | %% } 4 | -------------------------------------------------------------------------------- /root/healthcheck.tx: -------------------------------------------------------------------------------- 1 | [% { status => $status }.json() | raw %] 2 | -------------------------------------------------------------------------------- /root/inc/activity.tx: -------------------------------------------------------------------------------- 1 |
    2 | Activity Graph 3 |
    24 month
    4 |
    5 | -------------------------------------------------------------------------------- /root/inc/author_pic.tx: -------------------------------------------------------------------------------- 1 |
    2 | 3 | Author image 4 | 5 | 6 | 7 | 8 | %% if $author.has_display_name { 9 | [% $author.display_name %] 10 | %% } 11 |
    12 | -------------------------------------------------------------------------------- /root/inc/contributors.tx: -------------------------------------------------------------------------------- 1 | 2 | %% if $contributors.size() { 3 |
    4 | 5 |
    6 |
    7 | 30 |
    31 |
    32 |
    33 | %% } 34 | -------------------------------------------------------------------------------- /root/inc/dependencies.tx: -------------------------------------------------------------------------------- 1 | 32 | -------------------------------------------------------------------------------- /root/inc/favorite.tx: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | 5 | 6 | 7 | 8 |
    9 |
    10 |
    11 | 12 |
    13 | %% if $github && $repository.url { 14 | 20 | %% } 21 | -------------------------------------------------------------------------------- /root/inc/link_to_file.tx: -------------------------------------------------------------------------------- 1 | [% 2 | my $title = $file.documentation || $file.path; 3 | 4 | # If there is pod for this file... 5 | if $file.documentation || $file.pod_lines.size() || $file.has_associated_pod { 6 | -%] 7 | [% $linktext || $title %] 27 | [%- 28 | } 29 | # Else show source. 30 | else { 31 | include inc::link_to_source 32 | } 33 | -%] 34 | -------------------------------------------------------------------------------- /root/inc/link_to_source.tx: -------------------------------------------------------------------------------- 1 | [% $linktext || $file.module_name || $file.path %] 6 | [%- -%] 7 | -------------------------------------------------------------------------------- /root/inc/module_install.tx: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /root/inc/no_sidebar.tx: -------------------------------------------------------------------------------- 1 | %% override sidebar_toggle_button -> { } 2 | %% override left_nav -> { } 3 | -------------------------------------------------------------------------------- /root/inc/notification.tx: -------------------------------------------------------------------------------- 1 | %% if $notification { 2 | %% my $note_tmpl = sprintf('inc/notification/%s.tx', $notification.type.lc()); 3 | %% include $note_tmpl { $notification }; 4 | %% } 5 | -------------------------------------------------------------------------------- /root/inc/notification/adoptme.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::notification::base { 2 | %% title => 'Why not adopt me?', 3 | %% email_subject => 'Adopt ' ~ $module_name ~ '?', 4 | %% email_contact => 'the PAUSE module admins', 5 | %% } 6 | %% override text -> { 7 | This distribution is up for adoption! 8 | %% } 9 | %% override email_body -> { 10 | Hello, 11 | 12 | I'm interested in adopting the [% $module_name %] module. If you can grant me the privilege I will release the next version. 13 | 14 | %% } 15 | -------------------------------------------------------------------------------- /root/inc/notification/base.tx: -------------------------------------------------------------------------------- 1 | 2 | 18 | %% } 19 | -------------------------------------------------------------------------------- /root/inc/notification/deprecated.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::notification::base { 2 | %% title => 'Deprecated.', 3 | %% } 4 | %% override text -> { 5 | The maintainer of this distribution has indicated that it is deprecated and no longer suitable for use. 6 | %% } 7 | -------------------------------------------------------------------------------- /root/inc/notification/handoff.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::notification::base { 2 | %% title => 'Take me over?', 3 | %% email_subject => 'Take over ' ~ $module_name ~ '?', 4 | %% email_contact => 'them', 5 | %% } 6 | %% override text -> { 7 | The maintainer of this distribution is looking for someone to take over! 8 | %% } 9 | %% override email_body -> { 10 | Hello, 11 | 12 | I'm interested in taking over the [% $module_name %] module. If you can grant me the privilege I will release the next version. 13 | 14 | %% } 15 | -------------------------------------------------------------------------------- /root/inc/notification/module_deprecated.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::notification::base { 2 | %% title => 'Deprecated.', 3 | %% } 4 | %% override text -> { 5 | The maintainer of this module has indicated that the module is deprecated and no longer suitable for use. 6 | %% } 7 | -------------------------------------------------------------------------------- /root/inc/notification/needhelp.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::notification::base { 2 | %% title => 'Looking for help!', 3 | %% email_subject => 'Looking for help with ' ~ $module_name ~ '?', 4 | %% email_contact => 'them', 5 | %% } 6 | %% override text -> { 7 | The maintainer of this distribution is looking for people to help them improve this module! 8 | %% } 9 | %% override email_body -> { 10 | Hello, 11 | 12 | I'm willing to provide some time to help you with new feature for the [% $module_name %] module, if you can let me know what you would like to be done. 13 | 14 | %% } 15 | -------------------------------------------------------------------------------- /root/inc/opengraph.tx: -------------------------------------------------------------------------------- 1 | %% block opengraph -> { 2 | 3 | 4 | 5 | 6 | 7 | 8 | %% if $opengraph_description { 9 | 10 | %% } 11 | 12 | %% } 13 | -------------------------------------------------------------------------------- /root/inc/opengraph/author.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::opengraph { 2 | %% opengraph_title => $author.display_name, 3 | %% opengraph_description => "CPAN Author - " ~ $author.display_name, 4 | %% opengraph_image => gravatar_image($author, 400), 5 | %% } 6 | %% after opengraph -> { 7 | %% for $author.profile -> $profile { 8 | %% if $profile.name == "twitter" { 9 | 10 | %% } 11 | %% } 12 | %% } 13 | -------------------------------------------------------------------------------- /root/inc/opengraph/module.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::opengraph { 2 | %% opengraph_title => $file.documentation, 3 | %% opengraph_description => $file.abstract, 4 | %% } 5 | -------------------------------------------------------------------------------- /root/inc/opengraph/release.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::opengraph { 2 | %% opengraph_title => $release.name, 3 | %% opengraph_description => $release.abstract, 4 | %% } 5 | -------------------------------------------------------------------------------- /root/inc/pager.tx: -------------------------------------------------------------------------------- 1 | %% if $pageset && $pageset.total_entries { 2 | %% if $pageset.last_page > 1 { 3 |
    4 |
      5 |
    • 6 | « 7 |
    • 8 | 9 | %% for $pageset.pages_in_set -> $page_num { 10 |
    • 11 | [% $page_num %] 12 |
    • 13 | %% } 14 | 15 |
    • 16 | » 17 |
    • 18 |
    19 |
    20 | %% } 21 | 22 |
    23 | 31 |
    32 | [% $pageset.total_entries | format_number %] 33 | [% pluralize("result", $pageset.total_entries) %] 34 | [% if $took { %] ([% $took / 1000 %] seconds)[% } %] 35 |
    36 |
    37 | %% } 38 | -------------------------------------------------------------------------------- /root/inc/permission.tx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %% for $permissions -> $module { 8 | 9 | 12 | 15 | 20 | 21 | %% } 22 |
    Module ([% $permissions.size() %])Owner ([% $owner_count %])Co-Maintainers ([% $comaint_count %])
    10 | [% $module.module_name %] 11 | 13 | [% $module.owner %] 14 | 16 | %% for $module.co_maintainers -> $co_maintainer { 17 | [% $co_maintainer %] 18 | %% } 19 |
    23 | -------------------------------------------------------------------------------- /root/inc/plussers.tx: -------------------------------------------------------------------------------- 1 | %% if $plussers.authors.size() or $plussers.others { 2 |
    3 | 4 | %% if $plussers.authors.size() { 5 |
    6 | %%# display the gravatar url for each pause plusser alongwith their author page as a link. %> 7 | %% for $plussers.authors.shuffle() -> $plusser { 8 | %% if $~plusser.index >= 5 { last } 9 | [% $plusser.pauseid %] 10 | %% } 11 |
    12 | 13 |
    14 | [% pluralize("%d PAUSE user(s)", $plussers.authors.size()) %] 15 |
    16 | %% } 17 | %% if $plussers.others { 18 |
    19 | [% pluralize("%d non-PAUSE user(s)", $plussers.others) %] 20 |
    21 | %% } 22 |
    23 | %% } 24 | -------------------------------------------------------------------------------- /root/inc/release_status.tx: -------------------------------------------------------------------------------- 1 | %% if $maturity == 'developer' { 2 |
  • 3 | Development release 4 |
  • 5 | %% } 6 | -------------------------------------------------------------------------------- /root/inc/river_gauge.tx: -------------------------------------------------------------------------------- 1 | %%# Unlike an , an grafts the SVG document into the DOM, which 2 | %%# means browsers will display the elements of the SVG. Yay! 3 | %% if $river { 4 | <span class="river-gauge-gauge"> 5 | %% include "river/gauge.svg.tx" { river => $river } 6 | </span> 7 | %% } 8 | %% else { 9 | <object data="/dist/[% $distribution | uri %]/river.svg" 10 | type="image/svg+xml" 11 | width="24px" 12 | height="15px" 13 | alt="river gauge for [% $distribution %]" 14 | class="river-gauge-gauge"></object> 15 | %% } 16 | -------------------------------------------------------------------------------- /root/inc/version_select.tx: -------------------------------------------------------------------------------- 1 | <select class="select-navigator [% $class %]"> 2 | %% my $nav_format = $navigate_format || "/release/%s/%s"; 3 | %% my $view_format = $file_format || "/view/%s"; 4 | %% if $head { 5 | <option disabled [% if $active != 'selected' { 'selected' } %]>[% $head %]</option> 6 | %% } 7 | %% my $versions_bp = $versions.sort(-> $a, $b { ($a.status == 'backpan') cmp ($b.status == 'backpan') }); 8 | %% for $versions_bp -> $version { 9 | %% if $version.status == 'backpan' && $~version.peek_prev.status != 'backpan' { 10 | <optgroup label="BackPAN">' 11 | %% } 12 | <option 13 | [% $release.author == $version.author && $release.name == $version.name ? ($active || "selected") : "" %] 14 | value="[% $nav_format.sprintf($version.author, $version.name); %][% if $file { $view_format.sprintf($file.path); } %]" 15 | > 16 | [%- $version.distnameinfo.version ~ ($version.maturity == 'developer' ? ' DEV' : '') %] 17 | ([% $version.author %] on [% datetime($version.date).to_ymd %]) 18 | [%- if $mark_unauthorized_releases && !$version.authorized { %] UNAUTHORIZED[% } -%] 19 | </option> 20 | %% if $version.status == 'backpan' && $~version.is_last { 21 | </optgroup> 22 | %% } 23 | %% } 24 | </select> 25 | -------------------------------------------------------------------------------- /root/inc/version_select/diff.tx: -------------------------------------------------------------------------------- 1 | %% cascade inc::version_select { 2 | %% head => 'Diff with version', 3 | %% navigate_format => "/release/" ~ $release.author ~ "/" ~ $release.name ~ "/diff/%s/%s", 4 | %% file_format => "/%s", 5 | %% } 6 | -------------------------------------------------------------------------------- /root/internal_error.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::error { 2 | %% message => $message || 'Internal Server Error', 3 | %% } 4 | -------------------------------------------------------------------------------- /root/lab/dependencies.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::tools 2 | %% override content -> { 3 | <div class="row"> 4 | <div class="col-lg-12"> 5 | <h2>List all dependencies of a distribution</h2> 6 | <form class="form-horizontal"> 7 | <div class="input-group"> 8 | <input type="text" name="module" class="form-control"> 9 | <span class="input-group-btn"> 10 | <button class="btn btn-primary" type="submit">Go!</button> 11 | </span> 12 | </div> 13 | </form> 14 | %% if $module { 15 | <div class="row"> 16 | <div class="col-lg-12"> 17 | <h3>Module: <b>[% $module %]</b></h3> 18 | 19 | %% for $data -> $d { 20 | <div> 21 | [% if $d.orig { %]<b>[% } %] 22 | [% $d.dist %] [% $d.date %] [% $d.license.join(', ') %] 23 | [% if $d.orig { %]</b>[% } %] 24 | </div> 25 | %% } 26 | </div> 27 | </div> 28 | %% } 29 | </div> 30 | </div> 31 | %% } 32 | -------------------------------------------------------------------------------- /root/login/pause.tx: -------------------------------------------------------------------------------- 1 | %% cascade base with inc::no_sidebar 2 | %% override content -> { 3 | <div class="jumbotron"> 4 | <div class="container-fluid"> 5 | <div class="col-md-offset-3 col-md-6"> 6 | <p class="text-center">Connect to MetaCPAN using PAUSE</p> 7 | <form action="[% $oauth_url %]"> 8 | <input type="hidden" name="client_id" value="[% $consumer_key %]"> 9 | <input type="hidden" name="choice" value="pause"> 10 | <div class="input-group"> 11 | <span class="input-group-addon"> 12 | PAUSE ID 13 | </span> 14 | <input type="text" class="form-control" name="id" /> 15 | <span class="input-group-btn"> 16 | <button class="btn btn-primary" type="submit">Log in</button> 17 | </span> 18 | </div> 19 | </form> 20 | </div> 21 | </div> 22 | </div> 23 | %% } 24 | -------------------------------------------------------------------------------- /root/mobile/toolbar_search_form.tx: -------------------------------------------------------------------------------- 1 | <div> 2 | <form action="/search"> 3 | <input type="search" class="form-control tool-bar-form" placeholder="Search" name="q"> 4 | <input type="submit" class="hidden"> 5 | </form> 6 | </div> 7 | 8 | -------------------------------------------------------------------------------- /root/no_result.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::error { 2 | %% title => $title || 'Search for "' ~ $search_query ~ '"', 3 | %% } 4 | %% override content -> { 5 | <div class="no-results"> 6 | <h3 class="search-results-header">No search results for [% $search_query %]</h3> 7 | %% if $suggest { 8 | <div class="alert alert-danger"> 9 | Did you mean : 10 | <a href="/search?q=[% $suggest | uri %]">[% $suggest %]</a> 11 | </div> 12 | %% } 13 | %% else { 14 | <h4>Something missing? 15 | <a href="/about/missing_modules">Find out why</a> 16 | </h4> 17 | <p> Sorry, we didn't find a match. Maybe look at <a href="/pod/Task::Kensho">Task::Kensho</a>,<br> 18 | which is a list of recommended modules for Enlightened Perl development. 19 | </p> 20 | <p> 21 | <a class="btn btn-primary btn-large" href="/pod/Task::Kensho"> 22 | Learn more 23 | </a> 24 | </p> 25 | %% } 26 | </div> 27 | %% } 28 | -------------------------------------------------------------------------------- /root/not_found.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::error { 2 | %% message => $message || 'The resource you requested could not be found.', 3 | %% } 4 | -------------------------------------------------------------------------------- /root/permission/author.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || 'Author module permissions for ' ~ $search_term, 3 | %% } 4 | %% override content -> { 5 | 6 | <h1>Author Module Permissions for [% $search_term %]</h1> 7 | 8 | %% include inc::permission 9 | 10 | %% } 11 | -------------------------------------------------------------------------------- /root/permission/distribution.tx: -------------------------------------------------------------------------------- 1 | %% cascade base with inc::no_sidebar { 2 | %% title => $title || 'Module permissions for ' ~ $search_term, 3 | %% } 4 | %% override content -> { 5 | <h1>Module Permissions for [% $search_term %]</h1> 6 | 7 | <table class="table table-striped" style="width: auto; min-width: 33%"> 8 | <tr> 9 | <th>Authorized Releasers ([% $releaser.size() %])</th> 10 | </tr> 11 | %% for $releaser -> $author { 12 | <tr> 13 | <td> 14 | <a href="/author/[% $author %]">[% $author %]</a> 15 | </td> 16 | </tr> 17 | %% } 18 | %% else { 19 | <tr> 20 | <td> 21 | <i>No owner[% if $comaint_count { %] or co-maintainer[% } %] has permissions for all modules in this distribution.</i> 22 | </td> 23 | </tr> 24 | %% } 25 | </table> 26 | 27 | %% include inc::permission 28 | 29 | %% } 30 | -------------------------------------------------------------------------------- /root/permission/module.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || 'Module permissions for ' ~ $search_term, 3 | %% } 4 | %% override content -> { 5 | 6 | <h1>Module Permissions for [% $search_term %]</h1> 7 | 8 | %% for $permissions -> $permission { 9 | <p> 10 | <a href="/pod/[% $permission.module_name %]">[% $permission.module_name %]</a> is owned by <a href="/author/[% $permission.owner %]">[% $permission.owner %]</a>. 11 | </p> 12 | 13 | <p> 14 | This module is also maintained by 15 | </p> 16 | 17 | <ul> 18 | %% for $permission.co_maintainers -> $co_maintainer { 19 | <li><a href="/author/[% $co_maintainer %]">[% $co_maintainer %]</a></li> 20 | %% } 21 | </ul> 22 | %% } 23 | 24 | %% } 25 | -------------------------------------------------------------------------------- /root/plussers.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || 'Plussers - ' ~ $plussers.distribution, 3 | %% } 4 | %% override content -> { 5 | 6 | <div class="plusser-title"> 7 | <h4> PAUSE users who ++ed <a href="/release/[% $plussers.distribution %]">[% $plussers.distribution %]</a></h4> 8 | <div class="plussers_disp"> 9 | %% for $plussers.authors -> $plusser { 10 | 11 | <div class="plusser"> 12 | <a href="/author/[% $plusser.pauseid %]"> 13 | <img src="[% gravatar_image($plusser, 75) %]" title="[% $plusser.pauseid %]" alt="" width="75" height="75"> 14 | [% $plusser.id %] 15 | </a> 16 | </div> 17 | 18 | %% } 19 | </div> 20 | </div> 21 | 22 | %% } 23 | -------------------------------------------------------------------------------- /root/raw.tx: -------------------------------------------------------------------------------- 1 | %% cascade base 2 | %% override content -> { 3 | 4 | <p> 5 | <a href="/release/[% $file.author %]/[% $file.release %]/raw/[% $file.path %]?download=1">download</a> 6 | </p> 7 | 8 | <pre>[% $source %]</pre> 9 | 10 | %% } 11 | -------------------------------------------------------------------------------- /root/recent.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::recent { 2 | %% title => $title || 'Recent', 3 | %% rss => $rss || '/recent.rss' ~ ( $filter ? '?f=' ~ $filter : ''), 4 | %% rss_title => $rss_title || 'Recent CPAN Uploads - MetaCPAN', 5 | %% } 6 | %% override content -> { 7 | <div id="metacpan_feed_subscription" class="page-header"> 8 | <p>Recent Uploads</p> 9 | <a href="/recent.rss[% if $filter { '?f=' ~ $filter } %]"><i class="fa fa-rss fa-2x black"></i></a> 10 | </div> 11 | %% include inc::release_table { releases => $recent, per_day => 1 } 12 | %% } 13 | %% override pagination -> { 14 | %% include inc::pager 15 | %% } 16 | -------------------------------------------------------------------------------- /root/recent/topuploaders.tx: -------------------------------------------------------------------------------- 1 | %% cascade base::recent { 2 | %% title => $title || "CPAN Top Uploaders", 3 | %% } 4 | %% after content_classes -> { ' toplists row' } 5 | %% override content -> { 6 | %% for $authors -> $author { 7 | <div class="entry col-sm-6 col-md-3"> 8 | <div class="gravatar"> 9 | <a href="/author/[% $author.pauseid %]"> 10 | <img src="[% gravatar_image($author, 75) %]" class="author-img" style="width: 75px; height: 75px"> 11 | </a> 12 | </div> 13 | <strong class="pauseid"> 14 | <a rel="author" href="/author/[% $author.pauseid %]">[% $author.pauseid %]</a> 15 | </strong> 16 | <span class="name">[% $author.display_name %]</span> 17 | <strong class="count">[% $author.releases %] release[% if $author.releases > 1 { %]s[% } %]</strong> 18 | </div> 19 | %% } 20 | %% } 21 | -------------------------------------------------------------------------------- /root/requires.tx: -------------------------------------------------------------------------------- 1 | %% cascade base { 2 | %% title => $title || "Distributions which depend on " ~ $required, 3 | %% } 4 | %% override left_nav_content -> { 5 | <li class="nav-header">Activity</li> 6 | <li> 7 | %% include inc::activity { 8 | %% url => '/' ~ $type_of_required ~ '/' ~ $required ~ '/activity.svg', 9 | %% } 10 | </li> 11 | %% } 12 | %% override content -> { 13 | 14 | <strong>Distributions Which Depend on <a href="/[% $type_of_required %]/[% $required %]">[% $required %]</a></strong> 15 | %% if $releases.size() { 16 | %% include inc::release_table { 17 | %% header => 1, 18 | %% tablesorter => 1, 19 | %% default_sort => '2,1', 20 | %% table_id => 'revdep_releases', 21 | %% }; 22 | %% } 23 | %% else { 24 | <p>No distributions depending on <a href="/[% $type_of_required %]/[% $required %]">[% $required %]</a> could be found</p> 25 | %% } 26 | 27 | %% } 28 | %% override pagination -> { 29 | %% include inc::pager 30 | %% } 31 | -------------------------------------------------------------------------------- /root/static/css/user.css: -------------------------------------------------------------------------------- 1 | /* Specific css for User actions */ 2 | 3 | .logged_in { 4 | display: none; 5 | } 6 | 7 | .logged_out { 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /root/static/fastly_do_not_delete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/fastly_do_not_delete.gif -------------------------------------------------------------------------------- /root/static/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /root/static/icons/favicon-16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/favicon-16.ico -------------------------------------------------------------------------------- /root/static/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/favicon.ico -------------------------------------------------------------------------------- /root/static/icons/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/folder.png -------------------------------------------------------------------------------- /root/static/icons/grid.svg: -------------------------------------------------------------------------------- 1 | <svg viewBox="0 0 160 160" width="16px" height="16px" xmlns="http://www.w3.org/2000/svg"> 2 | <path fill-opacity="0" style="stroke: #000; stroke-width: 10" d=" 3 | M 16,16 4 | h 128 5 | v 128 6 | h -128 7 | z 8 | m 32,0 v 128 9 | m 32,0 v -128 10 | m 32,0 v 128 11 | m 32,-32 h -128 12 | m 0,-32 h 128 13 | m 0,-32 h -128 14 | "></path> 15 | </svg> 16 | -------------------------------------------------------------------------------- /root/static/icons/page_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/page_white.png -------------------------------------------------------------------------------- /root/static/icons/page_white_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/page_white_c.png -------------------------------------------------------------------------------- /root/static/icons/page_white_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/icons/page_white_code.png -------------------------------------------------------------------------------- /root/static/images/dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/dots.png -------------------------------------------------------------------------------- /root/static/images/dots.svg: -------------------------------------------------------------------------------- 1 | <svg 2 | xmlns="http://www.w3.org/2000/svg" 3 | x="0" 4 | y="0" 5 | width="64" 6 | height="64" 7 | viewBox="0 0 16 16" 8 | preserveAspectRatio="xMinYMin meet" 9 | > 10 | <g fill="#DA2037"> 11 | <circle cx="4" cy="4" r="3" /> 12 | <circle cx="4" cy="12" r="3" /> 13 | <circle cx="12" cy="4" r="3" /> 14 | <circle cx="12" cy="12" r="3" /> 15 | </g> 16 | </svg> 17 | -------------------------------------------------------------------------------- /root/static/images/flag/ad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ad.png -------------------------------------------------------------------------------- /root/static/images/flag/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ae.png -------------------------------------------------------------------------------- /root/static/images/flag/af.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/af.png -------------------------------------------------------------------------------- /root/static/images/flag/ag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ag.png -------------------------------------------------------------------------------- /root/static/images/flag/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ai.png -------------------------------------------------------------------------------- /root/static/images/flag/al.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/al.png -------------------------------------------------------------------------------- /root/static/images/flag/am.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/am.png -------------------------------------------------------------------------------- /root/static/images/flag/an.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/an.png -------------------------------------------------------------------------------- /root/static/images/flag/ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ao.png -------------------------------------------------------------------------------- /root/static/images/flag/ar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ar.png -------------------------------------------------------------------------------- /root/static/images/flag/as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/as.png -------------------------------------------------------------------------------- /root/static/images/flag/at.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/at.png -------------------------------------------------------------------------------- /root/static/images/flag/au.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/au.png -------------------------------------------------------------------------------- /root/static/images/flag/aw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/aw.png -------------------------------------------------------------------------------- /root/static/images/flag/ax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ax.png -------------------------------------------------------------------------------- /root/static/images/flag/az.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/az.png -------------------------------------------------------------------------------- /root/static/images/flag/ba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ba.png -------------------------------------------------------------------------------- /root/static/images/flag/bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bb.png -------------------------------------------------------------------------------- /root/static/images/flag/bd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bd.png -------------------------------------------------------------------------------- /root/static/images/flag/be.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/be.png -------------------------------------------------------------------------------- /root/static/images/flag/bf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bf.png -------------------------------------------------------------------------------- /root/static/images/flag/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bg.png -------------------------------------------------------------------------------- /root/static/images/flag/bh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bh.png -------------------------------------------------------------------------------- /root/static/images/flag/bi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bi.png -------------------------------------------------------------------------------- /root/static/images/flag/bj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bj.png -------------------------------------------------------------------------------- /root/static/images/flag/bm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bm.png -------------------------------------------------------------------------------- /root/static/images/flag/bn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bn.png -------------------------------------------------------------------------------- /root/static/images/flag/bo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bo.png -------------------------------------------------------------------------------- /root/static/images/flag/br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/br.png -------------------------------------------------------------------------------- /root/static/images/flag/bs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bs.png -------------------------------------------------------------------------------- /root/static/images/flag/bt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bt.png -------------------------------------------------------------------------------- /root/static/images/flag/bv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bv.png -------------------------------------------------------------------------------- /root/static/images/flag/bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bw.png -------------------------------------------------------------------------------- /root/static/images/flag/by.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/by.png -------------------------------------------------------------------------------- /root/static/images/flag/bz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/bz.png -------------------------------------------------------------------------------- /root/static/images/flag/ca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ca.png -------------------------------------------------------------------------------- /root/static/images/flag/catalonia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/catalonia.png -------------------------------------------------------------------------------- /root/static/images/flag/cc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cc.png -------------------------------------------------------------------------------- /root/static/images/flag/cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cd.png -------------------------------------------------------------------------------- /root/static/images/flag/cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cf.png -------------------------------------------------------------------------------- /root/static/images/flag/cg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cg.png -------------------------------------------------------------------------------- /root/static/images/flag/ch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ch.png -------------------------------------------------------------------------------- /root/static/images/flag/ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ci.png -------------------------------------------------------------------------------- /root/static/images/flag/ck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ck.png -------------------------------------------------------------------------------- /root/static/images/flag/cl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cl.png -------------------------------------------------------------------------------- /root/static/images/flag/cm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cm.png -------------------------------------------------------------------------------- /root/static/images/flag/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cn.png -------------------------------------------------------------------------------- /root/static/images/flag/co.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/co.png -------------------------------------------------------------------------------- /root/static/images/flag/cr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cr.png -------------------------------------------------------------------------------- /root/static/images/flag/cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cs.png -------------------------------------------------------------------------------- /root/static/images/flag/ct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ct.png -------------------------------------------------------------------------------- /root/static/images/flag/cu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cu.png -------------------------------------------------------------------------------- /root/static/images/flag/cv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cv.png -------------------------------------------------------------------------------- /root/static/images/flag/cx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cx.png -------------------------------------------------------------------------------- /root/static/images/flag/cy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cy.png -------------------------------------------------------------------------------- /root/static/images/flag/cz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/cz.png -------------------------------------------------------------------------------- /root/static/images/flag/de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/de.png -------------------------------------------------------------------------------- /root/static/images/flag/dj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/dj.png -------------------------------------------------------------------------------- /root/static/images/flag/dk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/dk.png -------------------------------------------------------------------------------- /root/static/images/flag/dm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/dm.png -------------------------------------------------------------------------------- /root/static/images/flag/do.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/do.png -------------------------------------------------------------------------------- /root/static/images/flag/dz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/dz.png -------------------------------------------------------------------------------- /root/static/images/flag/ec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ec.png -------------------------------------------------------------------------------- /root/static/images/flag/ee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ee.png -------------------------------------------------------------------------------- /root/static/images/flag/eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/eg.png -------------------------------------------------------------------------------- /root/static/images/flag/eh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/eh.png -------------------------------------------------------------------------------- /root/static/images/flag/england.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/england.png -------------------------------------------------------------------------------- /root/static/images/flag/er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/er.png -------------------------------------------------------------------------------- /root/static/images/flag/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/es.png -------------------------------------------------------------------------------- /root/static/images/flag/et.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/et.png -------------------------------------------------------------------------------- /root/static/images/flag/europeanunion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/europeanunion.png -------------------------------------------------------------------------------- /root/static/images/flag/fam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fam.png -------------------------------------------------------------------------------- /root/static/images/flag/fi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fi.png -------------------------------------------------------------------------------- /root/static/images/flag/fj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fj.png -------------------------------------------------------------------------------- /root/static/images/flag/fk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fk.png -------------------------------------------------------------------------------- /root/static/images/flag/fm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fm.png -------------------------------------------------------------------------------- /root/static/images/flag/fo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fo.png -------------------------------------------------------------------------------- /root/static/images/flag/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/fr.png -------------------------------------------------------------------------------- /root/static/images/flag/ga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ga.png -------------------------------------------------------------------------------- /root/static/images/flag/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gb.png -------------------------------------------------------------------------------- /root/static/images/flag/gd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gd.png -------------------------------------------------------------------------------- /root/static/images/flag/ge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ge.png -------------------------------------------------------------------------------- /root/static/images/flag/gf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gf.png -------------------------------------------------------------------------------- /root/static/images/flag/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gh.png -------------------------------------------------------------------------------- /root/static/images/flag/gi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gi.png -------------------------------------------------------------------------------- /root/static/images/flag/gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gl.png -------------------------------------------------------------------------------- /root/static/images/flag/gm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gm.png -------------------------------------------------------------------------------- /root/static/images/flag/gn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gn.png -------------------------------------------------------------------------------- /root/static/images/flag/gp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gp.png -------------------------------------------------------------------------------- /root/static/images/flag/gq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gq.png -------------------------------------------------------------------------------- /root/static/images/flag/gr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gr.png -------------------------------------------------------------------------------- /root/static/images/flag/gs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gs.png -------------------------------------------------------------------------------- /root/static/images/flag/gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gt.png -------------------------------------------------------------------------------- /root/static/images/flag/gu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gu.png -------------------------------------------------------------------------------- /root/static/images/flag/gw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gw.png -------------------------------------------------------------------------------- /root/static/images/flag/gy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/gy.png -------------------------------------------------------------------------------- /root/static/images/flag/hk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/hk.png -------------------------------------------------------------------------------- /root/static/images/flag/hm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/hm.png -------------------------------------------------------------------------------- /root/static/images/flag/hn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/hn.png -------------------------------------------------------------------------------- /root/static/images/flag/hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/hr.png -------------------------------------------------------------------------------- /root/static/images/flag/ht.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ht.png -------------------------------------------------------------------------------- /root/static/images/flag/hu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/hu.png -------------------------------------------------------------------------------- /root/static/images/flag/id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/id.png -------------------------------------------------------------------------------- /root/static/images/flag/ie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ie.png -------------------------------------------------------------------------------- /root/static/images/flag/il.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/il.png -------------------------------------------------------------------------------- /root/static/images/flag/in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/in.png -------------------------------------------------------------------------------- /root/static/images/flag/io.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/io.png -------------------------------------------------------------------------------- /root/static/images/flag/iq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/iq.png -------------------------------------------------------------------------------- /root/static/images/flag/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ir.png -------------------------------------------------------------------------------- /root/static/images/flag/is.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/is.png -------------------------------------------------------------------------------- /root/static/images/flag/it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/it.png -------------------------------------------------------------------------------- /root/static/images/flag/jm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/jm.png -------------------------------------------------------------------------------- /root/static/images/flag/jo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/jo.png -------------------------------------------------------------------------------- /root/static/images/flag/jp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/jp.png -------------------------------------------------------------------------------- /root/static/images/flag/ke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ke.png -------------------------------------------------------------------------------- /root/static/images/flag/kg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kg.png -------------------------------------------------------------------------------- /root/static/images/flag/kh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kh.png -------------------------------------------------------------------------------- /root/static/images/flag/ki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ki.png -------------------------------------------------------------------------------- /root/static/images/flag/km.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/km.png -------------------------------------------------------------------------------- /root/static/images/flag/kn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kn.png -------------------------------------------------------------------------------- /root/static/images/flag/kp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kp.png -------------------------------------------------------------------------------- /root/static/images/flag/kr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kr.png -------------------------------------------------------------------------------- /root/static/images/flag/kw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kw.png -------------------------------------------------------------------------------- /root/static/images/flag/ky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ky.png -------------------------------------------------------------------------------- /root/static/images/flag/kz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/kz.png -------------------------------------------------------------------------------- /root/static/images/flag/la.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/la.png -------------------------------------------------------------------------------- /root/static/images/flag/lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lb.png -------------------------------------------------------------------------------- /root/static/images/flag/lc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lc.png -------------------------------------------------------------------------------- /root/static/images/flag/li.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/li.png -------------------------------------------------------------------------------- /root/static/images/flag/lk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lk.png -------------------------------------------------------------------------------- /root/static/images/flag/lr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lr.png -------------------------------------------------------------------------------- /root/static/images/flag/ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ls.png -------------------------------------------------------------------------------- /root/static/images/flag/lt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lt.png -------------------------------------------------------------------------------- /root/static/images/flag/lu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lu.png -------------------------------------------------------------------------------- /root/static/images/flag/lv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/lv.png -------------------------------------------------------------------------------- /root/static/images/flag/ly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ly.png -------------------------------------------------------------------------------- /root/static/images/flag/ma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ma.png -------------------------------------------------------------------------------- /root/static/images/flag/mc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mc.png -------------------------------------------------------------------------------- /root/static/images/flag/md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/md.png -------------------------------------------------------------------------------- /root/static/images/flag/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/me.png -------------------------------------------------------------------------------- /root/static/images/flag/mg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mg.png -------------------------------------------------------------------------------- /root/static/images/flag/mh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mh.png -------------------------------------------------------------------------------- /root/static/images/flag/mk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mk.png -------------------------------------------------------------------------------- /root/static/images/flag/ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ml.png -------------------------------------------------------------------------------- /root/static/images/flag/mm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mm.png -------------------------------------------------------------------------------- /root/static/images/flag/mn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mn.png -------------------------------------------------------------------------------- /root/static/images/flag/mo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mo.png -------------------------------------------------------------------------------- /root/static/images/flag/mp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mp.png -------------------------------------------------------------------------------- /root/static/images/flag/mq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mq.png -------------------------------------------------------------------------------- /root/static/images/flag/mr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mr.png -------------------------------------------------------------------------------- /root/static/images/flag/ms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ms.png -------------------------------------------------------------------------------- /root/static/images/flag/mt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mt.png -------------------------------------------------------------------------------- /root/static/images/flag/mu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mu.png -------------------------------------------------------------------------------- /root/static/images/flag/mv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mv.png -------------------------------------------------------------------------------- /root/static/images/flag/mw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mw.png -------------------------------------------------------------------------------- /root/static/images/flag/mx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mx.png -------------------------------------------------------------------------------- /root/static/images/flag/my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/my.png -------------------------------------------------------------------------------- /root/static/images/flag/mz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/mz.png -------------------------------------------------------------------------------- /root/static/images/flag/na.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/na.png -------------------------------------------------------------------------------- /root/static/images/flag/nc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nc.png -------------------------------------------------------------------------------- /root/static/images/flag/ne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ne.png -------------------------------------------------------------------------------- /root/static/images/flag/nf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nf.png -------------------------------------------------------------------------------- /root/static/images/flag/ng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ng.png -------------------------------------------------------------------------------- /root/static/images/flag/ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ni.png -------------------------------------------------------------------------------- /root/static/images/flag/nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nl.png -------------------------------------------------------------------------------- /root/static/images/flag/no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/no.png -------------------------------------------------------------------------------- /root/static/images/flag/np.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/np.png -------------------------------------------------------------------------------- /root/static/images/flag/nr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nr.png -------------------------------------------------------------------------------- /root/static/images/flag/nu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nu.png -------------------------------------------------------------------------------- /root/static/images/flag/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/nz.png -------------------------------------------------------------------------------- /root/static/images/flag/om.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/om.png -------------------------------------------------------------------------------- /root/static/images/flag/pa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pa.png -------------------------------------------------------------------------------- /root/static/images/flag/pe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pe.png -------------------------------------------------------------------------------- /root/static/images/flag/pf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pf.png -------------------------------------------------------------------------------- /root/static/images/flag/pg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pg.png -------------------------------------------------------------------------------- /root/static/images/flag/ph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ph.png -------------------------------------------------------------------------------- /root/static/images/flag/pk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pk.png -------------------------------------------------------------------------------- /root/static/images/flag/pl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pl.png -------------------------------------------------------------------------------- /root/static/images/flag/pm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pm.png -------------------------------------------------------------------------------- /root/static/images/flag/pn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pn.png -------------------------------------------------------------------------------- /root/static/images/flag/pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pr.png -------------------------------------------------------------------------------- /root/static/images/flag/ps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ps.png -------------------------------------------------------------------------------- /root/static/images/flag/pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pt.png -------------------------------------------------------------------------------- /root/static/images/flag/pw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/pw.png -------------------------------------------------------------------------------- /root/static/images/flag/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/py.png -------------------------------------------------------------------------------- /root/static/images/flag/qa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/qa.png -------------------------------------------------------------------------------- /root/static/images/flag/re.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/re.png -------------------------------------------------------------------------------- /root/static/images/flag/ro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ro.png -------------------------------------------------------------------------------- /root/static/images/flag/rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/rs.png -------------------------------------------------------------------------------- /root/static/images/flag/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ru.png -------------------------------------------------------------------------------- /root/static/images/flag/rw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/rw.png -------------------------------------------------------------------------------- /root/static/images/flag/sa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sa.png -------------------------------------------------------------------------------- /root/static/images/flag/sb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sb.png -------------------------------------------------------------------------------- /root/static/images/flag/sc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sc.png -------------------------------------------------------------------------------- /root/static/images/flag/scotland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/scotland.png -------------------------------------------------------------------------------- /root/static/images/flag/sd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sd.png -------------------------------------------------------------------------------- /root/static/images/flag/se.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/se.png -------------------------------------------------------------------------------- /root/static/images/flag/sg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sg.png -------------------------------------------------------------------------------- /root/static/images/flag/sh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sh.png -------------------------------------------------------------------------------- /root/static/images/flag/si.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/si.png -------------------------------------------------------------------------------- /root/static/images/flag/sj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sj.png -------------------------------------------------------------------------------- /root/static/images/flag/sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sk.png -------------------------------------------------------------------------------- /root/static/images/flag/sl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sl.png -------------------------------------------------------------------------------- /root/static/images/flag/sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sm.png -------------------------------------------------------------------------------- /root/static/images/flag/sn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sn.png -------------------------------------------------------------------------------- /root/static/images/flag/so.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/so.png -------------------------------------------------------------------------------- /root/static/images/flag/sr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sr.png -------------------------------------------------------------------------------- /root/static/images/flag/st.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/st.png -------------------------------------------------------------------------------- /root/static/images/flag/sv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sv.png -------------------------------------------------------------------------------- /root/static/images/flag/sy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sy.png -------------------------------------------------------------------------------- /root/static/images/flag/sz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/sz.png -------------------------------------------------------------------------------- /root/static/images/flag/tc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tc.png -------------------------------------------------------------------------------- /root/static/images/flag/td.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/td.png -------------------------------------------------------------------------------- /root/static/images/flag/tf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tf.png -------------------------------------------------------------------------------- /root/static/images/flag/tg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tg.png -------------------------------------------------------------------------------- /root/static/images/flag/th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/th.png -------------------------------------------------------------------------------- /root/static/images/flag/tj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tj.png -------------------------------------------------------------------------------- /root/static/images/flag/tk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tk.png -------------------------------------------------------------------------------- /root/static/images/flag/tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tl.png -------------------------------------------------------------------------------- /root/static/images/flag/tm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tm.png -------------------------------------------------------------------------------- /root/static/images/flag/tn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tn.png -------------------------------------------------------------------------------- /root/static/images/flag/to.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/to.png -------------------------------------------------------------------------------- /root/static/images/flag/tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tr.png -------------------------------------------------------------------------------- /root/static/images/flag/tt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tt.png -------------------------------------------------------------------------------- /root/static/images/flag/tv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tv.png -------------------------------------------------------------------------------- /root/static/images/flag/tw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tw.png -------------------------------------------------------------------------------- /root/static/images/flag/tz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/tz.png -------------------------------------------------------------------------------- /root/static/images/flag/ua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ua.png -------------------------------------------------------------------------------- /root/static/images/flag/ug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ug.png -------------------------------------------------------------------------------- /root/static/images/flag/uk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/uk.png -------------------------------------------------------------------------------- /root/static/images/flag/um.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/um.png -------------------------------------------------------------------------------- /root/static/images/flag/us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/us.png -------------------------------------------------------------------------------- /root/static/images/flag/uy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/uy.png -------------------------------------------------------------------------------- /root/static/images/flag/uz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/uz.png -------------------------------------------------------------------------------- /root/static/images/flag/va.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/va.png -------------------------------------------------------------------------------- /root/static/images/flag/vc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/vc.png -------------------------------------------------------------------------------- /root/static/images/flag/ve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ve.png -------------------------------------------------------------------------------- /root/static/images/flag/vg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/vg.png -------------------------------------------------------------------------------- /root/static/images/flag/vi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/vi.png -------------------------------------------------------------------------------- /root/static/images/flag/vn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/vn.png -------------------------------------------------------------------------------- /root/static/images/flag/vu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/vu.png -------------------------------------------------------------------------------- /root/static/images/flag/wales.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/wales.png -------------------------------------------------------------------------------- /root/static/images/flag/wf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/wf.png -------------------------------------------------------------------------------- /root/static/images/flag/ws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ws.png -------------------------------------------------------------------------------- /root/static/images/flag/ye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/ye.png -------------------------------------------------------------------------------- /root/static/images/flag/yt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/yt.png -------------------------------------------------------------------------------- /root/static/images/flag/za.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/za.png -------------------------------------------------------------------------------- /root/static/images/flag/zm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/zm.png -------------------------------------------------------------------------------- /root/static/images/flag/zw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/flag/zw.png -------------------------------------------------------------------------------- /root/static/images/gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/gray.png -------------------------------------------------------------------------------- /root/static/images/profile/bitbucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/bitbucket.png -------------------------------------------------------------------------------- /root/static/images/profile/blinklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/blinklist.png -------------------------------------------------------------------------------- /root/static/images/profile/brightkite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/brightkite.png -------------------------------------------------------------------------------- /root/static/images/profile/coderwall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/coderwall.png -------------------------------------------------------------------------------- /root/static/images/profile/couchsurfing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/couchsurfing.png -------------------------------------------------------------------------------- /root/static/images/profile/design_float.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/design_float.png -------------------------------------------------------------------------------- /root/static/images/profile/dopplr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/dopplr.png -------------------------------------------------------------------------------- /root/static/images/profile/dotshare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/dotshare.png -------------------------------------------------------------------------------- /root/static/images/profile/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/email.png -------------------------------------------------------------------------------- /root/static/images/profile/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/facebook.png -------------------------------------------------------------------------------- /root/static/images/profile/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/feed.png -------------------------------------------------------------------------------- /root/static/images/profile/flickr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/flickr.png -------------------------------------------------------------------------------- /root/static/images/profile/friendfeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/friendfeed.png -------------------------------------------------------------------------------- /root/static/images/profile/furl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/furl.png -------------------------------------------------------------------------------- /root/static/images/profile/gamespot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/gamespot.png -------------------------------------------------------------------------------- /root/static/images/profile/geeklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/geeklist.png -------------------------------------------------------------------------------- /root/static/images/profile/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/github.png -------------------------------------------------------------------------------- /root/static/images/profile/gitlab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/gitlab.png -------------------------------------------------------------------------------- /root/static/images/profile/gitorious.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/gitorious.png -------------------------------------------------------------------------------- /root/static/images/profile/gittip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/gittip.png -------------------------------------------------------------------------------- /root/static/images/profile/hackernews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/hackernews.png -------------------------------------------------------------------------------- /root/static/images/profile/hackerrank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/hackerrank.png -------------------------------------------------------------------------------- /root/static/images/profile/hackthissite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/hackthissite.png -------------------------------------------------------------------------------- /root/static/images/profile/identica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/identica.png -------------------------------------------------------------------------------- /root/static/images/profile/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/instagram.png -------------------------------------------------------------------------------- /root/static/images/profile/lastfm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/lastfm.png -------------------------------------------------------------------------------- /root/static/images/profile/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/linkedin.png -------------------------------------------------------------------------------- /root/static/images/profile/magnolia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/magnolia.png -------------------------------------------------------------------------------- /root/static/images/profile/meetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/meetup.png -------------------------------------------------------------------------------- /root/static/images/profile/metacpan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/metacpan.png -------------------------------------------------------------------------------- /root/static/images/profile/mixx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/mixx.png -------------------------------------------------------------------------------- /root/static/images/profile/myspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/myspace.png -------------------------------------------------------------------------------- /root/static/images/profile/nerdability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/nerdability.png -------------------------------------------------------------------------------- /root/static/images/profile/newsblur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/newsblur.png -------------------------------------------------------------------------------- /root/static/images/profile/newsvine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/newsvine.png -------------------------------------------------------------------------------- /root/static/images/profile/ohloh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/ohloh.png -------------------------------------------------------------------------------- /root/static/images/profile/orcid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/orcid.png -------------------------------------------------------------------------------- /root/static/images/profile/perlmonks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/perlmonks.png -------------------------------------------------------------------------------- /root/static/images/profile/pinboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/pinboard.png -------------------------------------------------------------------------------- /root/static/images/profile/playperl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/playperl.png -------------------------------------------------------------------------------- /root/static/images/profile/posterous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/posterous.png -------------------------------------------------------------------------------- /root/static/images/profile/reddit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/reddit.png -------------------------------------------------------------------------------- /root/static/images/profile/slideshare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/slideshare.png -------------------------------------------------------------------------------- /root/static/images/profile/sourceforge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/sourceforge.png -------------------------------------------------------------------------------- /root/static/images/profile/speakerdeck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/speakerdeck.png -------------------------------------------------------------------------------- /root/static/images/profile/sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/sphere.png -------------------------------------------------------------------------------- /root/static/images/profile/sphinn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/sphinn.png -------------------------------------------------------------------------------- /root/static/images/profile/stackexchange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/stackexchange.png -------------------------------------------------------------------------------- /root/static/images/profile/stackoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/stackoverflow.png -------------------------------------------------------------------------------- /root/static/images/profile/stackoverflowcareers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/stackoverflowcareers.png -------------------------------------------------------------------------------- /root/static/images/profile/steam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/steam.png -------------------------------------------------------------------------------- /root/static/images/profile/stumbleupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/stumbleupon.png -------------------------------------------------------------------------------- /root/static/images/profile/substack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/substack.png -------------------------------------------------------------------------------- /root/static/images/profile/technorati.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/technorati.png -------------------------------------------------------------------------------- /root/static/images/profile/tripadvisor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/tripadvisor.png -------------------------------------------------------------------------------- /root/static/images/profile/tumblr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/tumblr.png -------------------------------------------------------------------------------- /root/static/images/profile/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/twitter.png -------------------------------------------------------------------------------- /root/static/images/profile/vimeo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/vimeo.png -------------------------------------------------------------------------------- /root/static/images/profile/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/profile/youtube.png -------------------------------------------------------------------------------- /root/static/images/sponsors/activestate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/activestate.png -------------------------------------------------------------------------------- /root/static/images/sponsors/advance-systems.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/advance-systems.jpg -------------------------------------------------------------------------------- /root/static/images/sponsors/booking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/booking.png -------------------------------------------------------------------------------- /root/static/images/sponsors/control-my-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/control-my-id.png -------------------------------------------------------------------------------- /root/static/images/sponsors/cpanel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/cpanel.png -------------------------------------------------------------------------------- /root/static/images/sponsors/datadog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/datadog.png -------------------------------------------------------------------------------- /root/static/images/sponsors/dealspotr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/dealspotr.png -------------------------------------------------------------------------------- /root/static/images/sponsors/dyn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/dyn.png -------------------------------------------------------------------------------- /root/static/images/sponsors/easyname.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/easyname.png -------------------------------------------------------------------------------- /root/static/images/sponsors/epo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/epo.png -------------------------------------------------------------------------------- /root/static/images/sponsors/github_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/github_logo.png -------------------------------------------------------------------------------- /root/static/images/sponsors/idonethis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/idonethis.png -------------------------------------------------------------------------------- /root/static/images/sponsors/liquidweb_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/liquidweb_logo.png -------------------------------------------------------------------------------- /root/static/images/sponsors/panopta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/panopta.png -------------------------------------------------------------------------------- /root/static/images/sponsors/perl-careers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/perl-careers.png -------------------------------------------------------------------------------- /root/static/images/sponsors/perl_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/perl_logo.png -------------------------------------------------------------------------------- /root/static/images/sponsors/qah-2014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/qah-2014.png -------------------------------------------------------------------------------- /root/static/images/sponsors/route4me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/route4me.png -------------------------------------------------------------------------------- /root/static/images/sponsors/servercentral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/servercentral.png -------------------------------------------------------------------------------- /root/static/images/sponsors/sonic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/sonic.png -------------------------------------------------------------------------------- /root/static/images/sponsors/speedchilli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/speedchilli.png -------------------------------------------------------------------------------- /root/static/images/sponsors/travis-ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/travis-ci.png -------------------------------------------------------------------------------- /root/static/images/sponsors/vienna.pm.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/vienna.pm.jpeg -------------------------------------------------------------------------------- /root/static/images/sponsors/yellowbot-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/yellowbot-small.png -------------------------------------------------------------------------------- /root/static/images/sponsors/yellowbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/yellowbot.png -------------------------------------------------------------------------------- /root/static/images/sponsors/yellowbot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metacpan/metacpan-web/65fe1f33374ff888835f7a593a25bf9d572f24b5/root/static/images/sponsors/yellowbot_2.png -------------------------------------------------------------------------------- /root/static/js/bootstrap-slidepanel.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | for (const toggle of document.querySelectorAll('[data-toggle="slidepanel"]')) { 4 | const panel = document.querySelector(toggle.dataset.target); 5 | if (!panel) { 6 | continue; 7 | } 8 | 9 | const showAnim = new Animation(new KeyframeEffect( 10 | panel, { 11 | transform: ['translateX(-100%)', 'translateX(0)'] 12 | }, 13 | 200 14 | )); 15 | 16 | const hideAnim = new Animation(new KeyframeEffect( 17 | panel, { 18 | transform: ['translateX(0)', 'translateX(-100%)'] 19 | }, 20 | 200 21 | )); 22 | hideAnim.addEventListener('finish', () => { 23 | panel.style.removeProperty('visibility'); 24 | }); 25 | 26 | toggle.addEventListener('click', function(e) { 27 | e.preventDefault(); 28 | 29 | toggle.classList.toggle('slidepanel-visible'); 30 | panel.style.visibility = 'visible'; 31 | if (panel.classList.toggle('slidepanel-visible')) { 32 | showAnim.play(); 33 | } 34 | else { 35 | hideAnim.play(); 36 | } 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /root/static/js/brush-cpan-changes.js: -------------------------------------------------------------------------------- 1 | const BrushBase = require('brush-base'); 2 | 3 | function Brush() { 4 | this.regexList = [ 5 | // these classes/colors are totally arbitrary 6 | { 7 | regex: /^\{\{\$NEXT\}\}$/gm, 8 | css: 'color3' 9 | }, // placeholder (oops) 10 | { 11 | regex: /^v?([0-9._]+)(-TRIAL)?([ \t]+.+)?/gm, 12 | css: 'constants' 13 | }, // version/date 14 | { 15 | regex: /^\s+\[.+?\]/gm, 16 | css: 'value' 17 | }, // group 18 | { 19 | regex: /^\s+[-*]/gm, 20 | css: 'functions' 21 | }, // item marker 22 | { 23 | regex: /^[^v0-9].+\n(?=\nv?[0-9_.])/g, 24 | css: 'preprocessor' 25 | } // preamble 26 | ]; 27 | }; 28 | 29 | Brush.prototype = new BrushBase(); 30 | Brush.aliases = ['cpanchanges']; 31 | module.exports = Brush; 32 | -------------------------------------------------------------------------------- /root/static/js/dropdown.js: -------------------------------------------------------------------------------- 1 | for (const el of document.querySelectorAll('.dropdown select')) { 2 | el.addEventListener('change', () => { 3 | document.location.href = el.value; 4 | }); 5 | } 6 | -------------------------------------------------------------------------------- /root/static/js/google-analytics.mjs: -------------------------------------------------------------------------------- 1 | window.dataLayer = window.dataLayer || []; 2 | 3 | const gtag = (...args) => { 4 | window.dataLayer.push(args); 5 | }; 6 | 7 | gtag('js', new Date()); 8 | gtag('config', 'G-E82Q2V8LVD', { 9 | cookie_flags: 'SameSite=Lax;Secure' 10 | }); 11 | 12 | export { 13 | gtag, 14 | gtag as 15 | default, 16 | }; 17 | -------------------------------------------------------------------------------- /root/static/js/inject.mjs: -------------------------------------------------------------------------------- 1 | import jQuery from 'jquery'; 2 | export { 3 | jQuery, 4 | }; 5 | -------------------------------------------------------------------------------- /root/static/js/main.mjs: -------------------------------------------------------------------------------- 1 | import './google-analytics.mjs'; 2 | import './autocomplete.mjs'; 3 | import './tablesorter.mjs'; 4 | import './cpan.js'; 5 | import './github.js'; 6 | import './dropdown.js'; 7 | import './profile.js'; 8 | import './search.js'; 9 | import 'bootstrap/js/dropdown.js'; 10 | import 'bootstrap/js/collapse.js'; 11 | import 'bootstrap/js/modal.js'; 12 | import 'bootstrap/js/tooltip.js'; 13 | import 'bootstrap/js/affix.js'; 14 | import './bootstrap-slidepanel.js'; 15 | import './syntaxhighlighter.mjs'; 16 | import './pod2html.mjs'; 17 | -------------------------------------------------------------------------------- /root/static/js/storage.js: -------------------------------------------------------------------------------- 1 | let storage; 2 | 3 | // provide localStorage shim to work around https://bugzilla.mozilla.org/show_bug.cgi?id=748620 4 | try { 5 | storage = window.localStorage; 6 | } 7 | catch { 8 | // noop 9 | } 10 | if (!storage) { 11 | storage = new class { 12 | getItem(k) { 13 | return this["_" + k]; 14 | } 15 | setItem(k, v) { 16 | return this["_" + k] = v; 17 | } 18 | }; 19 | } 20 | 21 | module.exports = storage; 22 | -------------------------------------------------------------------------------- /root/static/less/about.less: -------------------------------------------------------------------------------- 1 | .about { 2 | margin-bottom: 10px; 3 | 4 | h1 { 5 | border-bottom: 2px dotted @gray-lighter; 6 | } 7 | 8 | ul { 9 | list-style-type: disc; 10 | } 11 | 12 | .lead { 13 | font-size: 120%; 14 | } 15 | } 16 | 17 | .about-sponsor { 18 | table { 19 | width: 100%; 20 | } 21 | 22 | td { 23 | padding: 8px; 24 | vertical-align: top; 25 | } 26 | 27 | img { 28 | margin: 8px 0; 29 | } 30 | 31 | h2 { 32 | margin-top: 2em; 33 | } 34 | 35 | .sponsor td:first-child { 36 | text-align: center; 37 | } 38 | 39 | .sponsor-footer { 40 | text-align: center; 41 | font-weight: bold; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /root/static/less/anchors.less: -------------------------------------------------------------------------------- 1 | // Show bookmark icons when hovering over heading tags. 2 | // The a.anchor may be added by js. 3 | .anchors { 4 | a.anchor { 5 | // Shrink font-size so that heading text isn't offset by invisible icon. 6 | // This size is directly related to the padding/width/etc. 7 | padding-left: 9px; 8 | width: 26px; 9 | margin-left: -26px; 10 | vertical-align: top; 11 | font-size: 14px; 12 | display: inline-block; 13 | 14 | span { 15 | visibility: hidden; 16 | } 17 | } 18 | 19 | *:hover > a.anchor span, 20 | a.anchor:focus span { 21 | visibility: visible; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /root/static/less/breadcrumbs.less: -------------------------------------------------------------------------------- 1 | .breadcrumbs { 2 | column-gap: 5px; 3 | font-weight: bold; 4 | font-size: 1.2em; 5 | display: flex; 6 | flex-wrap: wrap; 7 | justify-self: center; 8 | max-width: 1200px; 9 | padding: 20px 20px 0 20px; 10 | width: 100%; 11 | 12 | a.latest i { 13 | margin: 2px 5px 2px 0; 14 | } 15 | 16 | .dropdown a { 17 | text-decoration: none; 18 | font-size: 0.8em; 19 | } 20 | 21 | .release { 22 | display: flex; 23 | gap: 5px; 24 | position: relative; 25 | 26 | select { 27 | position: absolute; 28 | left: -0.5em; 29 | width: 1.5em; 30 | height: 1.5em; 31 | opacity: 0; 32 | font-weight: normal; 33 | } 34 | 35 | select.extend { 36 | width: 100%; 37 | left: 0; 38 | } 39 | 40 | .dropdown .caret { 41 | margin-left: auto; 42 | margin-right: 2px; 43 | } 44 | } 45 | } 46 | 47 | .plussers { 48 | &.box-right { 49 | padding-top: 0px; 50 | } 51 | 52 | > a > img { 53 | width: 20px; 54 | height: 20px; 55 | border-radius: 3.5px; 56 | } 57 | 58 | margin-bottom: 0.7em; 59 | } 60 | 61 | @media only screen and (min-width: @screen-sm-max) { 62 | .breadcrumbs { 63 | padding: 40px 40px 0px 40px; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /root/static/less/diff.less: -------------------------------------------------------------------------------- 1 | .diff-container { 2 | border: 1px solid #ccc; 3 | background-color: #f9f9f9; 4 | margin-bottom: 10px; 5 | 6 | pre { 7 | border: 0px; 8 | margin: 5px; 9 | } 10 | } 11 | 12 | .diff-header { 13 | background: linear-gradient( 14 | to bottom, 15 | rgb(255, 255, 255), 16 | rgb(221, 221, 221) 17 | ); 18 | padding: 5px; 19 | font-family: @font-family-monospace; 20 | 21 | a { 22 | color: #000; 23 | } 24 | } 25 | 26 | .diff-list { 27 | border-top: 1px solid #eee; 28 | margin-bottom: 20px; 29 | width: 100%; 30 | 31 | tr { 32 | border-bottom: 1px solid #eee; 33 | margin: 2px; 34 | font-family: @font-family-monospace; 35 | } 36 | 37 | .plus, 38 | .minus { 39 | float: right; 40 | padding-left: 5px; 41 | padding-right: 5px; 42 | font-weight: bold; 43 | font-family: sans-serif; 44 | color: #fff; 45 | text-align: center; 46 | border-radius: 3px 3px; 47 | margin-left: 5px; 48 | } 49 | 50 | .plus { 51 | background-color: #090; 52 | } 53 | 54 | .minus { 55 | background-color: #900; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /root/static/less/dropdown.less: -------------------------------------------------------------------------------- 1 | .dropdown { 2 | position: relative; 3 | display: inline-block; 4 | 5 | select { 6 | height: auto; 7 | line-height: 1; 8 | margin: 0; 9 | padding: 0; 10 | position: absolute; 11 | left: 0; 12 | width: 100%; 13 | opacity: 0; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /root/static/less/lab.less: -------------------------------------------------------------------------------- 1 | .dashboard-dist-table { 2 | padding-left: 5px; 3 | padding-right: 5px; 4 | 5 | td { 6 | text-align: center; 7 | 8 | &:nth-child(1), 9 | &:nth-child(2) { 10 | text-align: left; 11 | } 12 | } 13 | 14 | td, 15 | th { 16 | padding-left: 5px; 17 | padding-right: 5px; 18 | } 19 | 20 | .test-ratio-good, 21 | .tests-pass { 22 | color: #090; 23 | } 24 | .test-ratio-bad, 25 | .tests-fail, 26 | .missing { 27 | color: #900; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /root/static/less/notification.less: -------------------------------------------------------------------------------- 1 | #metacpan_notification { 2 | margin-bottom: 15px; 3 | overflow: auto; 4 | position: relative; 5 | } 6 | 7 | .notification-toggle-checkbox { 8 | display: none; 9 | } 10 | 11 | .notification-toggle-checkbox:checked ~ #metacpan_notification { 12 | max-height: 0; 13 | border: none; 14 | min-height: 0; 15 | padding: 0; 16 | margin: 0; 17 | transition: min-height 0.5s cubic-bezier(0, 1, 0.5, 1); 18 | } 19 | 20 | label.remove-notification { 21 | position: absolute; 22 | right: 5px; 23 | top: 5px; 24 | cursor: pointer; 25 | } 26 | 27 | #metacpan_notification h2 { 28 | display: block; 29 | font-weight: bold; 30 | font-size: 100%; 31 | margin: 0; 32 | line-height: inherit; 33 | } 34 | 35 | .notify-NEEDHELP { 36 | background: #d7f5dd; 37 | } 38 | 39 | .notify-ADOPTME { 40 | background: #f5efd7; 41 | } 42 | 43 | .notify-HANDOFF { 44 | background: #d7e1f5; 45 | } 46 | 47 | .notify-DEPRECATED, 48 | .notify-MODULE_DEPRECATED { 49 | background: #f8d7da; 50 | } 51 | -------------------------------------------------------------------------------- /root/static/less/plusser.less: -------------------------------------------------------------------------------- 1 | .plusser-title { 2 | text-align: center; 3 | } 4 | 5 | .plussers_disp { 6 | margin: 30px 0px; 7 | font-size: 1.1em; 8 | text-align: center; 9 | 10 | div.plusser { 11 | display: inline-block; 12 | margin: 0 30px 50px 30px; 13 | width: 100px; 14 | } 15 | 16 | img { 17 | margin: 0 auto; 18 | border-radius: 9px; 19 | display: block; 20 | height: 75px; 21 | width: 75px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /root/static/less/print.less: -------------------------------------------------------------------------------- 1 | @media print { 2 | .pod { 3 | margin: 0px; 4 | border: 0px solid #000; 5 | padding: 0px; 6 | } 7 | .home, 8 | .header, 9 | .search-bar, 10 | .box-right, 11 | .footer, 12 | a.favorite { 13 | display: none; 14 | } 15 | .page-content { 16 | .dependencies, 17 | .search-form, 18 | .dropdown, 19 | .logged_in, 20 | .footer + div, 21 | .footer + div + div, 22 | .toggle-index, 23 | .toggle-index-right { 24 | display: none !important; 25 | } 26 | a[href]:after { 27 | content: none !important; 28 | } 29 | #index-container { 30 | width: 100%; 31 | } 32 | .index-border { 33 | width: 100%; 34 | } 35 | .pod { 36 | margin-top: 1.5em; 37 | } 38 | .index-header { 39 | color: transparent !important; 40 | display: flex; 41 | align-items: center; 42 | } 43 | .index-header b { 44 | display: block !important; 45 | } 46 | .index-header b { 47 | color: black; 48 | margin: auto; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /root/static/less/search.less: -------------------------------------------------------------------------------- 1 | .search-results { 2 | ul.inner-results { 3 | padding: 5px 0 0 10px; 4 | margin: 0; 5 | list-style: none; 6 | } 7 | 8 | .description { 9 | color: #545454; 10 | max-height: 3em; 11 | overflow: hidden; 12 | } 13 | 14 | .module-result { 15 | margin-bottom: 3ch; 16 | 17 | h3 { 18 | font-weight: bold; 19 | font-size: 120%; 20 | line-height: inherit; 21 | margin: 0; 22 | } 23 | } 24 | } 25 | 26 | .search-group { 27 | position: relative; 28 | } 29 | 30 | .search-group .fa-search { 31 | color: @input-color; 32 | font-size: 20px; 33 | left: 18px; 34 | position: absolute; 35 | top: 50%; 36 | transform: translateY(-50%); 37 | } 38 | 39 | .navbar-nav .search-form { 40 | .fa-search { 41 | font-size: 15px; 42 | } 43 | 44 | input[type="text"] { 45 | border-radius: 50px; 46 | padding-left: 40px; 47 | } 48 | } 49 | 50 | .searchbar-open { 51 | display: inline-block; 52 | left: 50%; 53 | position: absolute; 54 | top: 50%; 55 | transform: translate(-50%, -50%); 56 | width: 95%; 57 | z-index: 100; 58 | 59 | input[type="text"] { 60 | height: 40px; 61 | padding-left: 45px !important; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /root/static/less/silk.less: -------------------------------------------------------------------------------- 1 | .file-table-entry { 2 | padding-left: 20px; 3 | background-repeat: no-repeat !important; 4 | background: url(/static/icons/page_white.png); 5 | 6 | &[data-directory] { 7 | background: url(/static/icons/folder.png); 8 | } 9 | 10 | &[data-mime-type="text/x-script.perl"], 11 | &[data-mime-type="text/x-script.perl-module"] { 12 | background: url(/static/icons/page_white_code.png); 13 | } 14 | &[data-mime-type="text/x-c"] { 15 | background: url(/static/icons/page_white_c.png); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /root/static/less/table.less: -------------------------------------------------------------------------------- 1 | .table { 2 | table-layout: fixed; 3 | 4 | thead > tr > th { 5 | vertical-align: none; 6 | border: none; 7 | font-weight: bold; 8 | } 9 | 10 | tbody > tr > td { 11 | border-top: none; 12 | } 13 | 14 | td { 15 | border-top-width: 0px; 16 | } 17 | 18 | td.abstract { 19 | text-overflow: ellipsis; 20 | overflow: hidden; 21 | white-space: nowrap; 22 | } 23 | 24 | th.date, 25 | th.number, 26 | td.date, 27 | td.number { 28 | text-align: right; 29 | white-space: nowrap; 30 | } 31 | 32 | th.date, 33 | th.number { 34 | width: 8em; 35 | direction: rtl; // overflow left, not right 36 | } 37 | 38 | td.name, 39 | th.name { 40 | width: 21em; 41 | font-weight: bold; 42 | } 43 | 44 | th.position { 45 | width: 10px; 46 | } 47 | 48 | th.river-gauge, 49 | td.river-gauge { 50 | width: 36px; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /root/static/less/tablesorter.less: -------------------------------------------------------------------------------- 1 | /* tables */ 2 | 3 | table.tablesorter { 4 | thead tr { 5 | th.tablesorter-header { 6 | cursor: pointer; 7 | height: auto; 8 | font-weight: bold; 9 | 10 | &:before { 11 | .fa; 12 | line-height: inherit; 13 | float: right; 14 | display: inline; 15 | padding-left: 5px; 16 | content: @fa-var-sort; 17 | } 18 | &.tablesorter-headerDesc:before { 19 | content: @fa-var-caret-down; 20 | } 21 | &.tablesorter-headerAsc:before { 22 | content: @fa-var-caret-up; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /root/static/less/toplists.less: -------------------------------------------------------------------------------- 1 | .toplists { 2 | .entry { 3 | position: relative; 4 | float: left; 5 | height: 80px; 6 | padding-left: 80px; 7 | margin-bottom: 20px; 8 | .pauseid, 9 | .name, 10 | .count { 11 | display: block; 12 | } 13 | .count { 14 | position: absolute; 15 | bottom: 0; 16 | } 17 | .gravatar { 18 | position: absolute; 19 | left: 0; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /root/static/opensearch.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" ?> 2 | <!-- See http://www.opensearch.org/Specifications/OpenSearch/1.1 --> 3 | <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> 4 | <ShortName>MetaCPAN</ShortName> 5 | <Description>Search CPAN with MetaCPAN</Description> 6 | <InputEncoding>UTF-8</InputEncoding> 7 | <OutputEncoding>UTF-8</OutputEncoding> 8 | <AdultContent>false</AdultContent> 9 | <Language>en-us</Language> 10 | <SyndicationRight>open</SyndicationRight> 11 | <Image height="16" width="16" type="image/x-icon">https://metacpan.org/static/icons/favicon-16.ico</Image> 12 | <Url type="text/html" template="https://metacpan.org/search?q={searchTerms}" /> 13 | <Tags>CPAN MetaCPAN Perl</Tags> 14 | </OpenSearchDescription> 15 | -------------------------------------------------------------------------------- /static-app.psgi: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Plack::Builder qw( builder enable mount ); 4 | use Plack::App::Proxy (); 5 | use File::Basename (); 6 | use Config::ZOMG (); 7 | 8 | my $root_dir; 9 | BEGIN { $root_dir = File::Basename::dirname(__FILE__); } 10 | use lib "$root_dir/lib"; 11 | 12 | my $port = $ENV{METACPAN_WEB_PORT} || 5001; 13 | 14 | my $config = Config::ZOMG->open( 15 | name => 'MetaCPAN::Web', 16 | path => $root_dir, 17 | ); 18 | 19 | builder { 20 | enable '+MetaCPAN::Middleware::Static' => ( 21 | root => $root_dir, 22 | config => $config, 23 | dev_mode => 1, 24 | ); 25 | enable sub { 26 | my ($app) = @_; 27 | sub { 28 | my ($env) = @_; 29 | $env->{HTTP_X_FORWARDED_HTTPS} = 'ON' 30 | if $env->{'psgi.url_scheme'} eq 'https'; 31 | $app->($env); 32 | }; 33 | }; 34 | mount '/' => Plack::App::Proxy->new( 35 | remote => "http://localhost:$port", 36 | preserve_host_header => 1, 37 | backend => 'LWP', 38 | options => { 39 | env_proxy => 0, 40 | }, 41 | )->to_app; 42 | }; 43 | -------------------------------------------------------------------------------- /t/assets.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | { 11 | ok( my $res = $cb->( GET '/' ), 'GET /' ); 12 | is( $res->code, 200, 'code 200' ); 13 | 14 | my $xpc = tx($res)->xpc; 15 | 16 | my @assets = grep m{^/}, map $_->value, 17 | $xpc->findnodes(q[//script/@src]), 18 | $xpc->findnodes(q[//link[@rel="stylesheet"]/@href]); 19 | 20 | ok( ( grep /\.js$/, @assets ), 'assets include a js file' ); 21 | ok( ( grep /\.css$/, @assets ), 'assets include a css file' ); 22 | 23 | for my $asset (@assets) { 24 | ok( my $res = $cb->( GET $asset ), "GET $asset" ); 25 | is( $res->code, 200, 'code 200' ); 26 | } 27 | } 28 | }; 29 | 30 | done_testing; 31 | -------------------------------------------------------------------------------- /t/controller/about.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_cache_headers test_psgi ); 6 | use Test::More; 7 | 8 | my @tests = ( 9 | { 10 | url => '/about' 11 | }, 12 | { 13 | url => '/about/contact', 14 | }, 15 | ); 16 | 17 | test_psgi app, sub { 18 | my $cb = shift; 19 | 20 | foreach my $test (@tests) { 21 | ok( my $res = $cb->( GET $test->{url} ), 'GET ' . $test->{url} ); 22 | is( $res->code, 200, 'code 200' ); 23 | test_cache_headers( 24 | $res, 25 | { 26 | cache_control => 'max-age=86400', 27 | surrogate_key => 28 | 'ABOUT STATIC content_type=text/html content_type=text', 29 | surrogate_control => 30 | 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', 31 | } 32 | ); 33 | } 34 | 35 | }; 36 | 37 | done_testing; 38 | -------------------------------------------------------------------------------- /t/controller/activity.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | my @tests 9 | = qw(/activity/releases.svg /author/PERLER/activity.svg /dist/Moose/activity.svg); 10 | 11 | test_psgi app, sub { 12 | my $cb = shift; 13 | foreach my $test (@tests) { 14 | ok( my $res = $cb->( GET $test ), $test ); 15 | is( $res->code, 200, 'code 200' ); 16 | is( 17 | $res->header('content-type'), 18 | 'image/svg+xml; charset=UTF-8', 19 | 'Content-type is image/svg+xml; charset=UTF-8' 20 | ); 21 | ok( my $tx = eval { tx($res) }, 'valid xml' ); 22 | } 23 | }; 24 | 25 | done_testing; 26 | -------------------------------------------------------------------------------- /t/controller/diff.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | 11 | my $mod_diff 12 | = '/release/ETHER/Moose-2.1605/diff/ETHER/Moose-2.1604/lib/Moose.pm'; 13 | my $rel_diff = '/release/ETHER/Moose-2.1605/diff/ETHER/Moose-2.1604'; 14 | 15 | ok( my $res = $cb->( GET $mod_diff ), 'GET module diff' ); 16 | is( $res->code, 200, 'code 200' ); 17 | my $tx = tx($res); 18 | 19 | is( 20 | $tx->find_value( 21 | '//table[contains-token(@class, "diff-list")]//td[1]/a'), 22 | 'lib/Moose.pm', 23 | 'Module diff file list' 24 | ); 25 | 26 | ok( $res = $cb->( GET $rel_diff ), 'GET release diff' ); 27 | is( $res->code, 200, 'code 200' ); 28 | $tx = tx($res); 29 | 30 | is( 31 | $tx->find_value( 32 | '//table[contains-token(@class, "diff-list")]//tr[position() <= 5]/td[1]/a' 33 | ), 34 | 'ChangesLICENSEMANIFESTMETA.jsonMETA.yml', 35 | 'Release diff file list' 36 | ); 37 | }; 38 | 39 | done_testing; 40 | -------------------------------------------------------------------------------- /t/controller/favorite/leaderboard.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | { 11 | ok( 12 | my $res = $cb->( GET '/favorite/leaderboard' ), 13 | 'GET leaderboard', 14 | ); 15 | is( $res->code, 200, 'code 200' ); 16 | my $tx = tx($res); 17 | $tx->ok( 18 | '//table[contains-token(@class, "table-releases")]//td[contains-token(@class, "name")]//a', 19 | sub { 20 | my $anchor = shift; 21 | $anchor->is( 22 | './@href', 23 | '/dist/' . $anchor->node->textContent, 24 | 'href points to release' 25 | ); 26 | }, 27 | 'links point to release' 28 | ); 29 | } 30 | }; 31 | 32 | done_testing; 33 | -------------------------------------------------------------------------------- /t/controller/healthcheck.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Cpanel::JSON::XS qw( decode_json ); 6 | use MetaCPAN::Web::Test qw( app GET test_psgi ); 7 | use Test::More; 8 | 9 | test_psgi app, sub { 10 | my $cb = shift; 11 | ok( my $res = $cb->( GET '/healthcheck' ), 'GET /healthcheck' ); 12 | is( $res->code, 200, 'code 200' ); 13 | is $res->header('Content-Type'), 'application/json', 14 | 'correct Content-Type'; 15 | my $data = decode_json( $res->content ); 16 | is $data->{status}, 'healthy', 'has correct status'; 17 | }; 18 | 19 | done_testing; 20 | -------------------------------------------------------------------------------- /t/controller/home.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_cache_headers test_psgi ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | ok( my $res = $cb->( GET '/' ), 'GET /' ); 11 | is( $res->code, 200, 'code 200' ); 12 | test_cache_headers( 13 | $res, 14 | { 15 | cache_control => 'max-age=3600', 16 | surrogate_key => 17 | 'HOMEPAGE content_type=text/html content_type=text', 18 | surrogate_control => 19 | 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', 20 | } 21 | ); 22 | 23 | }; 24 | 25 | done_testing; 26 | -------------------------------------------------------------------------------- /t/controller/lab/dashboard.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | 11 | ok( my $res = $cb->( GET '/lab/dashboard' ), 'GET /lab/dashboard' ); 12 | is( $res->code, 200, 'code 200' ); 13 | }; 14 | 15 | done_testing(); 16 | -------------------------------------------------------------------------------- /t/controller/raw.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | ok( my $res = $cb->( GET '/pod/Moose' ), 'GET /pod/Moose' ); 11 | is( $res->code, 200, 'code 200' ); 12 | my $tx = tx($res); 13 | ok( my $source = $tx->find_value('//a[text()="Source"]/@href'), 14 | 'contains link to Source' ); 15 | $source =~ s/^\/source/\/raw/; 16 | ok( $res = $cb->( GET $source ), "GET $source" ); 17 | ok( $res->code(200), 'code 200' ); 18 | is( 19 | $res->header('Content-Type'), 20 | 'text/html; charset=utf-8', 21 | 'Content-type text/html; charset=utf-8' 22 | ); 23 | 24 | $tx = tx($res); 25 | ok( my $dl = $tx->find_value('//a[text()="Download"]/@href'), 26 | 'contains link to Download' ); 27 | ok( $res = $cb->( GET $dl ), "GET $dl" ); 28 | is( 29 | $res->header('Content-Disposition'), 30 | 'attachment; filename=Moose.pm', 31 | 'content-disposition attachment with filename set' 32 | ); 33 | is( 34 | $res->header('Content-Type'), 35 | 'text/plain; charset=UTF-8', 36 | 'content-type text/plain' 37 | ); 38 | 39 | }; 40 | 41 | done_testing; 42 | -------------------------------------------------------------------------------- /t/controller/recent.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | ok( my $res = $cb->( GET '/recent' ), 'GET /recent' ); 11 | is( $res->code, 200, 'code 200' ); 12 | 13 | my $tx = tx($res); 14 | ok( 15 | my $release = $tx->find_value( 16 | '//table[contains-token(@class, "table-releases")][1]/tbody/tr[1]/td[contains-token(@class, "name")]//a[1]/@href' 17 | ), 18 | 'contains a release' 19 | ); 20 | ok( $res = $cb->( GET $release ), "GET $release" ); 21 | is( $res->code, 200, 'code 200' ); 22 | 23 | }; 24 | 25 | done_testing; 26 | -------------------------------------------------------------------------------- /t/controller/robots.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_cache_headers test_psgi ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | ok( my $res = $cb->( GET '/robots.txt' ), 'GET /robots.txt' ); 11 | is( $res->code, 200, 'code 200' ); 12 | 13 | SKIP: { 14 | skip 'Root controller is not serving /robots.txt!', 3; 15 | test_cache_headers( 16 | $res, 17 | { 18 | cache_control => 'max-age=3600', 19 | surrogate_key => 'ROBOTS', 20 | surrogate_control => 'max-age=86400', 21 | } 22 | ); 23 | } 24 | }; 25 | 26 | done_testing; 27 | -------------------------------------------------------------------------------- /t/controller/search/suggestion.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi tx ); 6 | use Test::More; 7 | 8 | my %tests = ( 9 | 'DBIx:Class:::ResultSet' => 'DBIx::Class::ResultSet', 10 | 'DBIx::Class:ResultSet' => 'DBIx::Class::ResultSet', 11 | 'DBIx:Class' => 'DBIx::Class', 12 | 'DBIx: Class' => 'DBIx::Class', 13 | 'DBIx ::Class: ResultSet' => 'DBIx::Class::ResultSet', 14 | ); 15 | 16 | test_psgi app, sub { 17 | my $cb = shift; 18 | while ( my ( $k, $v ) = each %tests ) { 19 | ok( my $res = $cb->( GET "/search?q=$k" ), 'search for ' . $k ); 20 | my $tx = tx($res); 21 | my $module 22 | = $tx->find_value( 23 | '//div[contains-token(@class, "no-results")]//div[contains-token(@class,"alert")][contains-token(@class, "alert-danger")]//a[1]' 24 | ); 25 | is( $module, $v, 'get no result page with suggestion' ); 26 | } 27 | }; 28 | 29 | done_testing; 30 | -------------------------------------------------------------------------------- /t/fastly_headers.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web::Test qw( app GET test_psgi ); 6 | use Test::More; 7 | 8 | test_psgi app, sub { 9 | my $cb = shift; 10 | { 11 | ok( my $res = $cb->( GET '/static/images/metacpan-logo.svg' ), 12 | 'GET /static/images/logo.png...' ); 13 | is( $res->code, 200, 'code 200' ); 14 | is( $res->header('Set-Cookie'), undef, 'No cookie' ); 15 | is( $res->header('Surrogate-Control'), 16 | 'max-age=31536000', 'Image Surrogate-Control as a year' ); 17 | } 18 | }; 19 | 20 | done_testing; 21 | -------------------------------------------------------------------------------- /t/html.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More; 6 | 7 | use File::Find (); 8 | use Path::Tiny qw( path ); 9 | 10 | # files that have inline <script> tags 11 | my %skip = map { $_ => 1 } (); 12 | 13 | File::Find::find( 14 | { 15 | no_chdir => 1, 16 | wanted => sub { 17 | my $file = $File::Find::name; 18 | if ( $file eq 'root/static' ) { 19 | $File::Find::prune = 1; 20 | return; 21 | } 22 | elsif ( -d $file ) { 23 | return; 24 | } 25 | elsif ( $file !~ /\.tx\z/ ) { 26 | return; 27 | } 28 | elsif ( $skip{$file} ) { 29 | return; 30 | } 31 | 32 | my $html = path($file)->slurp_utf8; 33 | 34 | ok $html !~ /<style>/, "no inline style in $file"; 35 | if ( not $skip{$file} ) { 36 | my @script_tags = $html =~ /<script\b([^>]*)>/; 37 | my @js = grep { 38 | /\btype="([^"]*)"/ 39 | ? ( $1 =~ /(?:j|java|emca)script/ ? 1 : () ) 40 | : 1 41 | } @script_tags; 42 | ok !@js, "no inline script in $file"; 43 | } 44 | }, 45 | }, 46 | 'root' 47 | ); 48 | 49 | done_testing; 50 | -------------------------------------------------------------------------------- /t/lib/MetaCPAN/Web/Controller/Test.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Controller::Test; 2 | 3 | use Moose; 4 | use Cpanel::JSON::XS (); 5 | 6 | BEGIN { extends 'MetaCPAN::Web::Controller' } 7 | 8 | sub _json_body { 9 | my ( $self, $c ) = @_; 10 | Cpanel::JSON::XS->new->utf8->decode( 11 | do { local $/; $c->req->body->getline } 12 | ); 13 | } 14 | 15 | sub json_echo : Local { 16 | my ( $self, $c ) = @_; 17 | 18 | $c->stash->{json}{echo} = $self->_json_body($c); 19 | 20 | $c->detach( $c->view('JSON') ); 21 | } 22 | 23 | __PACKAGE__->meta->make_immutable; 24 | 25 | 1; 26 | -------------------------------------------------------------------------------- /t/lib/MetaCPAN/Web/Test/HTML5/Element/SVG.pm: -------------------------------------------------------------------------------- 1 | package MetaCPAN::Web::Test::HTML5::Element::SVG; 2 | use strict; 3 | use warnings; 4 | 5 | use parent 'HTML::Element'; 6 | 7 | sub starttag_XML { 8 | my $self = shift; 9 | my $is_svg = $self->{_tag} eq 'svg'; 10 | local $self->{xmlns} = 'http://www.w3.org/2000/svg' if $is_svg; 11 | local $self->{'xmlns:xlink'} = 'http://www.w3.org/1999/xlink' 12 | if $is_svg; 13 | 14 | return $self->SUPER::starttag_XML(@_); 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /t/markdown.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More; 6 | 7 | use MetaCPAN::Web::RenderUtil qw( render_markdown ); 8 | 9 | my $html = render_markdown(<<'EOM'); 10 | # Heading 11 | 12 | Some body text 13 | 14 | ## Heading 15 | 16 | More stuff 17 | 18 | ## Heading 19 | 20 | more stuff 21 | 22 | ## Heading **with** _markup_ 23 | 24 | Content 25 | 26 | EOM 27 | 28 | like $html, qr{<h1 id="heading">Heading</h1>}, 'first heading'; 29 | like $html, qr{<h2 id="heading-2">Heading</h2>}, 'second heading'; 30 | like $html, qr{<h2 id="heading-3">Heading</h2>}, 'third heading'; 31 | 32 | like $html, qr{<h2 id="heading-with-markup">Heading <}, 'heading with markup'; 33 | 34 | $html = render_markdown(<<'EOM'); 35 | # Heading 36 | 37 | Some body text 38 | 39 | <div>Raw HTML</div> 40 | 41 | EOM 42 | 43 | like $html, qr{Raw HTML}, 'raw html allowed'; 44 | 45 | $html = render_markdown( <<'EOM', unsafe => 0 ); 46 | # Heading 47 | 48 | Some body text 49 | 50 | <div>Raw HTML</div> 51 | 52 | EOM 53 | 54 | unlike $html, qr{Raw HTML}, 'raw html blocked'; 55 | 56 | eval { render_markdown( '# Heading', chorg => 1 ) }; 57 | like "$@", qr/^Unsupported options: chorg /, 'invalid options throw errors'; 58 | 59 | done_testing(); 60 | -------------------------------------------------------------------------------- /t/model/api/lab.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use MetaCPAN::Web (); 6 | use Test::More; 7 | 8 | my $model = MetaCPAN::Web->model('API::Lab'); 9 | 10 | my $report = $model->fetch_latest_distros( 2, 'OALDERS' )->get; 11 | is( keys %{ $report->{distros} }, 2, 'gets two distros' ); 12 | 13 | my $dependencies = $model->dependencies('HTML::Restrict'); 14 | isa_ok( $dependencies, 'Future', 'dependencies' ); 15 | my @foo = $dependencies->get; 16 | cmp_ok( @{ $dependencies->get }, '>', 10, 'finds at least 11 deps' ); 17 | 18 | done_testing; 19 | -------------------------------------------------------------------------------- /t/model/changes-tests/moose.changes: -------------------------------------------------------------------------------- 1 | Also see Moose::Manual::Delta for more details of, and workarounds 2 | for, noteworthy changes. 3 | 4 | 2.1005 Tue, Aug 06, 2013 5 | 6 | [ENHANCEMENTS] 7 | 8 | * add_method now accepts blessed subs (Graham Knop, PR#28) 9 | 10 | [BUG FIXES] 11 | 12 | * If a role consumed another role, we resolve method conflicts just like a 13 | class consuming a role, but when metaclass compat tried to fix up 14 | metaclass roles, we were putting all methods into one composite role and 15 | allowing methods in the metaclass roles to conflict. Now we resolve them 16 | as we should. (Jesse Luehrs, PR#27) 17 | 18 | * Some edge cases in tests with base.pm and non-existent module files are 19 | handled more strictly (see also perl RT#118561) (Graham Knop, PR#25) 20 | 21 | 2.1004 Fri, Jul 26, 2013 22 | 23 | [BUG FIXES] 24 | 25 | * 2.1003 was released with some bad metadata, which caused the prereq test 26 | to fail. 27 | -------------------------------------------------------------------------------- /t/model/changes.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More; 6 | 7 | use aliased 'MetaCPAN::Web::Model::API::Changes'; 8 | 9 | ok 1; 10 | 11 | done_testing; 12 | -------------------------------------------------------------------------------- /t/moose.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Test::More; 6 | use File::Find (); # core 7 | use Module::Runtime (); 8 | 9 | sub uses_moose_ok { 10 | my ($mod) = @_; 11 | SKIP: { 12 | my $meta = $mod->can('meta') && $mod->meta; 13 | my $metaclass = $meta && ref $meta; 14 | 15 | if ( $metaclass && $metaclass->can('is_immutable') ) { 16 | ::ok( $meta->is_immutable, "$mod is immutable" ); 17 | } 18 | elsif ( $metaclass && $metaclass->isa('Moose::Meta::Role') ) { 19 | ::pass("$mod is a role"); 20 | } 21 | else { 22 | ::skip( "$mod is not a Moose class or role", 1 ); 23 | } 24 | } 25 | } 26 | 27 | sub package_from_path { 28 | local $_ = shift; 29 | s{^(t/)?lib/}{}; 30 | s{\.pm$}{}; 31 | s{[\\/]}{::}g; 32 | return $_; 33 | } 34 | 35 | my @modules; 36 | File::Find::find( 37 | { 38 | no_chdir => 1, 39 | wanted => sub { 40 | return unless /\.pm$/; 41 | push @modules, package_from_path($_); 42 | }, 43 | }, 44 | qw( lib t/lib ), 45 | ); 46 | 47 | plan tests => scalar(@modules); 48 | 49 | foreach my $mod (@modules) { 50 | Module::Runtime::require_module($mod); 51 | uses_moose_ok($mod); 52 | } 53 | -------------------------------------------------------------------------------- /t/testrules.yml: -------------------------------------------------------------------------------- 1 | --- 2 | seq: 3 | - par: 4 | - t/**.t 5 | -------------------------------------------------------------------------------- /t/view/json.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use lib 't/lib'; 4 | 5 | use Cpanel::JSON::XS qw( decode_json ); 6 | use HTTP::Request::Common qw( POST ); 7 | use MetaCPAN::Web::Test qw( app test_psgi ); 8 | use Test::More; 9 | 10 | sub post_json { 11 | POST( 12 | shift(), 13 | Content => shift(), 14 | Content_type => 'application/json', 15 | @_ 16 | ); 17 | } 18 | 19 | my $cb; 20 | 21 | sub echo_json_ok { 22 | my ( $json, $desc ) = @_; 23 | 24 | subtest $desc => sub { 25 | my $exp = decode_json($json); 26 | 27 | ok( my $res = $cb->( post_json '/test/json_echo', $json ), 28 | 'http post' ); 29 | is( $res->code, 200, '200 OK' ); 30 | 31 | my $res_json = $res->content; 32 | ok( my $obj = eval { decode_json($res_json); }, 'decode json' ); 33 | 34 | note "received: $res_json"; 35 | 36 | is_deeply $obj, { echo => $exp }, 'json passed through unchanged'; 37 | }; 38 | } 39 | 40 | test_psgi app, sub { 41 | $cb = shift; # global 42 | }; 43 | 44 | { 45 | 46 | echo_json_ok( q!{"test": 1}!, 'minimal json' ); 47 | 48 | echo_json_ok( q!{"test": [1, 2, {"hash": {}}] }!, 'arrays and hashes' ); 49 | 50 | echo_json_ok( q!{"test": true}!, 'booleans' ); 51 | } 52 | 53 | done_testing; 54 | --------------------------------------------------------------------------------