Siden findes ikke
-Hov!
-Der er vidst gået noget galt. Prøv at gå tilbage til forsiden
- - - -diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index ba7735c..0000000 --- a/docs/404.html +++ /dev/null @@ -1,606 +0,0 @@ - -
- - - - - - - -Hvilke værktøjer skal vi bruge og hvordan spiller de sammen?
- - - - -@online{bang-larsen2024,
- author = {Bang-Larsen, Aleksander},
- title = {Hvordan laver man en hjemmeside med Quarto?},
- date = {2024-05-15},
- url = {https://aleksanderbl.dk/guides/quarto-blog},
- langid = {da}
-}
-
${missingFields[0]}
field.`,
- message: `The items being returned for this search do not include all the required fields. Please ensure that your index items include the ${missingFields[0]}
field or use index-fields
in your _quarto.yml
file to specify the field names.`,
- };
- } else if (missingFields.length > 1) {
- const missingFieldList = missingFields
- .map((field) => {
- return `${field}
`;
- })
- .join(", ");
-
- throw {
- name: `Error: Search index is missing the following fields: ${missingFieldList}.`,
- message: `The items being returned for this search do not include all the required fields. Please ensure that your index items includes the following fields: ${missingFieldList}, or use index-fields
in your _quarto.yml
file to specify the field names.`,
- };
- }
- }
-}
-
-let lastQuery = null;
-function showCopyLink(query, options) {
- const language = options.language;
- lastQuery = query;
- // Insert share icon
- const inputSuffixEl = window.document.body.querySelector(
- ".aa-Form .aa-InputWrapperSuffix"
- );
-
- if (inputSuffixEl) {
- let copyButtonEl = window.document.body.querySelector(
- ".aa-Form .aa-InputWrapperSuffix .aa-CopyButton"
- );
-
- if (copyButtonEl === null) {
- copyButtonEl = window.document.createElement("button");
- copyButtonEl.setAttribute("class", "aa-CopyButton");
- copyButtonEl.setAttribute("type", "button");
- copyButtonEl.setAttribute("title", language["search-copy-link-title"]);
- copyButtonEl.onmousedown = (e) => {
- e.preventDefault();
- e.stopPropagation();
- };
-
- const linkIcon = "bi-clipboard";
- const checkIcon = "bi-check2";
-
- const shareIconEl = window.document.createElement("i");
- shareIconEl.setAttribute("class", `bi ${linkIcon}`);
- copyButtonEl.appendChild(shareIconEl);
- inputSuffixEl.prepend(copyButtonEl);
-
- const clipboard = new window.ClipboardJS(".aa-CopyButton", {
- text: function (_trigger) {
- const copyUrl = new URL(window.location);
- copyUrl.searchParams.set(kQueryArg, lastQuery);
- copyUrl.searchParams.set(kResultsArg, "1");
- return copyUrl.toString();
- },
- });
- clipboard.on("success", function (e) {
- // Focus the input
-
- // button target
- const button = e.trigger;
- const icon = button.querySelector("i.bi");
-
- // flash "checked"
- icon.classList.add(checkIcon);
- icon.classList.remove(linkIcon);
- setTimeout(function () {
- icon.classList.remove(checkIcon);
- icon.classList.add(linkIcon);
- }, 1000);
- });
- }
-
- // If there is a query, show the link icon
- if (copyButtonEl) {
- if (lastQuery && options["copy-button"]) {
- copyButtonEl.style.display = "flex";
- } else {
- copyButtonEl.style.display = "none";
- }
- }
- }
-}
-
-/* Search Index Handling */
-// create the index
-var fuseIndex = undefined;
-var shownWarning = false;
-
-// fuse index options
-const kFuseIndexOptions = {
- keys: [
- { name: "title", weight: 20 },
- { name: "section", weight: 20 },
- { name: "text", weight: 10 },
- ],
- ignoreLocation: true,
- threshold: 0.1,
-};
-
-async function readSearchData() {
- // Initialize the search index on demand
- if (fuseIndex === undefined) {
- if (window.location.protocol === "file:" && !shownWarning) {
- window.alert(
- "Search requires JavaScript features disabled when running in file://... URLs. In order to use search, please run this document in a web server."
- );
- shownWarning = true;
- return;
- }
- const fuse = new window.Fuse([], kFuseIndexOptions);
-
- // fetch the main search.json
- const response = await fetch(offsetURL("search.json"));
- if (response.status == 200) {
- return response.json().then(function (searchDocs) {
- searchDocs.forEach(function (searchDoc) {
- fuse.add(searchDoc);
- });
- fuseIndex = fuse;
- return fuseIndex;
- });
- } else {
- return Promise.reject(
- new Error(
- "Unexpected status from search index request: " + response.status
- )
- );
- }
- }
-
- return fuseIndex;
-}
-
-function inputElement() {
- return window.document.body.querySelector(".aa-Form .aa-Input");
-}
-
-function focusSearchInput() {
- setTimeout(() => {
- const inputEl = inputElement();
- if (inputEl) {
- inputEl.focus();
- }
- }, 50);
-}
-
-/* Panels */
-const kItemTypeDoc = "document";
-const kItemTypeMore = "document-more";
-const kItemTypeItem = "document-item";
-const kItemTypeError = "error";
-
-function renderItem(
- item,
- createElement,
- state,
- setActiveItemId,
- setContext,
- refresh,
- quartoSearchOptions
-) {
- switch (item.type) {
- case kItemTypeDoc:
- return createDocumentCard(
- createElement,
- "file-richtext",
- item.title,
- item.section,
- item.text,
- item.href,
- item.crumbs,
- quartoSearchOptions
- );
- case kItemTypeMore:
- return createMoreCard(
- createElement,
- item,
- state,
- setActiveItemId,
- setContext,
- refresh
- );
- case kItemTypeItem:
- return createSectionCard(
- createElement,
- item.section,
- item.text,
- item.href
- );
- case kItemTypeError:
- return createErrorCard(createElement, item.title, item.text);
- default:
- return undefined;
- }
-}
-
-function createDocumentCard(
- createElement,
- icon,
- title,
- section,
- text,
- href,
- crumbs,
- quartoSearchOptions
-) {
- const iconEl = createElement("i", {
- class: `bi bi-${icon} search-result-icon`,
- });
- const titleEl = createElement("p", { class: "search-result-title" }, title);
- const titleContents = [iconEl, titleEl];
- const showParent = quartoSearchOptions["show-item-context"];
- if (crumbs && showParent) {
- let crumbsOut = undefined;
- const crumbClz = ["search-result-crumbs"];
- if (showParent === "root") {
- crumbsOut = crumbs.length > 1 ? crumbs[0] : undefined;
- } else if (showParent === "parent") {
- crumbsOut = crumbs.length > 1 ? crumbs[crumbs.length - 2] : undefined;
- } else {
- crumbsOut = crumbs.length > 1 ? crumbs.join(" > ") : undefined;
- crumbClz.push("search-result-crumbs-wrap");
- }
-
- const crumbEl = createElement(
- "p",
- { class: crumbClz.join(" ") },
- crumbsOut
- );
- titleContents.push(crumbEl);
- }
-
- const titleContainerEl = createElement(
- "div",
- { class: "search-result-title-container" },
- titleContents
- );
-
- const textEls = [];
- if (section) {
- const sectionEl = createElement(
- "p",
- { class: "search-result-section" },
- section
- );
- textEls.push(sectionEl);
- }
- const descEl = createElement("p", {
- class: "search-result-text",
- dangerouslySetInnerHTML: {
- __html: text,
- },
- });
- textEls.push(descEl);
-
- const textContainerEl = createElement(
- "div",
- { class: "search-result-text-container" },
- textEls
- );
-
- const containerEl = createElement(
- "div",
- {
- class: "search-result-container",
- },
- [titleContainerEl, textContainerEl]
- );
-
- const linkEl = createElement(
- "a",
- {
- href: offsetURL(href),
- class: "search-result-link",
- },
- containerEl
- );
-
- const classes = ["search-result-doc", "search-item"];
- if (!section) {
- classes.push("document-selectable");
- }
-
- return createElement(
- "div",
- {
- class: classes.join(" "),
- },
- linkEl
- );
-}
-
-function createMoreCard(
- createElement,
- item,
- state,
- setActiveItemId,
- setContext,
- refresh
-) {
- const moreCardEl = createElement(
- "div",
- {
- class: "search-result-more search-item",
- onClick: (e) => {
- // Handle expanding the sections by adding the expanded
- // section to the list of expanded sections
- toggleExpanded(item, state, setContext, setActiveItemId, refresh);
- e.stopPropagation();
- },
- },
- item.title
- );
-
- return moreCardEl;
-}
-
-function toggleExpanded(item, state, setContext, setActiveItemId, refresh) {
- const expanded = state.context.expanded || [];
- if (expanded.includes(item.target)) {
- setContext({
- expanded: expanded.filter((target) => target !== item.target),
- });
- } else {
- setContext({ expanded: [...expanded, item.target] });
- }
-
- refresh();
- setActiveItemId(item.__autocomplete_id);
-}
-
-function createSectionCard(createElement, section, text, href) {
- const sectionEl = createSection(createElement, section, text, href);
- return createElement(
- "div",
- {
- class: "search-result-doc-section search-item",
- },
- sectionEl
- );
-}
-
-function createSection(createElement, title, text, href) {
- const descEl = createElement("p", {
- class: "search-result-text",
- dangerouslySetInnerHTML: {
- __html: text,
- },
- });
-
- const titleEl = createElement("p", { class: "search-result-section" }, title);
- const linkEl = createElement(
- "a",
- {
- href: offsetURL(href),
- class: "search-result-link",
- },
- [titleEl, descEl]
- );
- return linkEl;
-}
-
-function createErrorCard(createElement, title, text) {
- const descEl = createElement("p", {
- class: "search-error-text",
- dangerouslySetInnerHTML: {
- __html: text,
- },
- });
-
- const titleEl = createElement("p", {
- class: "search-error-title",
- dangerouslySetInnerHTML: {
- __html: ` ${title}`,
- },
- });
- const errorEl = createElement("div", { class: "search-error" }, [
- titleEl,
- descEl,
- ]);
- return errorEl;
-}
-
-function positionPanel(pos) {
- const panelEl = window.document.querySelector(
- "#quarto-search-results .aa-Panel"
- );
- const inputEl = window.document.querySelector(
- "#quarto-search .aa-Autocomplete"
- );
-
- if (panelEl && inputEl) {
- panelEl.style.top = `${Math.round(panelEl.offsetTop)}px`;
- if (pos === "start") {
- panelEl.style.left = `${Math.round(inputEl.left)}px`;
- } else {
- panelEl.style.right = `${Math.round(inputEl.offsetRight)}px`;
- }
- }
-}
-
-/* Highlighting */
-// highlighting functions
-function highlightMatch(query, text) {
- if (text) {
- const start = text.toLowerCase().indexOf(query.toLowerCase());
- if (start !== -1) {
- const startMark = "";
- const endMark = "";
-
- const end = start + query.length;
- text =
- text.slice(0, start) +
- startMark +
- text.slice(start, end) +
- endMark +
- text.slice(end);
- const startInfo = clipStart(text, start);
- const endInfo = clipEnd(
- text,
- startInfo.position + startMark.length + endMark.length
- );
- text =
- startInfo.prefix +
- text.slice(startInfo.position, endInfo.position) +
- endInfo.suffix;
-
- return text;
- } else {
- return text;
- }
- } else {
- return text;
- }
-}
-
-function clipStart(text, pos) {
- const clipStart = pos - 50;
- if (clipStart < 0) {
- // This will just return the start of the string
- return {
- position: 0,
- prefix: "",
- };
- } else {
- // We're clipping before the start of the string, walk backwards to the first space.
- const spacePos = findSpace(text, pos, -1);
- return {
- position: spacePos.position,
- prefix: "",
- };
- }
-}
-
-function clipEnd(text, pos) {
- const clipEnd = pos + 200;
- if (clipEnd > text.length) {
- return {
- position: text.length,
- suffix: "",
- };
- } else {
- const spacePos = findSpace(text, clipEnd, 1);
- return {
- position: spacePos.position,
- suffix: spacePos.clipped ? "…" : "",
- };
- }
-}
-
-function findSpace(text, start, step) {
- let stepPos = start;
- while (stepPos > -1 && stepPos < text.length) {
- const char = text[stepPos];
- if (char === " " || char === "," || char === ":") {
- return {
- position: step === 1 ? stepPos : stepPos - step,
- clipped: stepPos > 1 && stepPos < text.length,
- };
- }
- stepPos = stepPos + step;
- }
-
- return {
- position: stepPos - step,
- clipped: false,
- };
-}
-
-// removes highlighting as implemented by the mark tag
-function clearHighlight(searchterm, el) {
- const childNodes = el.childNodes;
- for (let i = childNodes.length - 1; i >= 0; i--) {
- const node = childNodes[i];
- if (node.nodeType === Node.ELEMENT_NODE) {
- if (
- node.tagName === "MARK" &&
- node.innerText.toLowerCase() === searchterm.toLowerCase()
- ) {
- el.replaceChild(document.createTextNode(node.innerText), node);
- } else {
- clearHighlight(searchterm, node);
- }
- }
- }
-}
-
-function escapeRegExp(string) {
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
-}
-
-// highlight matches
-function highlight(term, el) {
- const termRegex = new RegExp(term, "ig");
- const childNodes = el.childNodes;
-
- // walk back to front avoid mutating elements in front of us
- for (let i = childNodes.length - 1; i >= 0; i--) {
- const node = childNodes[i];
-
- if (node.nodeType === Node.TEXT_NODE) {
- // Search text nodes for text to highlight
- const text = node.nodeValue;
-
- let startIndex = 0;
- let matchIndex = text.search(termRegex);
- if (matchIndex > -1) {
- const markFragment = document.createDocumentFragment();
- while (matchIndex > -1) {
- const prefix = text.slice(startIndex, matchIndex);
- markFragment.appendChild(document.createTextNode(prefix));
-
- const mark = document.createElement("mark");
- mark.appendChild(
- document.createTextNode(
- text.slice(matchIndex, matchIndex + term.length)
- )
- );
- markFragment.appendChild(mark);
-
- startIndex = matchIndex + term.length;
- matchIndex = text.slice(startIndex).search(new RegExp(term, "ig"));
- if (matchIndex > -1) {
- matchIndex = startIndex + matchIndex;
- }
- }
- if (startIndex < text.length) {
- markFragment.appendChild(
- document.createTextNode(text.slice(startIndex, text.length))
- );
- }
-
- el.replaceChild(markFragment, node);
- }
- } else if (node.nodeType === Node.ELEMENT_NODE) {
- // recurse through elements
- highlight(term, node);
- }
- }
-}
-
-/* Link Handling */
-// get the offset from this page for a given site root relative url
-function offsetURL(url) {
- var offset = getMeta("quarto:offset");
- return offset ? offset + url : url;
-}
-
-// read a meta tag value
-function getMeta(metaName) {
- var metas = window.document.getElementsByTagName("meta");
- for (let i = 0; i < metas.length; i++) {
- if (metas[i].getAttribute("name") === metaName) {
- return metas[i].getAttribute("content");
- }
- }
- return "";
-}
-
-function algoliaSearch(query, limit, algoliaOptions) {
- const { getAlgoliaResults } = window["@algolia/autocomplete-preset-algolia"];
-
- const applicationId = algoliaOptions["application-id"];
- const searchOnlyApiKey = algoliaOptions["search-only-api-key"];
- const indexName = algoliaOptions["index-name"];
- const indexFields = algoliaOptions["index-fields"];
- const searchClient = window.algoliasearch(applicationId, searchOnlyApiKey);
- const searchParams = algoliaOptions["params"];
- const searchAnalytics = !!algoliaOptions["analytics-events"];
-
- return getAlgoliaResults({
- searchClient,
- queries: [
- {
- indexName: indexName,
- query,
- params: {
- hitsPerPage: limit,
- clickAnalytics: searchAnalytics,
- ...searchParams,
- },
- },
- ],
- transformResponse: (response) => {
- if (!indexFields) {
- return response.hits.map((hit) => {
- return hit.map((item) => {
- return {
- ...item,
- text: highlightMatch(query, item.text),
- };
- });
- });
- } else {
- const remappedHits = response.hits.map((hit) => {
- return hit.map((item) => {
- const newItem = { ...item };
- ["href", "section", "title", "text", "crumbs"].forEach(
- (keyName) => {
- const mappedName = indexFields[keyName];
- if (
- mappedName &&
- item[mappedName] !== undefined &&
- mappedName !== keyName
- ) {
- newItem[keyName] = item[mappedName];
- delete newItem[mappedName];
- }
- }
- );
- newItem.text = highlightMatch(query, newItem.text);
- return newItem;
- });
- });
- return remappedHits;
- }
- },
- });
-}
-
-let subSearchTerm = undefined;
-let subSearchFuse = undefined;
-const kFuseMaxWait = 125;
-
-async function fuseSearch(query, fuse, fuseOptions) {
- let index = fuse;
- // Fuse.js using the Bitap algorithm for text matching which runs in
- // O(nm) time (no matter the structure of the text). In our case this
- // means that long search terms mixed with large index gets very slow
- //
- // This injects a subIndex that will be used once the terms get long enough
- // Usually making this subindex is cheap since there will typically be
- // a subset of results matching the existing query
- if (subSearchFuse !== undefined && query.startsWith(subSearchTerm)) {
- // Use the existing subSearchFuse
- index = subSearchFuse;
- } else if (subSearchFuse !== undefined) {
- // The term changed, discard the existing fuse
- subSearchFuse = undefined;
- subSearchTerm = undefined;
- }
-
- // Search using the active fuse
- const then = performance.now();
- const resultsRaw = await index.search(query, fuseOptions);
- const now = performance.now();
-
- const results = resultsRaw.map((result) => {
- const addParam = (url, name, value) => {
- const anchorParts = url.split("#");
- const baseUrl = anchorParts[0];
- const sep = baseUrl.search("\\?") > 0 ? "&" : "?";
- anchorParts[0] = baseUrl + sep + name + "=" + value;
- return anchorParts.join("#");
- };
-
- return {
- title: result.item.title,
- section: result.item.section,
- href: addParam(result.item.href, kQueryArg, query),
- text: highlightMatch(query, result.item.text),
- crumbs: result.item.crumbs,
- };
- });
-
- // If we don't have a subfuse and the query is long enough, go ahead
- // and create a subfuse to use for subsequent queries
- if (now - then > kFuseMaxWait && subSearchFuse === undefined) {
- subSearchTerm = query;
- subSearchFuse = new window.Fuse([], kFuseIndexOptions);
- resultsRaw.forEach((rr) => {
- subSearchFuse.add(rr.item);
- });
- }
- return results;
-}
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
deleted file mode 100644
index c12eba6..0000000
--- a/docs/sitemap.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-+ ++ +```{=html} + +``` diff --git a/guides/2024-05-19-danmarkskort-i-r/index.qmd b/guides/2024-05-19-danmarkskort-i-r/index.qmd new file mode 100644 index 0000000..0613f47 --- /dev/null +++ b/guides/2024-05-19-danmarkskort-i-r/index.qmd @@ -0,0 +1,11 @@ +--- +title: Nemt Danmarkskort i R +citation: + url: https://aleksanderbl.dk/guides/2024-05-19-danmarkskort-i-r +bibliography: refs.bib +date: 2024-05-19 +--- + +## Baggrund + +Da jeg skulle lære at lave kort i R, lavede jeg et par hurtige googlesøgninger, hvor jeg kom frem til en god guide lavet af Mikkel Freltoft @krogsholm2021. Jeg opdagede dog hurtigt, at guiden er out-of-date (hvorfor jeg skriver denne guide). \ No newline at end of file diff --git a/guides/2024-05-19-danmarkskort-i-r/refs.bib b/guides/2024-05-19-danmarkskort-i-r/refs.bib new file mode 100644 index 0000000..1896d58 --- /dev/null +++ b/guides/2024-05-19-danmarkskort-i-r/refs.bib @@ -0,0 +1,9 @@ +@misc{krogsholm2021, + title = {Easy Maps of {{Denmark}} in {{R}} {\textbar} {{LinkedIn}}}, + author = {Krogsholm, Mikkel Freltoft}, + year = {2021}, + month = mar, + urldate = {2024-05-09}, + howpublished = {https://www.linkedin.com/pulse/easy-maps-denmark-r-mikkel-freltoft-krogsholm/}, + file = {/Users/aleksanderbang-larsen/Zotero/storage/BMXGZWRD/easy-maps-denmark-r-mikkel-freltoft-krogsholm.html} +} diff --git a/guides/_metadata.yml b/guides/_metadata.yml index 47835cd..3539f04 100644 --- a/guides/_metadata.yml +++ b/guides/_metadata.yml @@ -3,11 +3,11 @@ # freeze computational output # (see https://quarto.org/docs/projects/code-execution.html#freeze) -freeze: true +freeze: auto # Enable banner style title blocks title-block-banner: true # no table of contents -toc: false +toc: true author: "Aleksander Bang-Larsen"+ +When you've written the same code 3 times, write a function
+ +--- David Robinson (@drob) November 9, 2017 + +
When you've given the same in-person advice 3 times, write a blog post + +