free-programming-books | Freely available programming books
\ No newline at end of file
+free-programming-books | Freely available programming books
\ No newline at end of file
diff --git a/static/js/main.9034130b.chunk.js b/static/js/main.9034130b.chunk.js
new file mode 100644
index 0000000..2a6517c
--- /dev/null
+++ b/static/js/main.9034130b.chunk.js
@@ -0,0 +1,2 @@
+(this.webpackJsonpfpb_search_page=this.webpackJsonpfpb_search_page||[]).push([[0],{28:function(e,t,r){},49:function(e,t,r){"use strict";r.r(t);var n=r(1),o=r.n(n),c=r(20),a=r.n(c),s=(r(28),r(21)),i=r(5),l=r(4),h=r(2),b=r(11),j=r.n(b),u=r(22),d=r.n(u),m=r(23),g=r(0);var f=function(e){var t,r=e.changeParameter,o=e.data,c=Object(n.useState)([]),a=Object(h.a)(c,2),s=a[0],i=a[1],l=Object(n.useState)(""),b=Object(h.a)(l,2),j=b[0],u=b[1],d=Object(n.useState)(!1),m=Object(h.a)(d,2),f=m[0],O=m[1],p=function(e){r("lang.code",e.target.value),u(e.target.value)};Object(n.useEffect)((function(){if(o){var e=[{code:"en",name:"English"}];o.children[0].children.forEach((function(t){"string"===typeof t.language.name&&t.language.name.length>0&&"en"!==t.language.code&&e.push(t.language)})),e.sort((function(e,t){return e.name>t.name})),i(e)}}),[o]),t=s&&s.map((function(e){return function(e){return Object(g.jsx)("div",{children:Object(g.jsxs)("label",{children:[Object(g.jsx)("input",{type:"radio",className:"lang",value:e.code,onChange:p,checked:e.code==j},e.code),e.name]})})}(e)}));var x=Object(g.jsxs)("form",{className:"filters",children:[Object(g.jsxs)("label",{children:[Object(g.jsx)("input",{type:"radio",className:"sect-select",value:"",onChange:p,checked:""==j},"all"),"All Languages"]}),t]});return Object(g.jsxs)("div",{className:"langFilters",children:[Object(g.jsxs)("div",{className:"filterHeader",children:[Object(g.jsx)("h3",{children:"Filter by Language"}),Object(g.jsx)("button",{onClick:function(){return O(!f)},children:f?"-":"+"})]}),f?x:""]})};var O=function(e){return Object(g.jsx)("form",{onSubmit:function(e){e.preventDefault()},name:"searchBar",className:"searchbar",children:Object(g.jsx)("input",{autoComplete:"off",type:"text",name:"searchTerm",placeholder:"Search Book or Author",className:"searchterm",onChange:function(t){e.changeParameter("searchTerm",t.target.value)}})})};var p=function(e){var t=e.data;return Object(g.jsx)("li",{className:"result",children:Object(g.jsxs)("a",{href:t.url,target:"_blank",rel:"noreferrer",children:["(",t.lang.code,") ",t.title,t.author?" by ".concat(t.author):""]})})};var x=function(){return Object(g.jsxs)("section",{children:[Object(g.jsx)("br",{}),Object(g.jsx)("h1",{id:"list-of-free-learning-resources-in-many-languages",children:"List of Free Learning Resources In Many Languages"}),Object(g.jsx)("div",{align:"center"}),Object(g.jsx)("h2",{id:"intro",children:"Intro"}),Object(g.jsxs)("p",{children:["This list was originally a clone of"," ",Object(g.jsx)("a",{href:"https://web.archive.org/web/20140606191453/http://stackoverflow.com/questions/194812/list-of-freely-available-programming-books/392926",children:"StackOverflow - List of Freely Available Programming Books"})," ","with contributions from Karan Bhangui and George Stocker."]}),Object(g.jsxs)("p",{children:["The list was moved to GitHub by Victor Felder for collaborative updating and maintenance. It has grown to become one of ",Object(g.jsx)("a",{href:"https://octoverse.github.com/",children:"GitHub\u2019s most popular repositories"}),", with 221,000+ stars, 6,900+ commits, 1,900+ contributors, and 47,100+ forks."]}),Object(g.jsxs)("p",{children:["The ",Object(g.jsx)("a",{href:"https://ebookfoundation.org",children:"Free Ebook Foundation"})," now administers the repo, a not-for-profit organization devoted to promoting the creation, distribution, archiving, and sustainability of free ebooks."," ",Object(g.jsx)("a",{href:"https://ebookfoundation.org/contributions.html",children:"Donations"})," to the Free Ebook Foundation are tax-deductible in the US."]}),Object(g.jsx)("h2",{id:"how-to-contribute",children:"How To Contribute"}),Object(g.jsxs)("p",{children:["Please read ",Object(g.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html",children:"CONTRIBUTING"}),". If you\u2019re new to GitHub,"," ",Object(g.jsx)("a",{href:"/free-programming-books/docs/HOWTO.html",children:"welcome"}),"! Remember to abide by our"," ",Object(g.jsx)("a",{href:"/free-programming-books/docs/CODE_OF_CONDUCT.html",children:"Code of Conduct"})," too. (",Object(g.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"translations"})," also available)"]}),Object(g.jsx)("h2",{id:"how-to-share",children:"How to Share"}),Object(g.jsxs)("ul",{children:[Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"http://twitter.com/intent/tweet?text=https://github.com/EbookFoundation/free-programming-books%0AFree%20Programming%20Books",children:"Share on Twitter"})}),Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"https://www.facebook.com/share.php?u=https%3A%2F%2Fgithub.com%2FEbookFoundation%2Ffree-programming-books&p%5Bimages%5D%5B0%5D=&p%5Btitle%5D=Free%20Programming%20Books&p%5Bsummary%5D=",children:"Share on Facebook"})}),Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"http://www.linkedin.com/shareArticle?mini=true&url=https://github.com/EbookFoundation/free-programming-books&title=Free%20Programming%20Books&summary=&source=",children:"Share on LinkedIn"})}),Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"https://t.me/share/url?url=https://github.com/EbookFoundation/free-programming-books",children:"Share on Telegram"})})]}),Object(g.jsx)("h2",{id:"translations",children:"Translations"}),Object(g.jsx)("p",{children:"Volunteers have translated many of our Contributing, How-to, and Code of Conduct documents into languages covered by our lists."}),Object(g.jsxs)("ul",{children:[Object(g.jsxs)("li",{children:["English",Object(g.jsxs)("ul",{children:[Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"/free-programming-books/docs/CODE_OF_CONDUCT.html",children:"Code of Conduct"})}),Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html",children:"Contributing"})}),Object(g.jsx)("li",{children:Object(g.jsx)("a",{href:"/free-programming-books/docs/HOWTO.html",children:"How-to"})})]})]}),Object(g.jsxs)("li",{children:["\u2026"," ",Object(g.jsx)("em",{children:Object(g.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"More languages"})})," ","\u2026"]})]}),Object(g.jsxs)("p",{children:["You might notice that there are"," ",Object(g.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"some missing translations here"})," - perhaps you would like to help out by"," ",Object(g.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html#help-out-by-contributing-a-translation",children:"contributing a translation"}),"?"]}),Object(g.jsx)("h2",{id:"license",children:"License"}),Object(g.jsxs)("p",{children:["Each file included in this repository is licensed under the"," ",Object(g.jsx)("a",{href:"/free-programming-books/LICENSE",children:"CC BY License"}),"."]})]})},k=(r.p,r.p,null);function v(e){var t=[],r=[];return e.children[0].children.forEach((function(e){e.sections.forEach((function(n){r.includes(n.section)||r.push(n.section),n.entries.forEach((function(r){t.push({author:r.author,title:r.title,url:r.url,lang:e.language,section:n.section})})),n.subsections.forEach((function(r){r.entries.forEach((function(o){t.push({author:o.author,title:o.title,url:o.url,lang:e.language,section:n.section,subsection:r.section})}))}))}))})),{arr:t,sections:r}}var w=function(){var e=Object(n.useState)(void 0),t=Object(h.a)(e,2),r=t[0],o=t[1],c=Object(n.useState)([]),a=Object(h.a)(c,2),b=a[0],u=a[1],w=Object(n.useState)([]),F=Object(h.a)(w,2),E=(F[0],F[1]),C=Object(n.useState)(!0),y=Object(h.a)(C,2),S=y[0],T=y[1],N=Object(n.useState)({searchTerm:""}),B=Object(h.a)(N,2),I=B[0],L=B[1],H=Object(n.useState)([]),_=Object(h.a)(H,2),P=_[0],D=_[1],A=Object(n.useState)([]),G=Object(h.a)(A,2),R=(G[0],G[1],Object(n.useState)(!0)),U=Object(h.a)(R,2),M=(U[0],U[1],Object(n.useState)("")),V=Object(h.a)(M,2),J=V[0],W=(V[1],null),Y=function(e,t){L(Object(l.a)(Object(l.a)({},I),{},Object(i.a)({},e,t)))};return Object(n.useEffect)((function(){function e(){return(e=Object(s.a)(j.a.mark((function e(){var t,r,n,c,a,s,i;return j.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,T(!0),e.next=4,d.a.get("https://raw.githubusercontent.com/FreeEbookFoundationBot/free-programming-books-json/main/fpb.json");case 4:t=e.sent,o(t.data),r=v(t.data),n=r.arr,c=r.sections,u(n),E(c),e.next=17;break;case 11:e.prev=11,e.t0=e.catch(0),o(k),a=v(k),s=a.arr,i=a.sections,E(i),u(s);case 17:T(!1);case 18:case"end":return e.stop()}}),e,null,[[0,11]])})))).apply(this,arguments)}!function(){e.apply(this,arguments)}()}),[]),Object(n.useEffect)((function(){if(b){for(var e=new m.a(b,{useExtendedSearch:!0,findAllMatches:!0,shouldSort:!0,includeScore:!0,threshold:.2,keys:["author","title","lang.code","section"]}),t=[],r=[],n=0,o=Object.entries(I);n {\r\n changeParameter(\"lang.code\", e.target.value);\r\n setSelected(e.target.value);\r\n };\r\n\r\n useEffect(\r\n // run whenever data changes\r\n () => {\r\n if (data) {\r\n let langArray = [{ code: \"en\", name: \"English\" }];\r\n data.children[0].children.forEach((document) => {\r\n if (typeof document.language.name === \"string\" && document.language.name.length > 0) {\r\n //make sure the language is valid and not blank\r\n //console.log(\"LANGUAGE: \" + document.language.name)\r\n if (document.language.code !== \"en\") {\r\n // used to ensure only one English is listed\r\n langArray.push(document.language);\r\n }\r\n }\r\n });\r\n langArray.sort((a, b) => a.name > b.name);\r\n setLanguages(langArray);\r\n }\r\n },\r\n [data]\r\n );\r\n\r\n const createOption = (language) => {\r\n return (\r\n
\r\n The list was moved to GitHub by Victor Felder for collaborative updating and maintenance. It has grown to become\r\n one of GitHub’s most popular repositories, with 221,000+ stars,\r\n 6,900+ commits, 1,900+ contributors, and 47,100+ forks.\r\n
\r\n\r\n
\r\n The Free Ebook Foundation now administers the repo, a not-for-profit\r\n organization devoted to promoting the creation, distribution, archiving, and sustainability of free ebooks.{\" \"}\r\n Donations to the Free Ebook Foundation are\r\n tax-deductible in the US.\r\n
\r\n Each file included in this repository is licensed under the{\" \"}\r\n CC BY License.\r\n
\r\n \r\n );\r\n}\r\n\r\nexport default Default;\r\n","import React, { useState, useEffect } from \"react\";\r\nimport axios from \"axios\";\r\nimport Fuse from \"fuse.js\";\r\n\r\nimport LangFilters from \"./components/LangFilters\";\r\nimport SectDropdown from \"./components/SectDropdown\";\r\nimport SearchBar from \"./components/SearchBar\";\r\nimport SearchResult from \"./components/SearchResult\";\r\nimport LightSwitch from \"./components/LightSwitch\";\r\nimport Default from \"./components/Default\";\r\n\r\nimport SunImg from \"./img/sun.png\";\r\nimport MoonImg from \"./img/moon.png\";\r\n\r\nconst fpb = null;\r\n\r\n// eslint-disable-next-line\r\nfunction makeBook(author, hLang, cLang, title, url) {\r\n //returns a struct with basic book info (author, human language, computer language, book title, url)\r\n return {\r\n author: author,\r\n hLang: hLang, //human language\r\n cLang: cLang, //computer language\r\n title: title,\r\n url: url,\r\n };\r\n}\r\n\r\n// eslint-disable-next-line\r\nfunction forEachBook(func, json) {\r\n //Runs func on each section, entry, and book in json, which is a list of entries\r\n if (typeof func !== \"function\") {\r\n // eslint-disable-next-line\r\n throw \"ERROR in forEachBook: parameter not a fucntion\";\r\n }\r\n\r\n for (const hLang in json) {\r\n //for each human language\r\n if (Array.isArray(hLang.sections)) {\r\n //check if sections is an array\r\n hLang.sections.forEach(\r\n (\r\n cLang //for each computer lanuage\r\n ) => {\r\n if (Array.isArray(cLang.entries)) {\r\n //verify is entries is an array\r\n cLang.entries.forEach(\r\n (\r\n book //for each book\r\n ) => {\r\n if (typeof book === \"object\") {\r\n //verify that book is an object\r\n func(json[hLang], cLang, book); //run the function\r\n }\r\n }\r\n );\r\n }\r\n }\r\n );\r\n }\r\n }\r\n}\r\n\r\n// Sorts search results by their score\r\n// eslint-disable-next-line\r\nfunction sortByScore(results) {\r\n results.sort(function (a, b) {\r\n return a.score - b.score;\r\n });\r\n return results;\r\n}\r\n\r\nfunction jsonToArray(json) {\r\n let arr = [];\r\n let sections = [];\r\n json.children[0].children.forEach((document) => {\r\n document.sections.forEach((section) => {\r\n if (!sections.includes(section.section)) sections.push(section.section);\r\n section.entries.forEach((entry) => {\r\n arr.push({\r\n author: entry.author,\r\n title: entry.title,\r\n url: entry.url,\r\n lang: document.language,\r\n section: section.section,\r\n });\r\n });\r\n section.subsections.forEach((subsection) => {\r\n subsection.entries.forEach((entry) => {\r\n arr.push({\r\n author: entry.author,\r\n title: entry.title,\r\n url: entry.url,\r\n lang: document.language,\r\n section: section.section,\r\n subsection: subsection.section,\r\n });\r\n });\r\n });\r\n });\r\n });\r\n return { arr: arr, sections: sections };\r\n}\r\n\r\nfunction App() {\r\n const [data, setData] = useState(undefined); // keeps the state of the json\r\n const [dataArray, setDataArray] = useState([]); // put everything into one array. uses more memory, but search is faster and less complex\r\n // eslint-disable-next-line\r\n const [index, setIndex] = useState([]); // used for \"table of contents\". currently unused\r\n const [loading, setLoading] = useState(true); // Determines whether to show spinner\r\n const [searchParams, setSearchParams] = useState({ searchTerm: \"\" });\r\n const [searchResults, setSearchResults] = useState([]);\r\n const [sectionResults, setSectionResults] = useState([]);\r\n const [lightMode, setLightMode] = useState(true);\r\n\r\n // eslint-disable-next-line\r\n const [error, setError] = useState(\"\");\r\n\r\n let resultsList = null; // the html string containing the search results\r\n let sectionResultsList = null;\r\n\r\n const changeParameter = (param, value) => {\r\n // Lets a child component set the value of the search term\r\n setSearchParams({ ...searchParams, [param]: value });\r\n };\r\n\r\n // fetches data the first time the page renders\r\n useEffect(() => {\r\n async function fetchData() {\r\n try {\r\n setLoading(true);\r\n let result = await axios.get(\r\n \"https://raw.githubusercontent.com/FreeEbookFoundationBot/free-programming-books-json/main/fpb.json\"\r\n );\r\n setData(result.data);\r\n let { arr, sections } = jsonToArray(result.data);\r\n setDataArray(arr);\r\n setIndex(sections);\r\n } catch (e) {\r\n // setError(\"Couldn't get data. Please try again later\")\r\n setData(fpb);\r\n let { arr, sections } = jsonToArray(fpb);\r\n setIndex(sections);\r\n setDataArray(arr);\r\n }\r\n setLoading(false);\r\n }\r\n fetchData();\r\n }, []);\r\n\r\n // fires when searchTerm changes\r\n // Finds most relevant title or author\r\n // THIS IS THE MAIN SEARCH FUNCTION\r\n useEffect(() => {\r\n if (dataArray) {\r\n const fuseOptions = {\r\n useExtendedSearch: true, // see fuse.js documentation\r\n findAllMatches: true, //continue searching after first match\r\n shouldSort: true, // sort by proximity score\r\n includeScore: true, // includes score in results\r\n threshold: 0.2, // threshold for fuzzy-search,\r\n keys: [\"author\", \"title\", \"lang.code\", \"section\"],\r\n };\r\n\r\n // create new fuse given the array of books and the fuse options from above\r\n let fuse = new Fuse(dataArray, fuseOptions);\r\n let andQuery = []; // for filters that MUST be matched, like language\r\n let orQuery = []; // filters where any may be matched, like author or title\r\n\r\n // for each search param\r\n for (const [key, value] of Object.entries(searchParams)) {\r\n if (value === null || value === \"\") continue;\r\n if (key === \"lang.code\" || key === \"section\") {\r\n // the '^' means it must be an exact match at the beginning\r\n // this is because lang.code and section are strict filters \r\n andQuery.push({ [key]: `^${value}` });\r\n }\r\n if(key === \"searchTerm\") {\r\n orQuery.push({ \"author\": value});\r\n orQuery.push({ \"title\": value});\r\n }\r\n }\r\n // Nest the 'or' query inside the 'and' query\r\n // Necessary step, a quirk with fuse.js\r\n andQuery.push({$or: orQuery})\r\n // Perform the search\r\n let result = fuse.search({\r\n $and: andQuery,\r\n });\r\n // filter to top results\r\n result = result.slice(0, 40);\r\n\r\n // Goes through the list of results\r\n let relevantLists = [];\r\n result.forEach((entry) => {\r\n // Checks if a new entry has already been made with the given programming language and human language.\r\n let obj = relevantLists.find(\r\n (o) => o.item.section === entry.item.section && o.item.lang.code === entry.item.lang.code\r\n );\r\n if (!obj && entry.item.lang.code) {\r\n let langCode = entry.item.lang.code;\r\n let section = entry.item.subsection ? entry.item.subsection : entry.item.section;\r\n // English is split into the subjects and langs file. The parser flags which type of entry it is to use here\r\n if (langCode === \"en\") {\r\n if (entry.item.lang.isSubject) {\r\n langCode = \"subjects\";\r\n } else {\r\n langCode = \"langs\";\r\n }\r\n }\r\n\r\n let id = section;\r\n \r\n // Some ids are in HTML tags, so this will extract that id to form proper links\r\n if (id.includes(\" {\r\n // let section = entry.item.section;\r\n // if (!sResults.includes(section)) sResults.push(section);\r\n // });\r\n // setSectionResults(sResults);\r\n }\r\n }, [searchParams, dataArray]);\r\n\r\n if (loading) {\r\n // if still fetching resource\r\n return
\r\n \r\n {/* Filters */}\r\n \r\n {/* Keeping sections commented out just in case */}\r\n {/* */}\r\n {/* {sectionResultsList &&
Suggestions based on your search
}\r\n
{sectionResultsList}
*/}\r\n
\r\n \r\n\r\n \r\n {resultsList ? (\r\n
\r\n \r\n
Search Results
\r\n
{resultsList}
\r\n
\r\n ) : searchParams.searchTerm ? (\r\n
\r\n \r\n
No results found.
\r\n
\r\n ) : (\r\n \r\n )}\r\n \r\n\r\n \r\n
\r\n );\r\n}\r\n\r\nexport default App;\r\n","export default __webpack_public_path__ + \"static/media/sun.d499a97b.png\";","export default __webpack_public_path__ + \"static/media/moon.6ad80c47.png\";","const reportWebVitals = onPerfEntry => {\r\n if (onPerfEntry && onPerfEntry instanceof Function) {\r\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\r\n getCLS(onPerfEntry);\r\n getFID(onPerfEntry);\r\n getFCP(onPerfEntry);\r\n getLCP(onPerfEntry);\r\n getTTFB(onPerfEntry);\r\n });\r\n }\r\n};\r\n\r\nexport default reportWebVitals;\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './App.css';\r\nimport App from './App';\r\nimport reportWebVitals from './reportWebVitals';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n"],"sourceRoot":""}
\ No newline at end of file
diff --git a/static/js/main.c2bca8c9.chunk.js b/static/js/main.c2bca8c9.chunk.js
deleted file mode 100644
index 16e3bcf..0000000
--- a/static/js/main.c2bca8c9.chunk.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(this.webpackJsonpfpb_search_page=this.webpackJsonpfpb_search_page||[]).push([[0],{28:function(e,t,r){},49:function(e,t,r){"use strict";r.r(t);var n=r(1),o=r.n(n),c=r(20),a=r.n(c),s=(r(28),r(21)),i=r(5),l=r(4),h=r(2),b=r(11),j=r.n(b),u=r(22),d=r.n(u),g=r(23),m=r(0);var f=function(e){var t,r=e.changeParameter,o=e.data,c=Object(n.useState)([]),a=Object(h.a)(c,2),s=a[0],i=a[1],l=Object(n.useState)(""),b=Object(h.a)(l,2),j=b[0],u=b[1],d=Object(n.useState)(!1),g=Object(h.a)(d,2),f=g[0],O=g[1],p=function(e){r("lang.code",e.target.value),u(e.target.value)};Object(n.useEffect)((function(){if(o){var e=[{code:"en",name:"English"}];o.children[0].children.forEach((function(t){"string"===typeof t.language.name&&t.language.name.length>0&&"en"!==t.language.code&&e.push(t.language)})),e.sort((function(e,t){return e.name>t.name})),i(e)}}),[o]),t=s&&s.map((function(e){return function(e){return Object(m.jsx)("div",{children:Object(m.jsxs)("label",{children:[Object(m.jsx)("input",{type:"radio",className:"lang",value:e.code,onChange:p,checked:e.code==j},e.code),e.name]})})}(e)}));var x=Object(m.jsxs)("form",{class:"filters",children:[Object(m.jsxs)("label",{children:[Object(m.jsx)("input",{type:"radio",className:"sect-select",value:"",onChange:p,checked:""==j}),"All Languages"]}),t]});return Object(m.jsxs)("div",{className:"langFilters",children:[Object(m.jsxs)("div",{className:"filterHeader",children:[Object(m.jsx)("h3",{children:"Filter by Language"}),Object(m.jsx)("button",{onClick:function(){return O(!f)},children:f?"-":"+"})]}),f?x:""]})};var O=function(e){return Object(m.jsx)("form",{onSubmit:function(e){e.preventDefault()},name:"searchBar",className:"searchbar",children:Object(m.jsx)("input",{autoComplete:"off",type:"text",name:"searchTerm",placeholder:"Search Book or Author",className:"searchterm",onChange:function(t){e.changeParameter("title",t.target.value)}})})};var p=function(e){var t=e.data;return Object(m.jsx)("li",{class:"result",children:Object(m.jsxs)("a",{href:t.url,target:"_blank",rel:"noreferrer",children:["(",t.lang.code,") ",t.title,t.author?" by ".concat(t.author):""]})})};var x=function(){return Object(m.jsxs)("section",{children:[Object(m.jsx)("br",{}),Object(m.jsx)("h1",{id:"list-of-free-learning-resources-in-many-languages",children:"List of Free Learning Resources In Many Languages"}),Object(m.jsx)("div",{align:"center"}),Object(m.jsx)("h2",{id:"intro",children:"Intro"}),Object(m.jsxs)("p",{children:["This list was originally a clone of"," ",Object(m.jsx)("a",{href:"https://web.archive.org/web/20140606191453/http://stackoverflow.com/questions/194812/list-of-freely-available-programming-books/392926",children:"StackOverflow - List of Freely Available Programming Books"})," ","with contributions from Karan Bhangui and George Stocker."]}),Object(m.jsxs)("p",{children:["The list was moved to GitHub by Victor Felder for collaborative updating and maintenance. It has grown to become one of ",Object(m.jsx)("a",{href:"https://octoverse.github.com/",children:"GitHub\u2019s most popular repositories"}),", with 221,000+ stars, 6,900+ commits, 1,900+ contributors, and 47,100+ forks."]}),Object(m.jsxs)("p",{children:["The ",Object(m.jsx)("a",{href:"https://ebookfoundation.org",children:"Free Ebook Foundation"})," now administers the repo, a not-for-profit organization devoted to promoting the creation, distribution, archiving, and sustainability of free ebooks."," ",Object(m.jsx)("a",{href:"https://ebookfoundation.org/contributions.html",children:"Donations"})," to the Free Ebook Foundation are tax-deductible in the US."]}),Object(m.jsx)("h2",{id:"how-to-contribute",children:"How To Contribute"}),Object(m.jsxs)("p",{children:["Please read ",Object(m.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html",children:"CONTRIBUTING"}),". If you\u2019re new to GitHub,"," ",Object(m.jsx)("a",{href:"/free-programming-books/docs/HOWTO.html",children:"welcome"}),"! Remember to abide by our"," ",Object(m.jsx)("a",{href:"/free-programming-books/docs/CODE_OF_CONDUCT.html",children:"Code of Conduct"})," too. (",Object(m.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"translations"})," also available)"]}),Object(m.jsx)("h2",{id:"how-to-share",children:"How to Share"}),Object(m.jsxs)("ul",{children:[Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"http://twitter.com/intent/tweet?text=https://github.com/EbookFoundation/free-programming-books%0AFree%20Programming%20Books",children:"Share on Twitter"})}),Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"https://www.facebook.com/share.php?u=https%3A%2F%2Fgithub.com%2FEbookFoundation%2Ffree-programming-books&p%5Bimages%5D%5B0%5D=&p%5Btitle%5D=Free%20Programming%20Books&p%5Bsummary%5D=",children:"Share on Facebook"})}),Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"http://www.linkedin.com/shareArticle?mini=true&url=https://github.com/EbookFoundation/free-programming-books&title=Free%20Programming%20Books&summary=&source=",children:"Share on LinkedIn"})}),Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"https://t.me/share/url?url=https://github.com/EbookFoundation/free-programming-books",children:"Share on Telegram"})})]}),Object(m.jsx)("h2",{id:"translations",children:"Translations"}),Object(m.jsx)("p",{children:"Volunteers have translated many of our Contributing, How-to, and Code of Conduct documents into languages covered by our lists."}),Object(m.jsxs)("ul",{children:[Object(m.jsxs)("li",{children:["English",Object(m.jsxs)("ul",{children:[Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"/free-programming-books/docs/CODE_OF_CONDUCT.html",children:"Code of Conduct"})}),Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html",children:"Contributing"})}),Object(m.jsx)("li",{children:Object(m.jsx)("a",{href:"/free-programming-books/docs/HOWTO.html",children:"How-to"})})]})]}),Object(m.jsxs)("li",{children:["\u2026"," ",Object(m.jsx)("em",{children:Object(m.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"More languages"})})," ","\u2026"]})]}),Object(m.jsxs)("p",{children:["You might notice that there are"," ",Object(m.jsx)("a",{href:"/free-programming-books/docs/#translations",children:"some missing translations here"})," - perhaps you would like to help out by"," ",Object(m.jsx)("a",{href:"/free-programming-books/docs/CONTRIBUTING.html#help-out-by-contributing-a-translation",children:"contributing a translation"}),"?"]}),Object(m.jsx)("h2",{id:"license",children:"License"}),Object(m.jsxs)("p",{children:["Each file included in this repository is licensed under the"," ",Object(m.jsx)("a",{href:"/free-programming-books/LICENSE",children:"CC BY License"}),"."]})]})},k=(r.p,r.p,null);function v(e){var t=[],r=[];return e.children[0].children.forEach((function(e){e.sections.forEach((function(n){r.includes(n.section)||r.push(n.section),n.entries.forEach((function(r){t.push({author:r.author,title:r.title,url:r.url,lang:e.language,section:n.section})})),n.subsections.forEach((function(r){r.entries.forEach((function(o){t.push({author:o.author,title:o.title,url:o.url,lang:e.language,section:n.section,subsection:r.section})}))}))}))})),{arr:t,sections:r}}var w=function(){var e=Object(n.useState)(void 0),t=Object(h.a)(e,2),r=t[0],o=t[1],c=Object(n.useState)([]),a=Object(h.a)(c,2),b=a[0],u=a[1],w=Object(n.useState)([]),F=Object(h.a)(w,2),E=(F[0],F[1]),C=Object(n.useState)(!0),y=Object(h.a)(C,2),S=y[0],T=y[1],N=Object(n.useState)({title:""}),B=Object(h.a)(N,2),I=B[0],L=B[1],H=Object(n.useState)([]),_=Object(h.a)(H,2),P=_[0],D=_[1],A=Object(n.useState)([]),G=Object(h.a)(A,2),R=(G[0],G[1],Object(n.useState)(!0)),U=Object(h.a)(R,2),M=(U[0],U[1],Object(n.useState)("")),V=Object(h.a)(M,2),J=V[0],W=(V[1],null),Y=function(e,t){L(Object(l.a)(Object(l.a)({},I),{},Object(i.a)({},e,t)))};return Object(n.useEffect)((function(){function e(){return(e=Object(s.a)(j.a.mark((function e(){var t,r,n,c,a,s,i;return j.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,T(!0),e.next=4,d.a.get("https://raw.githubusercontent.com/FreeEbookFoundationBot/free-programming-books-json/main/fpb.json");case 4:t=e.sent,o(t.data),r=v(t.data),n=r.arr,c=r.sections,console.log(n),u(n),E(c),e.next=18;break;case 12:e.prev=12,e.t0=e.catch(0),o(k),a=v(k),s=a.arr,i=a.sections,E(i),u(s);case 18:T(!1);case 19:case"end":return e.stop()}}),e,null,[[0,12]])})))).apply(this,arguments)}!function(){e.apply(this,arguments)}()}),[]),Object(n.useEffect)((function(){if(b){for(var e=new g.a(b,{useExtendedSearch:!0,findAllMatches:!0,shouldSort:!0,includeScore:!0,threshold:.2,keys:["title","lang.code","section"]}),t=[],r=0,n=Object.entries(I);r {\r\n changeParameter(\"lang.code\", e.target.value);\r\n setSelected(e.target.value);\r\n };\r\n\r\n useEffect(\r\n // run whenever data changes\r\n () => {\r\n if (data) {\r\n let langArray = [{ code: \"en\", name: \"English\" }];\r\n data.children[0].children.forEach((document) => {\r\n if (typeof document.language.name === \"string\" && document.language.name.length > 0) {\r\n //make sure the language is valid and not blank\r\n //console.log(\"LANGUAGE: \" + document.language.name)\r\n if (document.language.code !== \"en\") {\r\n // used to ensure only one English is listed\r\n langArray.push(document.language);\r\n }\r\n }\r\n });\r\n langArray.sort((a, b) => a.name > b.name);\r\n setLanguages(langArray);\r\n }\r\n },\r\n [data]\r\n );\r\n\r\n const createOption = (language) => {\r\n return (\r\n
\r\n The list was moved to GitHub by Victor Felder for collaborative updating and maintenance. It has grown to become\r\n one of GitHub’s most popular repositories, with 221,000+ stars,\r\n 6,900+ commits, 1,900+ contributors, and 47,100+ forks.\r\n
\r\n\r\n
\r\n The Free Ebook Foundation now administers the repo, a not-for-profit\r\n organization devoted to promoting the creation, distribution, archiving, and sustainability of free ebooks.{\" \"}\r\n Donations to the Free Ebook Foundation are\r\n tax-deductible in the US.\r\n
\r\n Each file included in this repository is licensed under the{\" \"}\r\n CC BY License.\r\n
\r\n \r\n );\r\n}\r\n\r\nexport default Default;\r\n","import React, { useState, useEffect } from \"react\";\r\nimport axios from \"axios\";\r\nimport Fuse from \"fuse.js\";\r\n\r\nimport LangFilters from \"./components/LangFilters\";\r\nimport SectDropdown from \"./components/SectDropdown\";\r\nimport SearchBar from \"./components/SearchBar\";\r\nimport SearchResult from \"./components/SearchResult\";\r\nimport LightSwitch from \"./components/LightSwitch\";\r\nimport Default from \"./components/Default\";\r\n\r\nimport SunImg from \"./img/sun.png\";\r\nimport MoonImg from \"./img/moon.png\";\r\n\r\nconst fpb = null;\r\n\r\n// eslint-disable-next-line\r\nfunction makeBook(author, hLang, cLang, title, url) {\r\n //returns a struct with basic book info (author, human language, computer language, book title, url)\r\n return {\r\n author: author,\r\n hLang: hLang, //human language\r\n cLang: cLang, //computer language\r\n title: title,\r\n url: url,\r\n };\r\n}\r\n\r\n// eslint-disable-next-line\r\nfunction forEachBook(func, json) {\r\n //Runs func on each section, entry, and book in json, which is a list of entries\r\n if (typeof func !== \"function\") {\r\n // eslint-disable-next-line\r\n throw \"ERROR in forEachBook: parameter not a fucntion\";\r\n }\r\n\r\n for (const hLang in json) {\r\n //for each human language\r\n if (Array.isArray(hLang.sections)) {\r\n //check if sections is an array\r\n hLang.sections.forEach(\r\n (\r\n cLang //for each computer lanuage\r\n ) => {\r\n if (Array.isArray(cLang.entries)) {\r\n //verify is entries is an array\r\n cLang.entries.forEach(\r\n (\r\n book //for each book\r\n ) => {\r\n if (typeof book === \"object\") {\r\n //verify that book is an object\r\n func(json[hLang], cLang, book); //run the function\r\n }\r\n }\r\n );\r\n }\r\n }\r\n );\r\n }\r\n }\r\n}\r\n\r\n// Sorts search results by their score\r\n// eslint-disable-next-line\r\nfunction sortByScore(results) {\r\n results.sort(function (a, b) {\r\n return a.score - b.score;\r\n });\r\n return results;\r\n}\r\n\r\nfunction jsonToArray(json) {\r\n let arr = [];\r\n let sections = [];\r\n json.children[0].children.forEach((document) => {\r\n document.sections.forEach((section) => {\r\n if (!sections.includes(section.section)) sections.push(section.section);\r\n section.entries.forEach((entry) => {\r\n arr.push({\r\n author: entry.author,\r\n title: entry.title,\r\n url: entry.url,\r\n lang: document.language,\r\n section: section.section,\r\n });\r\n });\r\n section.subsections.forEach((subsection) => {\r\n subsection.entries.forEach((entry) => {\r\n arr.push({\r\n author: entry.author,\r\n title: entry.title,\r\n url: entry.url,\r\n lang: document.language,\r\n section: section.section,\r\n subsection: subsection.section,\r\n });\r\n });\r\n });\r\n });\r\n });\r\n return { arr: arr, sections: sections };\r\n}\r\n\r\nfunction App() {\r\n const [data, setData] = useState(undefined); // keeps the state of the json\r\n const [dataArray, setDataArray] = useState([]); // put everything into one array. uses more memory, but search is faster and less complex\r\n // eslint-disable-next-line\r\n const [index, setIndex] = useState([]); // used for \"table of contents\". currently unused\r\n const [loading, setLoading] = useState(true); // Determines whether to show spinner\r\n const [searchParams, setSearchParams] = useState({ title: \"\" });\r\n const [searchResults, setSearchResults] = useState([]);\r\n const [sectionResults, setSectionResults] = useState([]);\r\n const [lightMode, setLightMode] = useState(true);\r\n\r\n // eslint-disable-next-line\r\n const [error, setError] = useState(\"\");\r\n\r\n let resultsList = null; // the html string containing the search results\r\n let sectionResultsList = null;\r\n\r\n const changeParameter = (param, value) => {\r\n // Lets a child component set the value of the search term\r\n setSearchParams({ ...searchParams, [param]: value });\r\n };\r\n\r\n // fetches data the first time the page renders\r\n useEffect(() => {\r\n async function fetchData() {\r\n try {\r\n setLoading(true);\r\n let result = await axios.get(\r\n \"https://raw.githubusercontent.com/FreeEbookFoundationBot/free-programming-books-json/main/fpb.json\"\r\n );\r\n setData(result.data);\r\n let { arr, sections } = jsonToArray(result.data);\r\n console.log(arr);\r\n setDataArray(arr);\r\n setIndex(sections);\r\n } catch (e) {\r\n // setError(\"Couldn't get data. Please try again later\")\r\n setData(fpb);\r\n let { arr, sections } = jsonToArray(fpb);\r\n setIndex(sections);\r\n setDataArray(arr);\r\n }\r\n setLoading(false);\r\n }\r\n fetchData();\r\n }, []);\r\n\r\n // fires when searchTerm changes\r\n // THIS IS THE MAIN SEARCH FUNCTION CURRENTLY\r\n useEffect(() => {\r\n if (dataArray) {\r\n // Finds most relevant titles\r\n const fuseOptions = {\r\n useExtendedSearch: true,\r\n findAllMatches: true,\r\n shouldSort: true,\r\n includeScore: true,\r\n threshold: 0.2,\r\n keys: [\"title\", \"lang.code\", \"section\"],\r\n };\r\n\r\n let fuse = new Fuse(dataArray, fuseOptions);\r\n let query = [];\r\n for (const [key, value] of Object.entries(searchParams)) {\r\n if (value === null || value === \"\") continue;\r\n if (key === \"lang.code\") {\r\n query.push({ \"lang.code\": `^${value}` });\r\n continue;\r\n }\r\n if (key === \"section\") {\r\n query.push({ section: `^${value}` });\r\n continue;\r\n }\r\n query.push({ [key]: value });\r\n }\r\n let result = fuse.search({\r\n $and: query,\r\n });\r\n result = result.slice(0, 40);\r\n\r\n // Goes through the list of results\r\n let relevantLists = [];\r\n result.forEach((entry) => {\r\n // Checks if a new entry has already been made with the given programming language and human language.\r\n let obj = relevantLists.find(\r\n (o) => o.item.section === entry.item.section && o.item.lang.code === entry.item.lang.code\r\n );\r\n if (!obj && entry.item.lang.code) {\r\n let langCode = entry.item.lang.code;\r\n let section = entry.item.section;\r\n // English is split into the subjects and langs file. The parser flags which type of entry it is to use here\r\n if (langCode === \"en\") {\r\n if (entry.item.lang.isSubject) {\r\n langCode = \"subjects\";\r\n } else {\r\n langCode = \"langs\";\r\n }\r\n }\r\n\r\n let id = entry.item.section;\r\n \r\n // Some ids are in HTML tags, so this will extract that id to form proper links\r\n if (id.includes(\" {\r\n // let section = entry.item.section;\r\n // if (!sResults.includes(section)) sResults.push(section);\r\n // });\r\n // setSectionResults(sResults);\r\n }\r\n }, [searchParams, dataArray]);\r\n\r\n if (loading) {\r\n // if still fetching resource\r\n return
\r\n \r\n {/* Filters */}\r\n \r\n {/* Keeping sections commented out just in case */}\r\n {/* */}\r\n {/* {sectionResultsList &&
Suggestions based on your search
}\r\n
{sectionResultsList}
*/}\r\n
\r\n \r\n\r\n \r\n {resultsList ? (\r\n
\r\n \r\n
Search Results
\r\n
{resultsList}
\r\n
\r\n ) : searchParams.title ? (\r\n
\r\n \r\n
No results found.
\r\n
\r\n ) : (\r\n \r\n )}\r\n \r\n\r\n \r\n
\r\n );\r\n}\r\n\r\nexport default App;\r\n","export default __webpack_public_path__ + \"static/media/sun.d499a97b.png\";","export default __webpack_public_path__ + \"static/media/moon.6ad80c47.png\";","const reportWebVitals = onPerfEntry => {\r\n if (onPerfEntry && onPerfEntry instanceof Function) {\r\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\r\n getCLS(onPerfEntry);\r\n getFID(onPerfEntry);\r\n getFCP(onPerfEntry);\r\n getLCP(onPerfEntry);\r\n getTTFB(onPerfEntry);\r\n });\r\n }\r\n};\r\n\r\nexport default reportWebVitals;\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './App.css';\r\nimport App from './App';\r\nimport reportWebVitals from './reportWebVitals';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n"],"sourceRoot":""}
\ No newline at end of file